Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
f6932f56
Commit
f6932f56
authored
Jun 16, 2003
by
Chas Williams
Committed by
David S. Miller
Jun 16, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[ATM]: Remove recvmsg and rename atm_async_release_vcc.
parent
e0380eac
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
400 additions
and
262 deletions
+400
-262
include/linux/atmdev.h
include/linux/atmdev.h
+1
-1
net/atm/clip.c
net/atm/clip.c
+2
-2
net/atm/common.c
net/atm/common.c
+125
-142
net/atm/common.h
net/atm/common.h
+8
-9
net/atm/lec.c
net/atm/lec.c
+2
-2
net/atm/mpoa_caches.c
net/atm/mpoa_caches.c
+2
-2
net/atm/pvc.c
net/atm/pvc.c
+42
-12
net/atm/signaling.c
net/atm/signaling.c
+7
-1
net/atm/svc.c
net/atm/svc.c
+211
-91
No files found.
include/linux/atmdev.h
View file @
f6932f56
...
@@ -452,7 +452,7 @@ struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
...
@@ -452,7 +452,7 @@ struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
int
atm_find_ci
(
struct
atm_vcc
*
vcc
,
short
*
vpi
,
int
*
vci
);
int
atm_find_ci
(
struct
atm_vcc
*
vcc
,
short
*
vpi
,
int
*
vci
);
int
atm_pcr_goal
(
struct
atm_trafprm
*
tp
);
int
atm_pcr_goal
(
struct
atm_trafprm
*
tp
);
void
atm_async_release_vcc
(
struct
atm_vcc
*
vcc
,
int
reply
);
void
vcc_release_async
(
struct
atm_vcc
*
vcc
,
int
reply
);
#endif
/* __KERNEL__ */
#endif
/* __KERNEL__ */
...
...
net/atm/clip.c
View file @
f6932f56
...
@@ -140,7 +140,7 @@ static void idle_timer_check(unsigned long dummy)
...
@@ -140,7 +140,7 @@ static void idle_timer_check(unsigned long dummy)
DPRINTK
(
"releasing vcc %p->%p of "
DPRINTK
(
"releasing vcc %p->%p of "
"entry %p
\n
"
,
clip_vcc
,
clip_vcc
->
vcc
,
"entry %p
\n
"
,
clip_vcc
,
clip_vcc
->
vcc
,
entry
);
entry
);
atm_async_release_vc
c
(
clip_vcc
->
vcc
,
vcc_release_asyn
c
(
clip_vcc
->
vcc
,
-
ETIMEDOUT
);
-
ETIMEDOUT
);
}
}
if
(
entry
->
vccs
||
if
(
entry
->
vccs
||
...
...
net/atm/common.c
View file @
f6932f56
...
@@ -239,15 +239,16 @@ int atm_release(struct socket *sock)
...
@@ -239,15 +239,16 @@ int atm_release(struct socket *sock)
}
}
void
atm_async_release_vcc
(
struct
atm_vcc
*
vcc
,
int
reply
)
void
vcc_release_async
(
struct
atm_vcc
*
vcc
,
int
reply
)
{
{
set_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
);
vcc
->
reply
=
reply
;
vcc
->
reply
=
reply
;
vcc
->
sk
->
sk_err
=
-
reply
;
wake_up
(
&
vcc
->
sleep
);
wake_up
(
&
vcc
->
sleep
);
}
}
EXPORT_SYMBOL
(
atm_async_release_vc
c
);
EXPORT_SYMBOL
(
vcc_release_asyn
c
);
static
int
adjust_tp
(
struct
atm_trafprm
*
tp
,
unsigned
char
aal
)
static
int
adjust_tp
(
struct
atm_trafprm
*
tp
,
unsigned
char
aal
)
...
@@ -276,7 +277,7 @@ static int adjust_tp(struct atm_trafprm *tp,unsigned char aal)
...
@@ -276,7 +277,7 @@ static int adjust_tp(struct atm_trafprm *tp,unsigned char aal)
}
}
static
int
atm_do_connect_dev
(
struct
atm_vcc
*
vcc
,
struct
atm_dev
*
dev
,
int
vpi
,
static
int
__vcc_connect
(
struct
atm_vcc
*
vcc
,
struct
atm_dev
*
dev
,
int
vpi
,
int
vci
)
int
vci
)
{
{
int
error
;
int
error
;
...
@@ -334,29 +335,26 @@ static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
...
@@ -334,29 +335,26 @@ static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
}
}
static
int
atm_do_connect
(
struct
atm_vcc
*
vcc
,
int
itf
,
int
vpi
,
int
vci
)
int
vcc_connect
(
struct
socket
*
sock
,
int
itf
,
short
vpi
,
int
vci
)
{
{
struct
atm_dev
*
dev
;
struct
atm_dev
*
dev
;
int
return_val
;
struct
atm_vcc
*
vcc
=
ATM_SD
(
sock
);
int
error
;
dev
=
atm_dev_lookup
(
itf
);
if
(
!
dev
)
return_val
=
-
ENODEV
;
else
{
return_val
=
atm_do_connect_dev
(
vcc
,
dev
,
vpi
,
vci
);
if
(
return_val
)
atm_dev_release
(
dev
);
}
return
return_val
;
}
DPRINTK
(
"vcc_connect (vpi %d, vci %d)
\n
"
,
vpi
,
vci
);
if
(
sock
->
state
==
SS_CONNECTED
)
return
-
EISCONN
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
return
-
EINVAL
;
if
(
!
(
vpi
||
vci
))
return
-
EINVAL
;
int
atm_connect_vcc
(
struct
atm_vcc
*
vcc
,
int
itf
,
short
vpi
,
int
vci
)
{
if
(
vpi
!=
ATM_VPI_UNSPEC
&&
vci
!=
ATM_VCI_UNSPEC
)
if
(
vpi
!=
ATM_VPI_UNSPEC
&&
vci
!=
ATM_VCI_UNSPEC
)
clear_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
);
else
if
(
test_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
))
return
-
EINVAL
;
else
DPRINTK
(
"atm_connect (TX: cl %d,bw %d-%d,sdu %d; "
if
(
test_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
))
return
-
EINVAL
;
DPRINTK
(
"vcc_connect (TX: cl %d,bw %d-%d,sdu %d; "
"RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)
\n
"
,
"RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)
\n
"
,
vcc
->
qos
.
txtp
.
traffic_class
,
vcc
->
qos
.
txtp
.
min_pcr
,
vcc
->
qos
.
txtp
.
traffic_class
,
vcc
->
qos
.
txtp
.
min_pcr
,
vcc
->
qos
.
txtp
.
max_pcr
,
vcc
->
qos
.
txtp
.
max_sdu
,
vcc
->
qos
.
txtp
.
max_pcr
,
vcc
->
qos
.
txtp
.
max_sdu
,
...
@@ -364,141 +362,135 @@ int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci)
...
@@ -364,141 +362,135 @@ int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci)
vcc
->
qos
.
rxtp
.
max_pcr
,
vcc
->
qos
.
rxtp
.
max_sdu
,
vcc
->
qos
.
rxtp
.
max_pcr
,
vcc
->
qos
.
rxtp
.
max_sdu
,
vcc
->
qos
.
aal
==
ATM_AAL5
?
""
:
vcc
->
qos
.
aal
==
ATM_AAL0
?
""
:
vcc
->
qos
.
aal
==
ATM_AAL5
?
""
:
vcc
->
qos
.
aal
==
ATM_AAL0
?
""
:
" ??? code "
,
vcc
->
qos
.
aal
==
ATM_AAL0
?
0
:
vcc
->
qos
.
aal
);
" ??? code "
,
vcc
->
qos
.
aal
==
ATM_AAL0
?
0
:
vcc
->
qos
.
aal
);
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
return
-
EBADFD
;
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
return
-
EBADFD
;
if
(
vcc
->
qos
.
txtp
.
traffic_class
==
ATM_ANYCLASS
||
if
(
vcc
->
qos
.
txtp
.
traffic_class
==
ATM_ANYCLASS
||
vcc
->
qos
.
rxtp
.
traffic_class
==
ATM_ANYCLASS
)
vcc
->
qos
.
rxtp
.
traffic_class
==
ATM_ANYCLASS
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
itf
!=
ATM_ITF_ANY
)
{
if
(
itf
!=
ATM_ITF_ANY
)
{
int
error
;
dev
=
atm_dev_lookup
(
itf
);
error
=
__vcc_connect
(
vcc
,
dev
,
vpi
,
vci
);
error
=
atm_do_connect
(
vcc
,
itf
,
vpi
,
vci
);
if
(
error
)
{
if
(
error
)
return
error
;
atm_dev_release
(
dev
);
return
error
;
}
}
else
{
}
else
{
struct
atm_dev
*
dev
=
NULL
;
struct
list_head
*
p
,
*
next
;
struct
list_head
*
p
,
*
next
;
dev
=
NULL
;
spin_lock
(
&
atm_dev_lock
);
spin_lock
(
&
atm_dev_lock
);
list_for_each_safe
(
p
,
next
,
&
atm_devs
)
{
list_for_each_safe
(
p
,
next
,
&
atm_devs
)
{
dev
=
list_entry
(
p
,
struct
atm_dev
,
dev_list
);
dev
=
list_entry
(
p
,
struct
atm_dev
,
dev_list
);
atm_dev_hold
(
dev
);
atm_dev_hold
(
dev
);
spin_unlock
(
&
atm_dev_lock
);
spin_unlock
(
&
atm_dev_lock
);
if
(
!
atm_do_connect_dev
(
vcc
,
dev
,
vpi
,
vci
))
if
(
!
__vcc_connect
(
vcc
,
dev
,
vpi
,
vci
))
break
;
break
;
atm_dev_release
(
dev
);
atm_dev_release
(
dev
);
dev
=
NULL
;
dev
=
NULL
;
spin_lock
(
&
atm_dev_lock
);
spin_lock
(
&
atm_dev_lock
);
}
}
spin_unlock
(
&
atm_dev_lock
);
spin_unlock
(
&
atm_dev_lock
);
if
(
!
dev
)
return
-
ENODEV
;
if
(
!
dev
)
return
-
ENODEV
;
}
}
if
(
vpi
==
ATM_VPI_UNSPEC
||
vci
==
ATM_VCI_UNSPEC
)
if
(
vpi
==
ATM_VPI_UNSPEC
||
vci
==
ATM_VCI_UNSPEC
)
set_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
);
return
0
;
}
int
atm_connect
(
struct
socket
*
sock
,
int
itf
,
short
vpi
,
int
vci
)
{
int
error
;
DPRINTK
(
"atm_connect (vpi %d, vci %d)
\n
"
,
vpi
,
vci
);
if
(
sock
->
state
==
SS_CONNECTED
)
return
-
EISCONN
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
return
-
EINVAL
;
if
(
!
(
vpi
||
vci
))
return
-
EINVAL
;
error
=
atm_connect_vcc
(
ATM_SD
(
sock
),
itf
,
vpi
,
vci
);
if
(
error
)
return
error
;
if
(
test_bit
(
ATM_VF_READY
,
&
ATM_SD
(
sock
)
->
flags
))
if
(
test_bit
(
ATM_VF_READY
,
&
ATM_SD
(
sock
)
->
flags
))
sock
->
state
=
SS_CONNECTED
;
sock
->
state
=
SS_CONNECTED
;
return
0
;
return
0
;
}
}
int
atm_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
vcc_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
total_len
,
int
flags
)
int
size
,
int
flags
)
{
{
DECLARE_WAITQUEUE
(
wait
,
current
)
;
struct
sock
*
sk
=
sock
->
sk
;
struct
atm_vcc
*
vcc
;
struct
atm_vcc
*
vcc
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
int
eff_len
,
error
;
int
copied
,
error
=
-
EINVAL
;
void
*
buff
;
int
size
;
if
(
sock
->
state
!=
SS_CONNECTED
)
return
-
ENOTCONN
;
if
(
sock
->
state
!=
SS_CONNECTED
)
if
(
flags
&
~
MSG_DONTWAIT
)
return
-
EOPNOTSUPP
;
return
-
ENOTCONN
;
if
(
m
->
msg_iovlen
!=
1
)
return
-
ENOSYS
;
/* fix this later @@@ */
if
(
flags
&
~
MSG_DONTWAIT
)
/* only handle MSG_DONTWAIT */
buff
=
m
->
msg_iov
->
iov_base
;
return
-
EOPNOTSUPP
;
size
=
m
->
msg_iov
->
iov_len
;
vcc
=
ATM_SD
(
sock
);
vcc
=
ATM_SD
(
sock
);
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
set_current_state
(
TASK_INTERRUPTIBLE
);
error
=
1
;
/* <= 0 is error */
while
(
!
(
skb
=
skb_dequeue
(
&
vcc
->
sk
->
sk_receive_queue
)))
{
if
(
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
||
if
(
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
||
test_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
))
{
test_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
))
error
=
vcc
->
reply
;
return
vcc
->
reply
;
break
;
if
(
!
test_bit
(
ATM_VF_READY
,
&
vcc
->
flags
))
}
return
0
;
if
(
!
test_bit
(
ATM_VF_READY
,
&
vcc
->
flags
))
{
error
=
0
;
skb
=
skb_recv_datagram
(
sk
,
flags
,
flags
&
MSG_DONTWAIT
,
&
error
);
break
;
if
(
!
skb
)
}
return
error
;
if
(
flags
&
MSG_DONTWAIT
)
{
error
=
-
EAGAIN
;
copied
=
skb
->
len
;
break
;
if
(
copied
>
size
)
{
}
copied
=
size
;
schedule
();
msg
->
msg_flags
|=
MSG_TRUNC
;
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
signal_pending
(
current
))
{
error
=
-
ERESTARTSYS
;
break
;
}
}
}
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
error
=
skb_copy_datagram_iovec
(
skb
,
0
,
msg
->
msg_iov
,
copied
);
if
(
error
<=
0
)
return
error
;
if
(
error
)
sock_recv_timestamp
(
m
,
vcc
->
sk
,
skb
);
return
error
;
eff_len
=
skb
->
len
>
size
?
size
:
skb
->
len
;
sock_recv_timestamp
(
msg
,
sk
,
skb
);
if
(
skb
->
len
>
size
)
/* Not fit ? Report it... */
m
->
msg_flags
|=
MSG_TRUNC
;
if
(
vcc
->
dev
->
ops
->
feedback
)
if
(
vcc
->
dev
->
ops
->
feedback
)
vcc
->
dev
->
ops
->
feedback
(
vcc
,
skb
,(
unsigned
long
)
skb
->
data
,
vcc
->
dev
->
ops
->
feedback
(
vcc
,
skb
,
(
unsigned
long
)
skb
->
data
,
(
unsigned
long
)
buff
,
eff_len
);
(
unsigned
long
)
msg
->
msg_iov
->
iov_base
,
copied
);
DPRINTK
(
"RcvM %d -= %d
\n
"
,
atomic_read
(
&
vcc
->
sk
->
sk_rmem_alloc
),
DPRINTK
(
"RcvM %d -= %d
\n
"
,
atomic_read
(
&
vcc
->
sk
->
rmem_alloc
),
skb
->
truesize
);
skb
->
truesize
);
atm_return
(
vcc
,
skb
->
truesize
);
atm_return
(
vcc
,
skb
->
truesize
);
skb_free_datagram
(
sk
,
skb
);
error
=
copy_to_user
(
buff
,
skb
->
data
,
eff_len
)
?
-
EFAULT
:
0
;
return
copied
;
kfree_skb
(
skb
);
return
error
?
error
:
eff_len
;
}
}
int
atm
_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
vcc
_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
total_len
)
int
total_len
)
{
{
DECLARE_WAITQUEUE
(
wait
,
current
);
struct
sock
*
sk
=
sock
->
sk
;
DEFINE_WAIT
(
wait
);
struct
atm_vcc
*
vcc
;
struct
atm_vcc
*
vcc
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
int
eff
,
error
;
int
eff
,
error
;
const
void
*
buff
;
const
void
*
buff
;
int
size
;
int
size
;
if
(
sock
->
state
!=
SS_CONNECTED
)
return
-
ENOTCONN
;
lock_sock
(
sk
);
if
(
m
->
msg_name
)
return
-
EISCONN
;
if
(
sock
->
state
!=
SS_CONNECTED
)
{
if
(
m
->
msg_iovlen
!=
1
)
return
-
ENOSYS
;
/* fix this later @@@ */
error
=
-
ENOTCONN
;
goto
out
;
}
if
(
m
->
msg_name
)
{
error
=
-
EISCONN
;
goto
out
;
}
if
(
m
->
msg_iovlen
!=
1
)
{
error
=
-
ENOSYS
;
/* fix this later @@@ */
goto
out
;
}
buff
=
m
->
msg_iov
->
iov_base
;
buff
=
m
->
msg_iov
->
iov_base
;
size
=
m
->
msg_iov
->
iov_len
;
size
=
m
->
msg_iov
->
iov_len
;
vcc
=
ATM_SD
(
sock
);
vcc
=
ATM_SD
(
sock
);
if
(
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
||
if
(
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
||
test_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
))
test_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
))
{
return
vcc
->
reply
;
error
=
vcc
->
reply
;
if
(
!
test_bit
(
ATM_VF_READY
,
&
vcc
->
flags
))
return
-
EPIPE
;
goto
out
;
if
(
!
size
)
return
0
;
}
if
(
size
<
0
||
size
>
vcc
->
qos
.
txtp
.
max_sdu
)
return
-
EMSGSIZE
;
if
(
!
test_bit
(
ATM_VF_READY
,
&
vcc
->
flags
))
{
error
=
-
EPIPE
;
goto
out
;
}
if
(
!
size
)
{
error
=
0
;
goto
out
;
}
if
(
size
<
0
||
size
>
vcc
->
qos
.
txtp
.
max_sdu
)
{
error
=
-
EMSGSIZE
;
goto
out
;
}
/* verify_area is done by net/socket.c */
/* verify_area is done by net/socket.c */
eff
=
(
size
+
3
)
&
~
3
;
/* align to word boundary */
eff
=
(
size
+
3
)
&
~
3
;
/* align to word boundary */
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
set_current_state
(
TASK_INTERRUPTIBLE
);
error
=
0
;
error
=
0
;
while
(
!
(
skb
=
alloc_tx
(
vcc
,
eff
)))
{
while
(
!
(
skb
=
alloc_tx
(
vcc
,
eff
)))
{
if
(
m
->
msg_flags
&
MSG_DONTWAIT
)
{
if
(
m
->
msg_flags
&
MSG_DONTWAIT
)
{
...
@@ -506,7 +498,6 @@ int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
...
@@ -506,7 +498,6 @@ int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
break
;
break
;
}
}
schedule
();
schedule
();
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
signal_pending
(
current
))
{
if
(
signal_pending
(
current
))
{
error
=
-
ERESTARTSYS
;
error
=
-
ERESTARTSYS
;
break
;
break
;
...
@@ -520,19 +511,24 @@ int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
...
@@ -520,19 +511,24 @@ int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
error
=
-
EPIPE
;
error
=
-
EPIPE
;
break
;
break
;
}
}
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
}
}
set_current_state
(
TASK_RUNNING
);
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
if
(
error
)
if
(
error
)
return
error
;
goto
out
;
skb
->
dev
=
NULL
;
/* for paths shared with net_device interfaces */
skb
->
dev
=
NULL
;
/* for paths shared with net_device interfaces */
ATM_SKB
(
skb
)
->
atm_options
=
vcc
->
atm_options
;
ATM_SKB
(
skb
)
->
atm_options
=
vcc
->
atm_options
;
if
(
copy_from_user
(
skb_put
(
skb
,
size
),
buff
,
size
))
{
if
(
copy_from_user
(
skb_put
(
skb
,
size
),
buff
,
size
))
{
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
-
EFAULT
;
error
=
-
EFAULT
;
goto
out
;
}
}
if
(
eff
!=
size
)
memset
(
skb
->
data
+
size
,
0
,
eff
-
size
);
if
(
eff
!=
size
)
memset
(
skb
->
data
+
size
,
0
,
eff
-
size
);
error
=
vcc
->
dev
->
ops
->
send
(
vcc
,
skb
);
error
=
vcc
->
dev
->
ops
->
send
(
vcc
,
skb
);
return
error
?
error
:
size
;
error
=
error
?
error
:
size
;
out:
release_sock
(
sk
);
return
error
;
}
}
...
@@ -880,14 +876,16 @@ static int check_qos(struct atm_qos *qos)
...
@@ -880,14 +876,16 @@ static int check_qos(struct atm_qos *qos)
return
check_tp
(
&
qos
->
rxtp
);
return
check_tp
(
&
qos
->
rxtp
);
}
}
int
vcc_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
static
int
atm_do_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
void
*
optval
,
int
optlen
)
{
{
struct
atm_vcc
*
vcc
;
struct
atm_vcc
*
vcc
;
unsigned
long
value
;
unsigned
long
value
;
int
error
;
int
error
;
if
(
__SO_LEVEL_MATCH
(
optname
,
level
)
&&
optlen
!=
__SO_SIZE
(
optname
))
return
-
EINVAL
;
vcc
=
ATM_SD
(
sock
);
vcc
=
ATM_SD
(
sock
);
switch
(
optname
)
{
switch
(
optname
)
{
case
SO_ATMQOS
:
case
SO_ATMQOS
:
...
@@ -921,10 +919,16 @@ static int atm_do_setsockopt(struct socket *sock,int level,int optname,
...
@@ -921,10 +919,16 @@ static int atm_do_setsockopt(struct socket *sock,int level,int optname,
}
}
static
int
atm_do_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
int
vcc_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
void
*
optval
,
int
optlen
)
char
*
optval
,
int
*
optlen
)
{
{
struct
atm_vcc
*
vcc
;
struct
atm_vcc
*
vcc
;
int
len
;
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
if
(
__SO_LEVEL_MATCH
(
optname
,
level
)
&&
len
!=
__SO_SIZE
(
optname
))
return
-
EINVAL
;
vcc
=
ATM_SD
(
sock
);
vcc
=
ATM_SD
(
sock
);
switch
(
optname
)
{
switch
(
optname
)
{
...
@@ -955,28 +959,7 @@ static int atm_do_getsockopt(struct socket *sock,int level,int optname,
...
@@ -955,28 +959,7 @@ static int atm_do_getsockopt(struct socket *sock,int level,int optname,
break
;
break
;
}
}
if
(
!
vcc
->
dev
||
!
vcc
->
dev
->
ops
->
getsockopt
)
return
-
EINVAL
;
if
(
!
vcc
->
dev
||
!
vcc
->
dev
->
ops
->
getsockopt
)
return
-
EINVAL
;
return
vcc
->
dev
->
ops
->
getsockopt
(
vcc
,
level
,
optname
,
optval
,
optlen
);
return
vcc
->
dev
->
ops
->
getsockopt
(
vcc
,
level
,
optname
,
optval
,
len
);
}
int
atm_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
{
if
(
__SO_LEVEL_MATCH
(
optname
,
level
)
&&
optlen
!=
__SO_SIZE
(
optname
))
return
-
EINVAL
;
return
atm_do_setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
}
int
atm_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
int
len
;
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
if
(
__SO_LEVEL_MATCH
(
optname
,
level
)
&&
len
!=
__SO_SIZE
(
optname
))
return
-
EINVAL
;
return
atm_do_getsockopt
(
sock
,
level
,
optname
,
optval
,
len
);
}
}
...
...
net/atm/common.h
View file @
f6932f56
...
@@ -12,19 +12,18 @@
...
@@ -12,19 +12,18 @@
int
atm_create
(
struct
socket
*
sock
,
int
protocol
,
int
family
);
int
atm_create
(
struct
socket
*
sock
,
int
protocol
,
int
family
);
int
atm_release
(
struct
socket
*
sock
);
int
atm_release
(
struct
socket
*
sock
);
int
atm_connect
(
struct
socket
*
sock
,
int
itf
,
short
vpi
,
int
vci
);
int
vcc_connect
(
struct
socket
*
sock
,
int
itf
,
short
vpi
,
int
vci
);
int
atm_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
vcc_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
total_len
,
int
flags
);
int
size
,
int
flags
);
int
atm
_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
vcc
_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
total_len
);
int
total_len
);
unsigned
int
atm_poll
(
struct
file
*
file
,
struct
socket
*
sock
,
poll_table
*
wait
);
unsigned
int
atm_poll
(
struct
file
*
file
,
struct
socket
*
sock
,
poll_table
*
wait
);
int
vcc_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
);
int
vcc_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
);
int
atm_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
vcc_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
);
int
optlen
);
int
atm_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
vcc_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
);
int
*
optlen
);
int
atm_connect_vcc
(
struct
atm_vcc
*
vcc
,
int
itf
,
short
vpi
,
int
vci
);
void
atm_release_vcc_sk
(
struct
sock
*
sk
,
int
free_sk
);
void
atm_release_vcc_sk
(
struct
sock
*
sk
,
int
free_sk
);
void
atm_shutdown_dev
(
struct
atm_dev
*
dev
);
void
atm_shutdown_dev
(
struct
atm_dev
*
dev
);
...
...
net/atm/lec.c
View file @
f6932f56
...
@@ -1079,7 +1079,7 @@ lec_arp_clear_vccs(struct lec_arp_table *entry)
...
@@ -1079,7 +1079,7 @@ lec_arp_clear_vccs(struct lec_arp_table *entry)
clear_bit(ATM_VF_READY,&entry->vcc->flags);
clear_bit(ATM_VF_READY,&entry->vcc->flags);
entry->vcc->push(entry->vcc, NULL);
entry->vcc->push(entry->vcc, NULL);
#endif
#endif
atm_async_release_vc
c
(
entry
->
vcc
,
-
EPIPE
);
vcc_release_asyn
c
(
entry
->
vcc
,
-
EPIPE
);
entry
->
vcc
=
NULL
;
entry
->
vcc
=
NULL
;
}
}
if
(
entry
->
recv_vcc
)
{
if
(
entry
->
recv_vcc
)
{
...
@@ -1089,7 +1089,7 @@ lec_arp_clear_vccs(struct lec_arp_table *entry)
...
@@ -1089,7 +1089,7 @@ lec_arp_clear_vccs(struct lec_arp_table *entry)
clear_bit(ATM_VF_READY,&entry->recv_vcc->flags);
clear_bit(ATM_VF_READY,&entry->recv_vcc->flags);
entry->recv_vcc->push(entry->recv_vcc, NULL);
entry->recv_vcc->push(entry->recv_vcc, NULL);
#endif
#endif
atm_async_release_vc
c
(
entry
->
recv_vcc
,
-
EPIPE
);
vcc_release_asyn
c
(
entry
->
recv_vcc
,
-
EPIPE
);
entry
->
recv_vcc
=
NULL
;
entry
->
recv_vcc
=
NULL
;
}
}
}
}
...
...
net/atm/mpoa_caches.c
View file @
f6932f56
...
@@ -212,7 +212,7 @@ static void in_cache_remove_entry(in_cache_entry *entry,
...
@@ -212,7 +212,7 @@ static void in_cache_remove_entry(in_cache_entry *entry,
client
->
eg_ops
->
put
(
eg_entry
);
client
->
eg_ops
->
put
(
eg_entry
);
return
;
return
;
}
}
atm_async_release_vc
c
(
vcc
,
-
EPIPE
);
vcc_release_asyn
c
(
vcc
,
-
EPIPE
);
}
}
return
;
return
;
...
@@ -447,7 +447,7 @@ static void eg_cache_remove_entry(eg_cache_entry *entry,
...
@@ -447,7 +447,7 @@ static void eg_cache_remove_entry(eg_cache_entry *entry,
client
->
in_ops
->
put
(
in_entry
);
client
->
in_ops
->
put
(
in_entry
);
return
;
return
;
}
}
atm_async_release_vc
c
(
vcc
,
-
EPIPE
);
vcc_release_asyn
c
(
vcc
,
-
EPIPE
);
}
}
return
;
return
;
...
...
net/atm/pvc.c
View file @
f6932f56
...
@@ -31,20 +31,29 @@ static int pvc_shutdown(struct socket *sock,int how)
...
@@ -31,20 +31,29 @@ static int pvc_shutdown(struct socket *sock,int how)
static
int
pvc_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
static
int
pvc_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
int
sockaddr_len
)
int
sockaddr_len
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sockaddr_atmpvc
*
addr
;
struct
sockaddr_atmpvc
*
addr
;
struct
atm_vcc
*
vcc
;
struct
atm_vcc
*
vcc
;
int
error
;
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmpvc
))
return
-
EINVAL
;
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmpvc
))
return
-
EINVAL
;
addr
=
(
struct
sockaddr_atmpvc
*
)
sockaddr
;
addr
=
(
struct
sockaddr_atmpvc
*
)
sockaddr
;
if
(
addr
->
sap_family
!=
AF_ATMPVC
)
return
-
EAFNOSUPPORT
;
if
(
addr
->
sap_family
!=
AF_ATMPVC
)
return
-
EAFNOSUPPORT
;
lock_sock
(
sk
);
vcc
=
ATM_SD
(
sock
);
vcc
=
ATM_SD
(
sock
);
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
return
-
EBADFD
;
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
{
error
=
-
EBADFD
;
goto
out
;
}
if
(
test_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
))
{
if
(
test_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
))
{
if
(
vcc
->
vpi
!=
ATM_VPI_UNSPEC
)
addr
->
sap_addr
.
vpi
=
vcc
->
vpi
;
if
(
vcc
->
vpi
!=
ATM_VPI_UNSPEC
)
addr
->
sap_addr
.
vpi
=
vcc
->
vpi
;
if
(
vcc
->
vci
!=
ATM_VCI_UNSPEC
)
addr
->
sap_addr
.
vci
=
vcc
->
vci
;
if
(
vcc
->
vci
!=
ATM_VCI_UNSPEC
)
addr
->
sap_addr
.
vci
=
vcc
->
vci
;
}
}
return
atm_connect
(
sock
,
addr
->
sap_addr
.
itf
,
addr
->
sap_addr
.
vpi
,
error
=
vcc_connect
(
sock
,
addr
->
sap_addr
.
itf
,
addr
->
sap_addr
.
vpi
,
addr
->
sap_addr
.
vci
);
addr
->
sap_addr
.
vci
);
out:
release_sock
(
sk
);
return
error
;
}
}
...
@@ -54,6 +63,31 @@ static int pvc_connect(struct socket *sock,struct sockaddr *sockaddr,
...
@@ -54,6 +63,31 @@ static int pvc_connect(struct socket *sock,struct sockaddr *sockaddr,
return
pvc_bind
(
sock
,
sockaddr
,
sockaddr_len
);
return
pvc_bind
(
sock
,
sockaddr
,
sockaddr_len
);
}
}
static
int
pvc_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
error
;
lock_sock
(
sk
);
error
=
vcc_setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
release_sock
(
sk
);
return
error
;
}
static
int
pvc_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
error
;
lock_sock
(
sk
);
error
=
vcc_getsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
release_sock
(
sk
);
return
error
;
}
static
int
pvc_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
static
int
pvc_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
int
*
sockaddr_len
,
int
peer
)
int
*
sockaddr_len
,
int
peer
)
...
@@ -72,7 +106,7 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr,
...
@@ -72,7 +106,7 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr,
}
}
static
struct
proto_ops
SOCKOPS_WRAPPED
(
pvc_proto_ops
)
=
{
static
struct
proto_ops
pvc_proto_ops
=
{
.
family
=
PF_ATMPVC
,
.
family
=
PF_ATMPVC
,
.
release
=
atm_release
,
.
release
=
atm_release
,
...
@@ -85,19 +119,15 @@ static struct proto_ops SOCKOPS_WRAPPED(pvc_proto_ops) = {
...
@@ -85,19 +119,15 @@ static struct proto_ops SOCKOPS_WRAPPED(pvc_proto_ops) = {
.
ioctl
=
vcc_ioctl
,
.
ioctl
=
vcc_ioctl
,
.
listen
=
sock_no_listen
,
.
listen
=
sock_no_listen
,
.
shutdown
=
pvc_shutdown
,
.
shutdown
=
pvc_shutdown
,
.
setsockopt
=
atm
_setsockopt
,
.
setsockopt
=
pvc
_setsockopt
,
.
getsockopt
=
atm
_getsockopt
,
.
getsockopt
=
pvc
_getsockopt
,
.
sendmsg
=
atm
_sendmsg
,
.
sendmsg
=
vcc
_sendmsg
,
.
recvmsg
=
atm
_recvmsg
,
.
recvmsg
=
vcc
_recvmsg
,
.
mmap
=
sock_no_mmap
,
.
mmap
=
sock_no_mmap
,
.
sendpage
=
sock_no_sendpage
,
.
sendpage
=
sock_no_sendpage
,
};
};
#include <linux/smp_lock.h>
SOCKOPS_WRAP
(
pvc_proto
,
PF_ATMPVC
);
static
int
pvc_create
(
struct
socket
*
sock
,
int
protocol
)
static
int
pvc_create
(
struct
socket
*
sock
,
int
protocol
)
{
{
sock
->
ops
=
&
pvc_proto_ops
;
sock
->
ops
=
&
pvc_proto_ops
;
...
...
net/atm/signaling.c
View file @
f6932f56
...
@@ -124,14 +124,16 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
...
@@ -124,14 +124,16 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
clear_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
vcc
->
reply
=
msg
->
reply
;
vcc
->
reply
=
msg
->
reply
;
vcc
->
sk
->
sk_err
=
-
msg
->
reply
;
break
;
break
;
case
as_indicate
:
case
as_indicate
:
vcc
=
*
(
struct
atm_vcc
**
)
&
msg
->
listen_vcc
;
vcc
=
*
(
struct
atm_vcc
**
)
&
msg
->
listen_vcc
;
DPRINTK
(
"as_indicate!!!
\n
"
);
DPRINTK
(
"as_indicate!!!
\n
"
);
lock_sock
(
vcc
->
sk
);
if
(
vcc
->
sk
->
sk_ack_backlog
==
if
(
vcc
->
sk
->
sk_ack_backlog
==
vcc
->
sk
->
sk_max_ack_backlog
)
{
vcc
->
sk
->
sk_max_ack_backlog
)
{
sigd_enq
(
0
,
as_reject
,
vcc
,
NULL
,
NULL
);
sigd_enq
(
0
,
as_reject
,
vcc
,
NULL
,
NULL
);
return
0
;
goto
as_indicate_complete
;
}
}
vcc
->
sk
->
sk_ack_backlog
++
;
vcc
->
sk
->
sk_ack_backlog
++
;
skb_queue_tail
(
&
vcc
->
sk
->
sk_receive_queue
,
skb
);
skb_queue_tail
(
&
vcc
->
sk
->
sk_receive_queue
,
skb
);
...
@@ -140,11 +142,14 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
...
@@ -140,11 +142,14 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
&
vcc
->
sleep
);
&
vcc
->
sleep
);
vcc
->
callback
(
vcc
);
vcc
->
callback
(
vcc
);
}
}
as_indicate_complete:
release_sock
(
vcc
->
sk
);
return
0
;
return
0
;
case
as_close
:
case
as_close
:
set_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
vcc
->
reply
=
msg
->
reply
;
vcc
->
reply
=
msg
->
reply
;
vcc
->
sk
->
sk_err
=
-
msg
->
reply
;
break
;
break
;
case
as_modify
:
case
as_modify
:
modify_qos
(
vcc
,
msg
);
modify_qos
(
vcc
,
msg
);
...
@@ -202,6 +207,7 @@ static void purge_vccs(struct atm_vcc *vcc)
...
@@ -202,6 +207,7 @@ static void purge_vccs(struct atm_vcc *vcc)
!
test_bit
(
ATM_VF_META
,
&
vcc
->
flags
))
{
!
test_bit
(
ATM_VF_META
,
&
vcc
->
flags
))
{
set_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
);
vcc
->
reply
=
-
EUNATCH
;
vcc
->
reply
=
-
EUNATCH
;
vcc
->
sk
->
sk_err
=
EUNATCH
;
wake_up
(
&
vcc
->
sleep
);
wake_up
(
&
vcc
->
sleep
);
}
}
vcc
=
vcc
->
next
;
vcc
=
vcc
->
next
;
...
...
net/atm/svc.c
View file @
f6932f56
...
@@ -59,18 +59,18 @@ static int svc_shutdown(struct socket *sock,int how)
...
@@ -59,18 +59,18 @@ static int svc_shutdown(struct socket *sock,int how)
static
void
svc_disconnect
(
struct
atm_vcc
*
vcc
)
static
void
svc_disconnect
(
struct
atm_vcc
*
vcc
)
{
{
DE
CLARE_WAITQUEUE
(
wait
,
curren
t
);
DE
FINE_WAIT
(
wai
t
);
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
DPRINTK
(
"svc_disconnect %p
\n
"
,
vcc
);
DPRINTK
(
"svc_disconnect %p
\n
"
,
vcc
);
if
(
test_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
))
{
if
(
test_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
))
{
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
sigd_enq
(
vcc
,
as_close
,
NULL
,
NULL
,
NULL
);
sigd_enq
(
vcc
,
as_close
,
NULL
,
NULL
,
NULL
);
while
(
!
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
&&
sigd
)
{
while
(
!
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
&&
sigd
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule
();
schedule
();
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
}
}
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
}
}
/* beware - socket is still in use by atmsigd until the last
/* beware - socket is still in use by atmsigd until the last
as_indicate has been answered */
as_indicate has been answered */
...
@@ -107,80 +107,138 @@ static int svc_release(struct socket *sock)
...
@@ -107,80 +107,138 @@ static int svc_release(struct socket *sock)
static
int
svc_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
static
int
svc_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
int
sockaddr_len
)
int
sockaddr_len
)
{
{
DECLARE_WAITQUEUE
(
wait
,
current
);
DEFINE_WAIT
(
wait
);
struct
sock
*
sk
=
sock
->
sk
;
struct
sockaddr_atmsvc
*
addr
;
struct
sockaddr_atmsvc
*
addr
;
struct
atm_vcc
*
vcc
;
struct
atm_vcc
*
vcc
;
int
error
;
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmsvc
))
return
-
EINVAL
;
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmsvc
))
if
(
sock
->
state
==
SS_CONNECTED
)
return
-
EISCONN
;
return
-
EINVAL
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
return
-
EINVAL
;
lock_sock
(
sk
);
if
(
sock
->
state
==
SS_CONNECTED
)
{
error
=
-
EISCONN
;
goto
out
;
}
if
(
sock
->
state
!=
SS_UNCONNECTED
)
{
error
=
-
EINVAL
;
goto
out
;
}
vcc
=
ATM_SD
(
sock
);
vcc
=
ATM_SD
(
sock
);
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
return
-
EINVAL
;
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
{
error
=
-
EINVAL
;
goto
out
;
}
addr
=
(
struct
sockaddr_atmsvc
*
)
sockaddr
;
addr
=
(
struct
sockaddr_atmsvc
*
)
sockaddr
;
if
(
addr
->
sas_family
!=
AF_ATMSVC
)
return
-
EAFNOSUPPORT
;
if
(
addr
->
sas_family
!=
AF_ATMSVC
)
{
error
=
-
EAFNOSUPPORT
;
goto
out
;
}
clear_bit
(
ATM_VF_BOUND
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_BOUND
,
&
vcc
->
flags
);
/* failing rebind will kill old binding */
/* failing rebind will kill old binding */
/* @@@ check memory (de)allocation on rebind */
/* @@@ check memory (de)allocation on rebind */
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
return
-
EBADFD
;
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
{
error
=
-
EBADFD
;
goto
out
;
}
vcc
->
local
=
*
addr
;
vcc
->
local
=
*
addr
;
vcc
->
reply
=
WAITING
;
vcc
->
reply
=
WAITING
;
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
sigd_enq
(
vcc
,
as_bind
,
NULL
,
NULL
,
&
vcc
->
local
);
sigd_enq
(
vcc
,
as_bind
,
NULL
,
NULL
,
&
vcc
->
local
);
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule
();
schedule
();
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
}
}
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
clear_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
);
/* doesn't count */
clear_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
);
/* doesn't count */
if
(
!
sigd
)
return
-
EUNATCH
;
if
(
!
sigd
)
{
if
(
!
vcc
->
reply
)
set_bit
(
ATM_VF_BOUND
,
&
vcc
->
flags
);
error
=
-
EUNATCH
;
return
vcc
->
reply
;
goto
out
;
}
if
(
!
vcc
->
reply
)
set_bit
(
ATM_VF_BOUND
,
&
vcc
->
flags
);
error
=
vcc
->
reply
;
out:
release_sock
(
sk
);
return
error
;
}
}
static
int
svc_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
static
int
svc_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
int
sockaddr_len
,
int
flags
)
int
sockaddr_len
,
int
flags
)
{
{
DECLARE_WAITQUEUE
(
wait
,
current
);
DEFINE_WAIT
(
wait
);
struct
sock
*
sk
=
sock
->
sk
;
struct
sockaddr_atmsvc
*
addr
;
struct
sockaddr_atmsvc
*
addr
;
struct
atm_vcc
*
vcc
=
ATM_SD
(
sock
);
struct
atm_vcc
*
vcc
=
ATM_SD
(
sock
);
int
error
;
int
error
;
DPRINTK
(
"svc_connect %p
\n
"
,
vcc
);
DPRINTK
(
"svc_connect %p
\n
"
,
vcc
);
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmsvc
))
return
-
EINVAL
;
lock_sock
(
sk
);
if
(
sock
->
state
==
SS_CONNECTED
)
return
-
EISCONN
;
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmsvc
))
{
if
(
sock
->
state
==
SS_CONNECTING
)
{
error
=
-
EINVAL
;
if
(
vcc
->
reply
==
WAITING
)
return
-
EALREADY
;
goto
out
;
sock
->
state
=
SS_UNCONNECTED
;
if
(
vcc
->
reply
)
return
vcc
->
reply
;
}
}
else
{
int
error
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
return
-
EINVAL
;
switch
(
sock
->
state
)
{
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
return
-
EINVAL
;
default:
error
=
-
EINVAL
;
goto
out
;
case
SS_CONNECTED
:
error
=
-
EISCONN
;
goto
out
;
case
SS_CONNECTING
:
if
(
vcc
->
reply
==
WAITING
)
{
error
=
-
EALREADY
;
goto
out
;
}
sock
->
state
=
SS_UNCONNECTED
;
if
(
vcc
->
reply
)
{
error
=
vcc
->
reply
;
goto
out
;
}
break
;
case
SS_UNCONNECTED
:
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
{
error
=
-
EINVAL
;
goto
out
;
}
addr
=
(
struct
sockaddr_atmsvc
*
)
sockaddr
;
addr
=
(
struct
sockaddr_atmsvc
*
)
sockaddr
;
if
(
addr
->
sas_family
!=
AF_ATMSVC
)
return
-
EAFNOSUPPORT
;
if
(
addr
->
sas_family
!=
AF_ATMSVC
)
{
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
return
-
EBADFD
;
error
=
-
EAFNOSUPPORT
;
goto
out
;
}
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
{
error
=
-
EBADFD
;
goto
out
;
}
if
(
vcc
->
qos
.
txtp
.
traffic_class
==
ATM_ANYCLASS
||
if
(
vcc
->
qos
.
txtp
.
traffic_class
==
ATM_ANYCLASS
||
vcc
->
qos
.
rxtp
.
traffic_class
==
ATM_ANYCLASS
)
vcc
->
qos
.
rxtp
.
traffic_class
==
ATM_ANYCLASS
)
{
return
-
EINVAL
;
error
=
-
EINVAL
;
goto
out
;
}
if
(
!
vcc
->
qos
.
txtp
.
traffic_class
&&
if
(
!
vcc
->
qos
.
txtp
.
traffic_class
&&
!
vcc
->
qos
.
rxtp
.
traffic_class
)
return
-
EINVAL
;
!
vcc
->
qos
.
rxtp
.
traffic_class
)
{
error
=
-
EINVAL
;
goto
out
;
}
vcc
->
remote
=
*
addr
;
vcc
->
remote
=
*
addr
;
vcc
->
reply
=
WAITING
;
vcc
->
reply
=
WAITING
;
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
sigd_enq
(
vcc
,
as_connect
,
NULL
,
NULL
,
&
vcc
->
remote
);
sigd_enq
(
vcc
,
as_connect
,
NULL
,
NULL
,
&
vcc
->
remote
);
if
(
flags
&
O_NONBLOCK
)
{
if
(
flags
&
O_NONBLOCK
)
{
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
sock
->
state
=
SS_CONNECTING
;
sock
->
state
=
SS_CONNECTING
;
return
-
EINPROGRESS
;
error
=
-
EINPROGRESS
;
goto
out
;
}
}
error
=
0
;
error
=
0
;
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule
();
schedule
();
if
(
!
signal_pending
(
current
))
continue
;
if
(
!
signal_pending
(
current
))
{
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
continue
;
}
DPRINTK
(
"*ABORT*
\n
"
);
DPRINTK
(
"*ABORT*
\n
"
);
/*
/*
* This is tricky:
* This is tricky:
...
@@ -196,13 +254,13 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr,
...
@@ -196,13 +254,13 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr,
*/
*/
sigd_enq
(
vcc
,
as_close
,
NULL
,
NULL
,
NULL
);
sigd_enq
(
vcc
,
as_close
,
NULL
,
NULL
,
NULL
);
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
set_current_state
(
TASK_UN
INTERRUPTIBLE
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_
INTERRUPTIBLE
);
schedule
();
schedule
();
}
}
if
(
!
vcc
->
reply
)
if
(
!
vcc
->
reply
)
while
(
!
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
while
(
!
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
&&
sigd
)
{
&&
sigd
)
{
set_current_state
(
TASK_UN
INTERRUPTIBLE
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_
INTERRUPTIBLE
);
schedule
();
schedule
();
}
}
clear_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
);
...
@@ -212,10 +270,17 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr,
...
@@ -212,10 +270,17 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr,
error
=
-
EINTR
;
error
=
-
EINTR
;
break
;
break
;
}
}
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
if
(
error
)
return
error
;
if
(
error
)
if
(
!
sigd
)
return
-
EUNATCH
;
goto
out
;
if
(
vcc
->
reply
)
return
vcc
->
reply
;
if
(
!
sigd
)
{
error
=
-
EUNATCH
;
goto
out
;
}
if
(
vcc
->
reply
)
{
error
=
vcc
->
reply
;
goto
out
;
}
}
}
/*
/*
* Not supported yet
* Not supported yet
...
@@ -228,56 +293,73 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr,
...
@@ -228,56 +293,73 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr,
/*
/*
* #endif
* #endif
*/
*/
if
(
!
(
error
=
atm_connect
(
sock
,
vcc
->
itf
,
vcc
->
vpi
,
vcc
->
vci
)))
if
(
!
(
error
=
vcc_connect
(
sock
,
vcc
->
itf
,
vcc
->
vpi
,
vcc
->
vci
)))
sock
->
state
=
SS_CONNECTED
;
sock
->
state
=
SS_CONNECTED
;
else
(
void
)
svc_disconnect
(
vcc
);
else
(
void
)
svc_disconnect
(
vcc
);
out:
release_sock
(
sk
);
return
error
;
return
error
;
}
}
static
int
svc_listen
(
struct
socket
*
sock
,
int
backlog
)
static
int
svc_listen
(
struct
socket
*
sock
,
int
backlog
)
{
{
DECLARE_WAITQUEUE
(
wait
,
current
);
DEFINE_WAIT
(
wait
);
struct
sock
*
sk
=
sock
->
sk
;
struct
atm_vcc
*
vcc
=
ATM_SD
(
sock
);
struct
atm_vcc
*
vcc
=
ATM_SD
(
sock
);
int
error
;
DPRINTK
(
"svc_listen %p
\n
"
,
vcc
);
DPRINTK
(
"svc_listen %p
\n
"
,
vcc
);
lock_sock
(
sk
);
/* let server handle listen on unbound sockets */
/* let server handle listen on unbound sockets */
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
return
-
EINVAL
;
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
{
error
=
-
EINVAL
;
goto
out
;
}
vcc
->
reply
=
WAITING
;
vcc
->
reply
=
WAITING
;
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
sigd_enq
(
vcc
,
as_listen
,
NULL
,
NULL
,
&
vcc
->
local
);
sigd_enq
(
vcc
,
as_listen
,
NULL
,
NULL
,
&
vcc
->
local
);
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule
();
schedule
();
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
}
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
if
(
!
sigd
)
{
error
=
-
EUNATCH
;
goto
out
;
}
}
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
if
(
!
sigd
)
return
-
EUNATCH
;
set_bit
(
ATM_VF_LISTEN
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_LISTEN
,
&
vcc
->
flags
);
vcc
->
sk
->
sk_max_ack_backlog
=
backlog
>
0
?
backlog
:
vcc
->
sk
->
sk_max_ack_backlog
=
backlog
>
0
?
backlog
:
ATM_BACKLOG_DEFAULT
;
ATM_BACKLOG_DEFAULT
;
return
vcc
->
reply
;
error
=
vcc
->
reply
;
out:
release_sock
(
sk
);
return
error
;
}
}
static
int
svc_accept
(
struct
socket
*
sock
,
struct
socket
*
newsock
,
int
flags
)
static
int
svc_accept
(
struct
socket
*
sock
,
struct
socket
*
newsock
,
int
flags
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
struct
atmsvc_msg
*
msg
;
struct
atmsvc_msg
*
msg
;
struct
atm_vcc
*
old_vcc
=
ATM_SD
(
sock
);
struct
atm_vcc
*
old_vcc
=
ATM_SD
(
sock
);
struct
atm_vcc
*
new_vcc
;
struct
atm_vcc
*
new_vcc
;
int
error
;
int
error
;
lock_sock
(
sk
);
error
=
svc_create
(
newsock
,
0
);
error
=
svc_create
(
newsock
,
0
);
if
(
error
)
if
(
error
)
return
error
;
goto
out
;
new_vcc
=
ATM_SD
(
newsock
);
new_vcc
=
ATM_SD
(
newsock
);
DPRINTK
(
"svc_accept %p -> %p
\n
"
,
old_vcc
,
new_vcc
);
DPRINTK
(
"svc_accept %p -> %p
\n
"
,
old_vcc
,
new_vcc
);
while
(
1
)
{
while
(
1
)
{
DE
CLARE_WAITQUEUE
(
wait
,
curren
t
);
DE
FINE_WAIT
(
wai
t
);
add_wait_queue
(
&
old_vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
old_vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
while
(
!
(
skb
=
skb_dequeue
(
&
old_vcc
->
sk
->
sk_receive_queue
))
&&
while
(
!
(
skb
=
skb_dequeue
(
&
old_vcc
->
sk
->
sk_receive_queue
))
&&
sigd
)
{
sigd
)
{
if
(
test_bit
(
ATM_VF_RELEASED
,
&
old_vcc
->
flags
))
break
;
if
(
test_bit
(
ATM_VF_RELEASED
,
&
old_vcc
->
flags
))
break
;
...
@@ -289,46 +371,63 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
...
@@ -289,46 +371,63 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
error
=
-
EAGAIN
;
error
=
-
EAGAIN
;
break
;
break
;
}
}
set_current_state
(
TASK_INTERRUPTIBLE
);
release_sock
(
sk
);
schedule
();
schedule
();
lock_sock
(
sk
);
if
(
signal_pending
(
current
))
{
if
(
signal_pending
(
current
))
{
error
=
-
ERESTARTSYS
;
error
=
-
ERESTARTSYS
;
break
;
break
;
}
}
prepare_to_wait
(
&
old_vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
}
finish_wait
(
&
old_vcc
->
sleep
,
&
wait
);
if
(
error
)
goto
out
;
if
(
!
skb
)
{
error
=
-
EUNATCH
;
goto
out
;
}
}
remove_wait_queue
(
&
old_vcc
->
sleep
,
&
wait
);
if
(
error
)
return
error
;
if
(
!
skb
)
return
-
EUNATCH
;
msg
=
(
struct
atmsvc_msg
*
)
skb
->
data
;
msg
=
(
struct
atmsvc_msg
*
)
skb
->
data
;
new_vcc
->
qos
=
msg
->
qos
;
new_vcc
->
qos
=
msg
->
qos
;
set_bit
(
ATM_VF_HASQOS
,
&
new_vcc
->
flags
);
set_bit
(
ATM_VF_HASQOS
,
&
new_vcc
->
flags
);
new_vcc
->
remote
=
msg
->
svc
;
new_vcc
->
remote
=
msg
->
svc
;
new_vcc
->
local
=
msg
->
local
;
new_vcc
->
local
=
msg
->
local
;
new_vcc
->
sap
=
msg
->
sap
;
new_vcc
->
sap
=
msg
->
sap
;
error
=
atm_connect
(
newsock
,
msg
->
pvc
.
sap_addr
.
itf
,
error
=
vcc_connect
(
newsock
,
msg
->
pvc
.
sap_addr
.
itf
,
msg
->
pvc
.
sap_addr
.
vpi
,
msg
->
pvc
.
sap_addr
.
vci
);
msg
->
pvc
.
sap_addr
.
vpi
,
msg
->
pvc
.
sap_addr
.
vci
);
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb
);
old_vcc
->
sk
->
sk_ack_backlog
--
;
old_vcc
->
sk
->
sk_ack_backlog
--
;
if
(
error
)
{
if
(
error
)
{
sigd_enq2
(
NULL
,
as_reject
,
old_vcc
,
NULL
,
NULL
,
sigd_enq2
(
NULL
,
as_reject
,
old_vcc
,
NULL
,
NULL
,
&
old_vcc
->
qos
,
error
);
&
old_vcc
->
qos
,
error
);
return
error
==
-
EAGAIN
?
-
EBUSY
:
error
;
error
=
error
==
-
EAGAIN
?
-
EBUSY
:
error
;
goto
out
;
}
}
/* wait should be short, so we ignore the non-blocking flag */
/* wait should be short, so we ignore the non-blocking flag */
new_vcc
->
reply
=
WAITING
;
new_vcc
->
reply
=
WAITING
;
add_wait_queue
(
&
new_vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
new_vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
sigd_enq
(
new_vcc
,
as_accept
,
old_vcc
,
NULL
,
NULL
);
sigd_enq
(
new_vcc
,
as_accept
,
old_vcc
,
NULL
,
NULL
);
while
(
new_vcc
->
reply
==
WAITING
&&
sigd
)
{
while
(
new_vcc
->
reply
==
WAITING
&&
sigd
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
release_sock
(
sk
);
schedule
();
schedule
();
lock_sock
(
sk
);
prepare_to_wait
(
&
new_vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
}
finish_wait
(
&
new_vcc
->
sleep
,
&
wait
);
if
(
!
sigd
)
{
error
=
-
EUNATCH
;
goto
out
;
}
}
remove_wait_queue
(
&
new_vcc
->
sleep
,
&
wait
);
if
(
!
sigd
)
return
-
EUNATCH
;
if
(
!
new_vcc
->
reply
)
break
;
if
(
!
new_vcc
->
reply
)
break
;
if
(
new_vcc
->
reply
!=
-
ERESTARTSYS
)
return
new_vcc
->
reply
;
if
(
new_vcc
->
reply
!=
-
ERESTARTSYS
)
{
error
=
new_vcc
->
reply
;
goto
out
;
}
}
}
newsock
->
state
=
SS_CONNECTED
;
newsock
->
state
=
SS_CONNECTED
;
return
0
;
out:
release_sock
(
sk
);
return
error
;
}
}
...
@@ -347,17 +446,17 @@ static int svc_getname(struct socket *sock,struct sockaddr *sockaddr,
...
@@ -347,17 +446,17 @@ static int svc_getname(struct socket *sock,struct sockaddr *sockaddr,
int
svc_change_qos
(
struct
atm_vcc
*
vcc
,
struct
atm_qos
*
qos
)
int
svc_change_qos
(
struct
atm_vcc
*
vcc
,
struct
atm_qos
*
qos
)
{
{
DE
CLARE_WAITQUEUE
(
wait
,
curren
t
);
DE
FINE_WAIT
(
wai
t
);
vcc
->
reply
=
WAITING
;
vcc
->
reply
=
WAITING
;
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
sigd_enq2
(
vcc
,
as_modify
,
NULL
,
NULL
,
&
vcc
->
local
,
qos
,
0
);
sigd_enq2
(
vcc
,
as_modify
,
NULL
,
NULL
,
&
vcc
->
local
,
qos
,
0
);
while
(
vcc
->
reply
==
WAITING
&&
!
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
while
(
vcc
->
reply
==
WAITING
&&
!
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
&&
sigd
)
{
&&
sigd
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule
();
schedule
();
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
}
}
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
if
(
!
sigd
)
return
-
EUNATCH
;
if
(
!
sigd
)
return
-
EUNATCH
;
return
vcc
->
reply
;
return
vcc
->
reply
;
}
}
...
@@ -366,33 +465,57 @@ int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
...
@@ -366,33 +465,57 @@ int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
static
int
svc_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
static
int
svc_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
char
*
optval
,
int
optlen
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
atm_vcc
*
vcc
;
struct
atm_vcc
*
vcc
;
int
error
=
0
;
if
(
!
__SO_LEVEL_MATCH
(
optname
,
level
)
||
optname
!=
SO_ATMSAP
||
if
(
!
__SO_LEVEL_MATCH
(
optname
,
level
)
||
optname
!=
SO_ATMSAP
||
optlen
!=
sizeof
(
struct
atm_sap
))
optlen
!=
sizeof
(
struct
atm_sap
))
{
return
atm_setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
error
=
vcc_setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
goto
out
;
}
vcc
=
ATM_SD
(
sock
);
vcc
=
ATM_SD
(
sock
);
if
(
copy_from_user
(
&
vcc
->
sap
,
optval
,
optlen
))
return
-
EFAULT
;
if
(
copy_from_user
(
&
vcc
->
sap
,
optval
,
optlen
))
{
set_bit
(
ATM_VF_HASSAP
,
&
vcc
->
flags
);
error
=
-
EFAULT
;
return
0
;
goto
out
;
}
set_bit
(
ATM_VF_HASSAP
,
&
vcc
->
flags
);
out:
release_sock
(
sk
);
return
error
;
}
}
static
int
svc_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
static
int
svc_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
char
*
optval
,
int
*
optlen
)
{
{
int
len
;
struct
sock
*
sk
=
sock
->
sk
;
int
error
=
0
,
len
;
if
(
!
__SO_LEVEL_MATCH
(
optname
,
level
)
||
optname
!=
SO_ATMSAP
)
return
atm_getsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
lock_sock
(
sk
);
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
if
(
!
__SO_LEVEL_MATCH
(
optname
,
level
)
||
optname
!=
SO_ATMSAP
)
{
if
(
len
!=
sizeof
(
struct
atm_sap
))
return
-
EINVAL
;
error
=
vcc_getsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
return
copy_to_user
(
optval
,
&
ATM_SD
(
sock
)
->
sap
,
sizeof
(
struct
atm_sap
))
?
goto
out
;
-
EFAULT
:
0
;
}
if
(
get_user
(
len
,
optlen
))
{
error
=
-
EFAULT
;
goto
out
;
}
if
(
len
!=
sizeof
(
struct
atm_sap
))
{
error
=
-
EINVAL
;
goto
out
;
}
if
(
copy_to_user
(
optval
,
&
ATM_SD
(
sock
)
->
sap
,
sizeof
(
struct
atm_sap
)))
{
error
=
-
EFAULT
;
goto
out
;
}
out:
release_sock
(
sk
);
return
error
;
}
}
static
struct
proto_ops
SOCKOPS_WRAPPED
(
svc_proto_ops
)
=
{
static
struct
proto_ops
svc_proto_ops
=
{
.
family
=
PF_ATMSVC
,
.
family
=
PF_ATMSVC
,
.
release
=
svc_release
,
.
release
=
svc_release
,
...
@@ -407,16 +530,13 @@ static struct proto_ops SOCKOPS_WRAPPED(svc_proto_ops) = {
...
@@ -407,16 +530,13 @@ static struct proto_ops SOCKOPS_WRAPPED(svc_proto_ops) = {
.
shutdown
=
svc_shutdown
,
.
shutdown
=
svc_shutdown
,
.
setsockopt
=
svc_setsockopt
,
.
setsockopt
=
svc_setsockopt
,
.
getsockopt
=
svc_getsockopt
,
.
getsockopt
=
svc_getsockopt
,
.
sendmsg
=
atm
_sendmsg
,
.
sendmsg
=
vcc
_sendmsg
,
.
recvmsg
=
atm
_recvmsg
,
.
recvmsg
=
vcc
_recvmsg
,
.
mmap
=
sock_no_mmap
,
.
mmap
=
sock_no_mmap
,
.
sendpage
=
sock_no_sendpage
,
.
sendpage
=
sock_no_sendpage
,
};
};
#include <linux/smp_lock.h>
SOCKOPS_WRAP
(
svc_proto
,
PF_ATMSVC
);
static
int
svc_create
(
struct
socket
*
sock
,
int
protocol
)
static
int
svc_create
(
struct
socket
*
sock
,
int
protocol
)
{
{
int
error
;
int
error
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment