diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/atm/svc.c | 249 |
1 files changed, 125 insertions, 124 deletions
diff --git a/net/atm/svc.c b/net/atm/svc.c index 251ddbc42e4b..3ba9a45a51ac 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c | |||
@@ -19,14 +19,15 @@ | |||
19 | #include <linux/atmdev.h> | 19 | #include <linux/atmdev.h> |
20 | #include <linux/bitops.h> | 20 | #include <linux/bitops.h> |
21 | #include <net/sock.h> /* for sock_no_* */ | 21 | #include <net/sock.h> /* for sock_no_* */ |
22 | #include <asm/uaccess.h> | 22 | #include <linux/uaccess.h> |
23 | 23 | ||
24 | #include "resources.h" | 24 | #include "resources.h" |
25 | #include "common.h" /* common for PVCs and SVCs */ | 25 | #include "common.h" /* common for PVCs and SVCs */ |
26 | #include "signaling.h" | 26 | #include "signaling.h" |
27 | #include "addr.h" | 27 | #include "addr.h" |
28 | 28 | ||
29 | static int svc_create(struct net *net, struct socket *sock, int protocol, int kern); | 29 | static int svc_create(struct net *net, struct socket *sock, int protocol, |
30 | int kern); | ||
30 | 31 | ||
31 | /* | 32 | /* |
32 | * Note: since all this is still nicely synchronized with the signaling demon, | 33 | * Note: since all this is still nicely synchronized with the signaling demon, |
@@ -35,25 +36,25 @@ static int svc_create(struct net *net, struct socket *sock, int protocol, int ke | |||
35 | */ | 36 | */ |
36 | 37 | ||
37 | 38 | ||
38 | static int svc_shutdown(struct socket *sock,int how) | 39 | static int svc_shutdown(struct socket *sock, int how) |
39 | { | 40 | { |
40 | return 0; | 41 | return 0; |
41 | } | 42 | } |
42 | 43 | ||
43 | |||
44 | static void svc_disconnect(struct atm_vcc *vcc) | 44 | static void svc_disconnect(struct atm_vcc *vcc) |
45 | { | 45 | { |
46 | DEFINE_WAIT(wait); | 46 | DEFINE_WAIT(wait); |
47 | struct sk_buff *skb; | 47 | struct sk_buff *skb; |
48 | struct sock *sk = sk_atm(vcc); | 48 | struct sock *sk = sk_atm(vcc); |
49 | 49 | ||
50 | pr_debug("%p\n",vcc); | 50 | pr_debug("%p\n", vcc); |
51 | if (test_bit(ATM_VF_REGIS,&vcc->flags)) { | 51 | if (test_bit(ATM_VF_REGIS, &vcc->flags)) { |
52 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 52 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); |
53 | sigd_enq(vcc,as_close,NULL,NULL,NULL); | 53 | sigd_enq(vcc, as_close, NULL, NULL, NULL); |
54 | while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) { | 54 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { |
55 | schedule(); | 55 | schedule(); |
56 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 56 | prepare_to_wait(sk->sk_sleep, &wait, |
57 | TASK_UNINTERRUPTIBLE); | ||
57 | } | 58 | } |
58 | finish_wait(sk->sk_sleep, &wait); | 59 | finish_wait(sk->sk_sleep, &wait); |
59 | } | 60 | } |
@@ -62,35 +63,35 @@ static void svc_disconnect(struct atm_vcc *vcc) | |||
62 | while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { | 63 | while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { |
63 | atm_return(vcc, skb->truesize); | 64 | atm_return(vcc, skb->truesize); |
64 | pr_debug("LISTEN REL\n"); | 65 | pr_debug("LISTEN REL\n"); |
65 | sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0); | 66 | sigd_enq2(NULL, as_reject, vcc, NULL, NULL, &vcc->qos, 0); |
66 | dev_kfree_skb(skb); | 67 | dev_kfree_skb(skb); |
67 | } | 68 | } |
68 | clear_bit(ATM_VF_REGIS, &vcc->flags); | 69 | clear_bit(ATM_VF_REGIS, &vcc->flags); |
69 | /* ... may retry later */ | 70 | /* ... may retry later */ |
70 | } | 71 | } |
71 | 72 | ||
72 | |||
73 | static int svc_release(struct socket *sock) | 73 | static int svc_release(struct socket *sock) |
74 | { | 74 | { |
75 | struct sock *sk = sock->sk; | 75 | struct sock *sk = sock->sk; |
76 | struct atm_vcc *vcc; | 76 | struct atm_vcc *vcc; |
77 | 77 | ||
78 | if (sk) { | 78 | if (sk) { |
79 | vcc = ATM_SD(sock); | 79 | vcc = ATM_SD(sock); |
80 | pr_debug("%p\n", vcc); | 80 | pr_debug("%p\n", vcc); |
81 | clear_bit(ATM_VF_READY, &vcc->flags); | 81 | clear_bit(ATM_VF_READY, &vcc->flags); |
82 | /* VCC pointer is used as a reference, so we must not free it | 82 | /* |
83 | (thereby subjecting it to re-use) before all pending connections | 83 | * VCC pointer is used as a reference, |
84 | are closed */ | 84 | * so we must not free it (thereby subjecting it to re-use) |
85 | * before all pending connections are closed | ||
86 | */ | ||
85 | svc_disconnect(vcc); | 87 | svc_disconnect(vcc); |
86 | vcc_release(sock); | 88 | vcc_release(sock); |
87 | } | 89 | } |
88 | return 0; | 90 | return 0; |
89 | } | 91 | } |
90 | 92 | ||
91 | 93 | static int svc_bind(struct socket *sock, struct sockaddr *sockaddr, | |
92 | static int svc_bind(struct socket *sock,struct sockaddr *sockaddr, | 94 | int sockaddr_len) |
93 | int sockaddr_len) | ||
94 | { | 95 | { |
95 | DEFINE_WAIT(wait); | 96 | DEFINE_WAIT(wait); |
96 | struct sock *sk = sock->sk; | 97 | struct sock *sk = sock->sk; |
@@ -115,38 +116,37 @@ static int svc_bind(struct socket *sock,struct sockaddr *sockaddr, | |||
115 | error = -EAFNOSUPPORT; | 116 | error = -EAFNOSUPPORT; |
116 | goto out; | 117 | goto out; |
117 | } | 118 | } |
118 | clear_bit(ATM_VF_BOUND,&vcc->flags); | 119 | clear_bit(ATM_VF_BOUND, &vcc->flags); |
119 | /* failing rebind will kill old binding */ | 120 | /* failing rebind will kill old binding */ |
120 | /* @@@ check memory (de)allocation on rebind */ | 121 | /* @@@ check memory (de)allocation on rebind */ |
121 | if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) { | 122 | if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) { |
122 | error = -EBADFD; | 123 | error = -EBADFD; |
123 | goto out; | 124 | goto out; |
124 | } | 125 | } |
125 | vcc->local = *addr; | 126 | vcc->local = *addr; |
126 | set_bit(ATM_VF_WAITING, &vcc->flags); | 127 | set_bit(ATM_VF_WAITING, &vcc->flags); |
127 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 128 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); |
128 | sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local); | 129 | sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local); |
129 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 130 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
130 | schedule(); | 131 | schedule(); |
131 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 132 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); |
132 | } | 133 | } |
133 | finish_wait(sk->sk_sleep, &wait); | 134 | finish_wait(sk->sk_sleep, &wait); |
134 | clear_bit(ATM_VF_REGIS,&vcc->flags); /* doesn't count */ | 135 | clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */ |
135 | if (!sigd) { | 136 | if (!sigd) { |
136 | error = -EUNATCH; | 137 | error = -EUNATCH; |
137 | goto out; | 138 | goto out; |
138 | } | 139 | } |
139 | if (!sk->sk_err) | 140 | if (!sk->sk_err) |
140 | set_bit(ATM_VF_BOUND,&vcc->flags); | 141 | set_bit(ATM_VF_BOUND, &vcc->flags); |
141 | error = -sk->sk_err; | 142 | error = -sk->sk_err; |
142 | out: | 143 | out: |
143 | release_sock(sk); | 144 | release_sock(sk); |
144 | return error; | 145 | return error; |
145 | } | 146 | } |
146 | 147 | ||
147 | 148 | static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |
148 | static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, | 149 | int sockaddr_len, int flags) |
149 | int sockaddr_len,int flags) | ||
150 | { | 150 | { |
151 | DEFINE_WAIT(wait); | 151 | DEFINE_WAIT(wait); |
152 | struct sock *sk = sock->sk; | 152 | struct sock *sk = sock->sk; |
@@ -154,7 +154,7 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, | |||
154 | struct atm_vcc *vcc = ATM_SD(sock); | 154 | struct atm_vcc *vcc = ATM_SD(sock); |
155 | int error; | 155 | int error; |
156 | 156 | ||
157 | pr_debug("%p\n",vcc); | 157 | pr_debug("%p\n", vcc); |
158 | lock_sock(sk); | 158 | lock_sock(sk); |
159 | if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) { | 159 | if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) { |
160 | error = -EINVAL; | 160 | error = -EINVAL; |
@@ -202,7 +202,7 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, | |||
202 | vcc->remote = *addr; | 202 | vcc->remote = *addr; |
203 | set_bit(ATM_VF_WAITING, &vcc->flags); | 203 | set_bit(ATM_VF_WAITING, &vcc->flags); |
204 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 204 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); |
205 | sigd_enq(vcc,as_connect,NULL,NULL,&vcc->remote); | 205 | sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote); |
206 | if (flags & O_NONBLOCK) { | 206 | if (flags & O_NONBLOCK) { |
207 | finish_wait(sk->sk_sleep, &wait); | 207 | finish_wait(sk->sk_sleep, &wait); |
208 | sock->state = SS_CONNECTING; | 208 | sock->state = SS_CONNECTING; |
@@ -213,7 +213,8 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, | |||
213 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 213 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
214 | schedule(); | 214 | schedule(); |
215 | if (!signal_pending(current)) { | 215 | if (!signal_pending(current)) { |
216 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 216 | prepare_to_wait(sk->sk_sleep, &wait, |
217 | TASK_INTERRUPTIBLE); | ||
217 | continue; | 218 | continue; |
218 | } | 219 | } |
219 | pr_debug("*ABORT*\n"); | 220 | pr_debug("*ABORT*\n"); |
@@ -229,20 +230,22 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, | |||
229 | * Kernel <--okay---- Demon | 230 | * Kernel <--okay---- Demon |
230 | * Kernel <--close--- Demon | 231 | * Kernel <--close--- Demon |
231 | */ | 232 | */ |
232 | sigd_enq(vcc,as_close,NULL,NULL,NULL); | 233 | sigd_enq(vcc, as_close, NULL, NULL, NULL); |
233 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 234 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
234 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 235 | prepare_to_wait(sk->sk_sleep, &wait, |
236 | TASK_INTERRUPTIBLE); | ||
235 | schedule(); | 237 | schedule(); |
236 | } | 238 | } |
237 | if (!sk->sk_err) | 239 | if (!sk->sk_err) |
238 | while (!test_bit(ATM_VF_RELEASED,&vcc->flags) | 240 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && |
239 | && sigd) { | 241 | sigd) { |
240 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 242 | prepare_to_wait(sk->sk_sleep, &wait, |
243 | TASK_INTERRUPTIBLE); | ||
241 | schedule(); | 244 | schedule(); |
242 | } | 245 | } |
243 | clear_bit(ATM_VF_REGIS,&vcc->flags); | 246 | clear_bit(ATM_VF_REGIS, &vcc->flags); |
244 | clear_bit(ATM_VF_RELEASED,&vcc->flags); | 247 | clear_bit(ATM_VF_RELEASED, &vcc->flags); |
245 | clear_bit(ATM_VF_CLOSE,&vcc->flags); | 248 | clear_bit(ATM_VF_CLOSE, &vcc->flags); |
246 | /* we're gone now but may connect later */ | 249 | /* we're gone now but may connect later */ |
247 | error = -EINTR; | 250 | error = -EINTR; |
248 | break; | 251 | break; |
@@ -270,17 +273,17 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, | |||
270 | /* | 273 | /* |
271 | * #endif | 274 | * #endif |
272 | */ | 275 | */ |
273 | if (!(error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci))) | 276 | error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci); |
277 | if (!error) | ||
274 | sock->state = SS_CONNECTED; | 278 | sock->state = SS_CONNECTED; |
275 | else | 279 | else |
276 | (void) svc_disconnect(vcc); | 280 | (void)svc_disconnect(vcc); |
277 | out: | 281 | out: |
278 | release_sock(sk); | 282 | release_sock(sk); |
279 | return error; | 283 | return error; |
280 | } | 284 | } |
281 | 285 | ||
282 | 286 | static int svc_listen(struct socket *sock, int backlog) | |
283 | static int svc_listen(struct socket *sock,int backlog) | ||
284 | { | 287 | { |
285 | DEFINE_WAIT(wait); | 288 | DEFINE_WAIT(wait); |
286 | struct sock *sk = sock->sk; | 289 | struct sock *sk = sock->sk; |
@@ -290,17 +293,17 @@ static int svc_listen(struct socket *sock,int backlog) | |||
290 | pr_debug("%p\n", vcc); | 293 | pr_debug("%p\n", vcc); |
291 | lock_sock(sk); | 294 | lock_sock(sk); |
292 | /* let server handle listen on unbound sockets */ | 295 | /* let server handle listen on unbound sockets */ |
293 | if (test_bit(ATM_VF_SESSION,&vcc->flags)) { | 296 | if (test_bit(ATM_VF_SESSION, &vcc->flags)) { |
294 | error = -EINVAL; | 297 | error = -EINVAL; |
295 | goto out; | 298 | goto out; |
296 | } | 299 | } |
297 | if (test_bit(ATM_VF_LISTEN, &vcc->flags)) { | 300 | if (test_bit(ATM_VF_LISTEN, &vcc->flags)) { |
298 | error = -EADDRINUSE; | 301 | error = -EADDRINUSE; |
299 | goto out; | 302 | goto out; |
300 | } | 303 | } |
301 | set_bit(ATM_VF_WAITING, &vcc->flags); | 304 | set_bit(ATM_VF_WAITING, &vcc->flags); |
302 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 305 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); |
303 | sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); | 306 | sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local); |
304 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 307 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
305 | schedule(); | 308 | schedule(); |
306 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 309 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); |
@@ -310,7 +313,7 @@ static int svc_listen(struct socket *sock,int backlog) | |||
310 | error = -EUNATCH; | 313 | error = -EUNATCH; |
311 | goto out; | 314 | goto out; |
312 | } | 315 | } |
313 | set_bit(ATM_VF_LISTEN,&vcc->flags); | 316 | set_bit(ATM_VF_LISTEN, &vcc->flags); |
314 | vcc_insert_socket(sk); | 317 | vcc_insert_socket(sk); |
315 | sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT; | 318 | sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT; |
316 | error = -sk->sk_err; | 319 | error = -sk->sk_err; |
@@ -319,8 +322,7 @@ out: | |||
319 | return error; | 322 | return error; |
320 | } | 323 | } |
321 | 324 | ||
322 | 325 | static int svc_accept(struct socket *sock, struct socket *newsock, int flags) | |
323 | static int svc_accept(struct socket *sock,struct socket *newsock,int flags) | ||
324 | { | 326 | { |
325 | struct sock *sk = sock->sk; | 327 | struct sock *sk = sock->sk; |
326 | struct sk_buff *skb; | 328 | struct sk_buff *skb; |
@@ -344,8 +346,9 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) | |||
344 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 346 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); |
345 | while (!(skb = skb_dequeue(&sk->sk_receive_queue)) && | 347 | while (!(skb = skb_dequeue(&sk->sk_receive_queue)) && |
346 | sigd) { | 348 | sigd) { |
347 | if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break; | 349 | if (test_bit(ATM_VF_RELEASED, &old_vcc->flags)) |
348 | if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) { | 350 | break; |
351 | if (test_bit(ATM_VF_CLOSE, &old_vcc->flags)) { | ||
349 | error = -sk->sk_err; | 352 | error = -sk->sk_err; |
350 | break; | 353 | break; |
351 | } | 354 | } |
@@ -360,7 +363,8 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) | |||
360 | error = -ERESTARTSYS; | 363 | error = -ERESTARTSYS; |
361 | break; | 364 | break; |
362 | } | 365 | } |
363 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 366 | prepare_to_wait(sk->sk_sleep, &wait, |
367 | TASK_INTERRUPTIBLE); | ||
364 | } | 368 | } |
365 | finish_wait(sk->sk_sleep, &wait); | 369 | finish_wait(sk->sk_sleep, &wait); |
366 | if (error) | 370 | if (error) |
@@ -369,31 +373,34 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) | |||
369 | error = -EUNATCH; | 373 | error = -EUNATCH; |
370 | goto out; | 374 | goto out; |
371 | } | 375 | } |
372 | msg = (struct atmsvc_msg *) skb->data; | 376 | msg = (struct atmsvc_msg *)skb->data; |
373 | new_vcc->qos = msg->qos; | 377 | new_vcc->qos = msg->qos; |
374 | set_bit(ATM_VF_HASQOS,&new_vcc->flags); | 378 | set_bit(ATM_VF_HASQOS, &new_vcc->flags); |
375 | new_vcc->remote = msg->svc; | 379 | new_vcc->remote = msg->svc; |
376 | new_vcc->local = msg->local; | 380 | new_vcc->local = msg->local; |
377 | new_vcc->sap = msg->sap; | 381 | new_vcc->sap = msg->sap; |
378 | error = vcc_connect(newsock, msg->pvc.sap_addr.itf, | 382 | error = vcc_connect(newsock, msg->pvc.sap_addr.itf, |
379 | msg->pvc.sap_addr.vpi, msg->pvc.sap_addr.vci); | 383 | msg->pvc.sap_addr.vpi, |
384 | msg->pvc.sap_addr.vci); | ||
380 | dev_kfree_skb(skb); | 385 | dev_kfree_skb(skb); |
381 | sk->sk_ack_backlog--; | 386 | sk->sk_ack_backlog--; |
382 | if (error) { | 387 | if (error) { |
383 | sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL, | 388 | sigd_enq2(NULL, as_reject, old_vcc, NULL, NULL, |
384 | &old_vcc->qos,error); | 389 | &old_vcc->qos, error); |
385 | error = error == -EAGAIN ? -EBUSY : error; | 390 | error = error == -EAGAIN ? -EBUSY : error; |
386 | goto out; | 391 | goto out; |
387 | } | 392 | } |
388 | /* wait should be short, so we ignore the non-blocking flag */ | 393 | /* wait should be short, so we ignore the non-blocking flag */ |
389 | set_bit(ATM_VF_WAITING, &new_vcc->flags); | 394 | set_bit(ATM_VF_WAITING, &new_vcc->flags); |
390 | prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 395 | prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, |
391 | sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL); | 396 | TASK_UNINTERRUPTIBLE); |
397 | sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL); | ||
392 | while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) { | 398 | while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) { |
393 | release_sock(sk); | 399 | release_sock(sk); |
394 | schedule(); | 400 | schedule(); |
395 | lock_sock(sk); | 401 | lock_sock(sk); |
396 | prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 402 | prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, |
403 | TASK_UNINTERRUPTIBLE); | ||
397 | } | 404 | } |
398 | finish_wait(sk_atm(new_vcc)->sk_sleep, &wait); | 405 | finish_wait(sk_atm(new_vcc)->sk_sleep, &wait); |
399 | if (!sigd) { | 406 | if (!sigd) { |
@@ -413,39 +420,37 @@ out: | |||
413 | return error; | 420 | return error; |
414 | } | 421 | } |
415 | 422 | ||
416 | 423 | static int svc_getname(struct socket *sock, struct sockaddr *sockaddr, | |
417 | static int svc_getname(struct socket *sock,struct sockaddr *sockaddr, | 424 | int *sockaddr_len, int peer) |
418 | int *sockaddr_len,int peer) | ||
419 | { | 425 | { |
420 | struct sockaddr_atmsvc *addr; | 426 | struct sockaddr_atmsvc *addr; |
421 | 427 | ||
422 | *sockaddr_len = sizeof(struct sockaddr_atmsvc); | 428 | *sockaddr_len = sizeof(struct sockaddr_atmsvc); |
423 | addr = (struct sockaddr_atmsvc *) sockaddr; | 429 | addr = (struct sockaddr_atmsvc *) sockaddr; |
424 | memcpy(addr,peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local, | 430 | memcpy(addr, peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local, |
425 | sizeof(struct sockaddr_atmsvc)); | 431 | sizeof(struct sockaddr_atmsvc)); |
426 | return 0; | 432 | return 0; |
427 | } | 433 | } |
428 | 434 | ||
429 | 435 | int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos) | |
430 | int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) | ||
431 | { | 436 | { |
432 | struct sock *sk = sk_atm(vcc); | 437 | struct sock *sk = sk_atm(vcc); |
433 | DEFINE_WAIT(wait); | 438 | DEFINE_WAIT(wait); |
434 | 439 | ||
435 | set_bit(ATM_VF_WAITING, &vcc->flags); | 440 | set_bit(ATM_VF_WAITING, &vcc->flags); |
436 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 441 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); |
437 | sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0); | 442 | sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0); |
438 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && | 443 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && |
439 | !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { | 444 | !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { |
440 | schedule(); | 445 | schedule(); |
441 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 446 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); |
442 | } | 447 | } |
443 | finish_wait(sk->sk_sleep, &wait); | 448 | finish_wait(sk->sk_sleep, &wait); |
444 | if (!sigd) return -EUNATCH; | 449 | if (!sigd) |
450 | return -EUNATCH; | ||
445 | return -sk->sk_err; | 451 | return -sk->sk_err; |
446 | } | 452 | } |
447 | 453 | ||
448 | |||
449 | static int svc_setsockopt(struct socket *sock, int level, int optname, | 454 | static int svc_setsockopt(struct socket *sock, int level, int optname, |
450 | char __user *optval, unsigned int optlen) | 455 | char __user *optval, unsigned int optlen) |
451 | { | 456 | { |
@@ -455,37 +460,35 @@ static int svc_setsockopt(struct socket *sock, int level, int optname, | |||
455 | 460 | ||
456 | lock_sock(sk); | 461 | lock_sock(sk); |
457 | switch (optname) { | 462 | switch (optname) { |
458 | case SO_ATMSAP: | 463 | case SO_ATMSAP: |
459 | if (level != SOL_ATM || optlen != sizeof(struct atm_sap)) { | 464 | if (level != SOL_ATM || optlen != sizeof(struct atm_sap)) { |
460 | error = -EINVAL; | 465 | error = -EINVAL; |
461 | goto out; | 466 | goto out; |
462 | } | 467 | } |
463 | if (copy_from_user(&vcc->sap, optval, optlen)) { | 468 | if (copy_from_user(&vcc->sap, optval, optlen)) { |
464 | error = -EFAULT; | 469 | error = -EFAULT; |
465 | goto out; | 470 | goto out; |
466 | } | 471 | } |
467 | set_bit(ATM_VF_HASSAP, &vcc->flags); | 472 | set_bit(ATM_VF_HASSAP, &vcc->flags); |
468 | break; | 473 | break; |
469 | case SO_MULTIPOINT: | 474 | case SO_MULTIPOINT: |
470 | if (level != SOL_ATM || optlen != sizeof(int)) { | 475 | if (level != SOL_ATM || optlen != sizeof(int)) { |
471 | error = -EINVAL; | 476 | error = -EINVAL; |
472 | goto out; | 477 | goto out; |
473 | } | 478 | } |
474 | if (get_user(value, (int __user *) optval)) { | 479 | if (get_user(value, (int __user *)optval)) { |
475 | error = -EFAULT; | 480 | error = -EFAULT; |
476 | goto out; | 481 | goto out; |
477 | } | 482 | } |
478 | if (value == 1) { | 483 | if (value == 1) |
479 | set_bit(ATM_VF_SESSION, &vcc->flags); | 484 | set_bit(ATM_VF_SESSION, &vcc->flags); |
480 | } else if (value == 0) { | 485 | else if (value == 0) |
481 | clear_bit(ATM_VF_SESSION, &vcc->flags); | 486 | clear_bit(ATM_VF_SESSION, &vcc->flags); |
482 | } else { | 487 | else |
483 | error = -EINVAL; | 488 | error = -EINVAL; |
484 | } | 489 | break; |
485 | break; | 490 | default: |
486 | default: | 491 | error = vcc_setsockopt(sock, level, optname, optval, optlen); |
487 | error = vcc_setsockopt(sock, level, optname, | ||
488 | optval, optlen); | ||
489 | } | 492 | } |
490 | 493 | ||
491 | out: | 494 | out: |
@@ -493,9 +496,8 @@ out: | |||
493 | return error; | 496 | return error; |
494 | } | 497 | } |
495 | 498 | ||
496 | 499 | static int svc_getsockopt(struct socket *sock, int level, int optname, | |
497 | static int svc_getsockopt(struct socket *sock,int level,int optname, | 500 | char __user *optval, int __user *optlen) |
498 | char __user *optval,int __user *optlen) | ||
499 | { | 501 | { |
500 | struct sock *sk = sock->sk; | 502 | struct sock *sk = sock->sk; |
501 | int error = 0, len; | 503 | int error = 0, len; |
@@ -522,7 +524,6 @@ out: | |||
522 | return error; | 524 | return error; |
523 | } | 525 | } |
524 | 526 | ||
525 | |||
526 | static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr, | 527 | static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr, |
527 | int sockaddr_len, int flags) | 528 | int sockaddr_len, int flags) |
528 | { | 529 | { |
@@ -553,7 +554,6 @@ out: | |||
553 | return error; | 554 | return error; |
554 | } | 555 | } |
555 | 556 | ||
556 | |||
557 | static int svc_dropparty(struct socket *sock, int ep_ref) | 557 | static int svc_dropparty(struct socket *sock, int ep_ref) |
558 | { | 558 | { |
559 | DEFINE_WAIT(wait); | 559 | DEFINE_WAIT(wait); |
@@ -580,7 +580,6 @@ out: | |||
580 | return error; | 580 | return error; |
581 | } | 581 | } |
582 | 582 | ||
583 | |||
584 | static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 583 | static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
585 | { | 584 | { |
586 | int error, ep_ref; | 585 | int error, ep_ref; |
@@ -588,29 +587,31 @@ static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
588 | struct atm_vcc *vcc = ATM_SD(sock); | 587 | struct atm_vcc *vcc = ATM_SD(sock); |
589 | 588 | ||
590 | switch (cmd) { | 589 | switch (cmd) { |
591 | case ATM_ADDPARTY: | 590 | case ATM_ADDPARTY: |
592 | if (!test_bit(ATM_VF_SESSION, &vcc->flags)) | 591 | if (!test_bit(ATM_VF_SESSION, &vcc->flags)) |
593 | return -EINVAL; | 592 | return -EINVAL; |
594 | if (copy_from_user(&sa, (void __user *) arg, sizeof(sa))) | 593 | if (copy_from_user(&sa, (void __user *) arg, sizeof(sa))) |
595 | return -EFAULT; | 594 | return -EFAULT; |
596 | error = svc_addparty(sock, (struct sockaddr *) &sa, sizeof(sa), 0); | 595 | error = svc_addparty(sock, (struct sockaddr *)&sa, sizeof(sa), |
597 | break; | 596 | 0); |
598 | case ATM_DROPPARTY: | 597 | break; |
599 | if (!test_bit(ATM_VF_SESSION, &vcc->flags)) | 598 | case ATM_DROPPARTY: |
600 | return -EINVAL; | 599 | if (!test_bit(ATM_VF_SESSION, &vcc->flags)) |
601 | if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int))) | 600 | return -EINVAL; |
602 | return -EFAULT; | 601 | if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int))) |
603 | error = svc_dropparty(sock, ep_ref); | 602 | return -EFAULT; |
604 | break; | 603 | error = svc_dropparty(sock, ep_ref); |
605 | default: | 604 | break; |
606 | error = vcc_ioctl(sock, cmd, arg); | 605 | default: |
606 | error = vcc_ioctl(sock, cmd, arg); | ||
607 | } | 607 | } |
608 | 608 | ||
609 | return error; | 609 | return error; |
610 | } | 610 | } |
611 | 611 | ||
612 | #ifdef CONFIG_COMPAT | 612 | #ifdef CONFIG_COMPAT |
613 | static int svc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 613 | static int svc_compat_ioctl(struct socket *sock, unsigned int cmd, |
614 | unsigned long arg) | ||
614 | { | 615 | { |
615 | /* The definition of ATM_ADDPARTY uses the size of struct atm_iobuf. | 616 | /* The definition of ATM_ADDPARTY uses the size of struct atm_iobuf. |
616 | But actually it takes a struct sockaddr_atmsvc, which doesn't need | 617 | But actually it takes a struct sockaddr_atmsvc, which doesn't need |
@@ -661,13 +662,13 @@ static int svc_create(struct net *net, struct socket *sock, int protocol, | |||
661 | 662 | ||
662 | sock->ops = &svc_proto_ops; | 663 | sock->ops = &svc_proto_ops; |
663 | error = vcc_create(net, sock, protocol, AF_ATMSVC); | 664 | error = vcc_create(net, sock, protocol, AF_ATMSVC); |
664 | if (error) return error; | 665 | if (error) |
666 | return error; | ||
665 | ATM_SD(sock)->local.sas_family = AF_ATMSVC; | 667 | ATM_SD(sock)->local.sas_family = AF_ATMSVC; |
666 | ATM_SD(sock)->remote.sas_family = AF_ATMSVC; | 668 | ATM_SD(sock)->remote.sas_family = AF_ATMSVC; |
667 | return 0; | 669 | return 0; |
668 | } | 670 | } |
669 | 671 | ||
670 | |||
671 | static const struct net_proto_family svc_family_ops = { | 672 | static const struct net_proto_family svc_family_ops = { |
672 | .family = PF_ATMSVC, | 673 | .family = PF_ATMSVC, |
673 | .create = svc_create, | 674 | .create = svc_create, |