Blame view
net/atm/svc.c
16 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 |
/* net/atm/svc.c - ATM SVC sockets */ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ |
99824461e net/atm: Convert ... |
5 |
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 11 12 |
#include <linux/string.h> #include <linux/net.h> /* struct socket, struct proto_ops */ #include <linux/errno.h> /* error codes */ #include <linux/kernel.h> /* printk */ #include <linux/skbuff.h> #include <linux/wait.h> |
174cd4b1e sched/headers: Pr... |
13 |
#include <linux/sched/signal.h> |
1da177e4c Linux-2.6.12-rc2 |
14 15 16 17 18 19 20 21 |
#include <linux/fcntl.h> /* O_NONBLOCK */ #include <linux/init.h> #include <linux/atm.h> /* ATM stuff */ #include <linux/atmsap.h> #include <linux/atmsvc.h> #include <linux/atmdev.h> #include <linux/bitops.h> #include <net/sock.h> /* for sock_no_* */ |
b7d9371be net/atm/svc.c: ch... |
22 |
#include <linux/uaccess.h> |
bc3b2d7fb net: Add export.h... |
23 |
#include <linux/export.h> |
1da177e4c Linux-2.6.12-rc2 |
24 25 26 27 28 |
#include "resources.h" #include "common.h" /* common for PVCs and SVCs */ #include "signaling.h" #include "addr.h" |
b7d9371be net/atm/svc.c: ch... |
29 30 |
static int svc_create(struct net *net, struct socket *sock, int protocol, int kern); |
1da177e4c Linux-2.6.12-rc2 |
31 |
|
1da177e4c Linux-2.6.12-rc2 |
32 33 34 35 36 |
/* * Note: since all this is still nicely synchronized with the signaling demon, * there's no need to protect sleep loops with clis. If signaling is * moved into the kernel, that would change. */ |
b7d9371be net/atm/svc.c: ch... |
37 |
static int svc_shutdown(struct socket *sock, int how) |
1da177e4c Linux-2.6.12-rc2 |
38 39 40 |
{ return 0; } |
1da177e4c Linux-2.6.12-rc2 |
41 42 43 44 45 |
static void svc_disconnect(struct atm_vcc *vcc) { DEFINE_WAIT(wait); struct sk_buff *skb; struct sock *sk = sk_atm(vcc); |
b7d9371be net/atm/svc.c: ch... |
46 47 48 |
pr_debug("%p ", vcc); if (test_bit(ATM_VF_REGIS, &vcc->flags)) { |
b7d9371be net/atm/svc.c: ch... |
49 |
sigd_enq(vcc, as_close, NULL, NULL, NULL); |
de713b579 atm/svc: Fix bloc... |
50 51 52 53 |
for (;;) { prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); if (test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd) break; |
1da177e4c Linux-2.6.12-rc2 |
54 |
schedule(); |
1da177e4c Linux-2.6.12-rc2 |
55 |
} |
aa3951451 net: sk_sleep() h... |
56 |
finish_wait(sk_sleep(sk), &wait); |
1da177e4c Linux-2.6.12-rc2 |
57 58 59 60 61 |
} /* beware - socket is still in use by atmsigd until the last as_indicate has been answered */ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { atm_return(vcc, skb->truesize); |
522400623 [ATM]: Replace DP... |
62 63 |
pr_debug("LISTEN REL "); |
b7d9371be net/atm/svc.c: ch... |
64 |
sigd_enq2(NULL, as_reject, vcc, NULL, NULL, &vcc->qos, 0); |
1da177e4c Linux-2.6.12-rc2 |
65 66 67 68 69 |
dev_kfree_skb(skb); } clear_bit(ATM_VF_REGIS, &vcc->flags); /* ... may retry later */ } |
1da177e4c Linux-2.6.12-rc2 |
70 71 72 73 |
static int svc_release(struct socket *sock) { struct sock *sk = sock->sk; struct atm_vcc *vcc; |
b7d9371be net/atm/svc.c: ch... |
74 |
if (sk) { |
1da177e4c Linux-2.6.12-rc2 |
75 |
vcc = ATM_SD(sock); |
99824461e net/atm: Convert ... |
76 77 |
pr_debug("%p ", vcc); |
1da177e4c Linux-2.6.12-rc2 |
78 |
clear_bit(ATM_VF_READY, &vcc->flags); |
b7d9371be net/atm/svc.c: ch... |
79 80 81 82 83 |
/* * VCC pointer is used as a reference, * so we must not free it (thereby subjecting it to re-use) * before all pending connections are closed */ |
1da177e4c Linux-2.6.12-rc2 |
84 85 86 87 88 |
svc_disconnect(vcc); vcc_release(sock); } return 0; } |
b7d9371be net/atm/svc.c: ch... |
89 90 |
static int svc_bind(struct socket *sock, struct sockaddr *sockaddr, int sockaddr_len) |
1da177e4c Linux-2.6.12-rc2 |
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
{ DEFINE_WAIT(wait); struct sock *sk = sock->sk; struct sockaddr_atmsvc *addr; struct atm_vcc *vcc; int error; if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) 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); |
1da177e4c Linux-2.6.12-rc2 |
110 111 112 113 114 |
addr = (struct sockaddr_atmsvc *) sockaddr; if (addr->sas_family != AF_ATMSVC) { error = -EAFNOSUPPORT; goto out; } |
b7d9371be net/atm/svc.c: ch... |
115 |
clear_bit(ATM_VF_BOUND, &vcc->flags); |
1da177e4c Linux-2.6.12-rc2 |
116 117 |
/* failing rebind will kill old binding */ /* @@@ check memory (de)allocation on rebind */ |
b7d9371be net/atm/svc.c: ch... |
118 |
if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) { |
1da177e4c Linux-2.6.12-rc2 |
119 120 121 122 123 |
error = -EBADFD; goto out; } vcc->local = *addr; set_bit(ATM_VF_WAITING, &vcc->flags); |
b7d9371be net/atm/svc.c: ch... |
124 |
sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local); |
de713b579 atm/svc: Fix bloc... |
125 |
for (;;) { |
aa3951451 net: sk_sleep() h... |
126 |
prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
de713b579 atm/svc: Fix bloc... |
127 128 129 |
if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) break; schedule(); |
1da177e4c Linux-2.6.12-rc2 |
130 |
} |
aa3951451 net: sk_sleep() h... |
131 |
finish_wait(sk_sleep(sk), &wait); |
b7d9371be net/atm/svc.c: ch... |
132 |
clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */ |
1da177e4c Linux-2.6.12-rc2 |
133 134 135 136 |
if (!sigd) { error = -EUNATCH; goto out; } |
f7d57453d [NET] ATM: Fix wh... |
137 |
if (!sk->sk_err) |
b7d9371be net/atm/svc.c: ch... |
138 |
set_bit(ATM_VF_BOUND, &vcc->flags); |
1da177e4c Linux-2.6.12-rc2 |
139 140 141 142 143 |
error = -sk->sk_err; out: release_sock(sk); return error; } |
b7d9371be net/atm/svc.c: ch... |
144 145 |
static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, int sockaddr_len, int flags) |
1da177e4c Linux-2.6.12-rc2 |
146 147 148 149 150 151 |
{ DEFINE_WAIT(wait); struct sock *sk = sock->sk; struct sockaddr_atmsvc *addr; struct atm_vcc *vcc = ATM_SD(sock); int error; |
b7d9371be net/atm/svc.c: ch... |
152 153 |
pr_debug("%p ", vcc); |
1da177e4c Linux-2.6.12-rc2 |
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
lock_sock(sk); if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) { error = -EINVAL; goto out; } switch (sock->state) { default: error = -EINVAL; goto out; case SS_CONNECTED: error = -EISCONN; goto out; case SS_CONNECTING: if (test_bit(ATM_VF_WAITING, &vcc->flags)) { error = -EALREADY; goto out; } sock->state = SS_UNCONNECTED; if (sk->sk_err) { error = -sk->sk_err; goto out; } break; case SS_UNCONNECTED: addr = (struct sockaddr_atmsvc *) sockaddr; if (addr->sas_family != AF_ATMSVC) { error = -EAFNOSUPPORT; goto out; } if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) { error = -EBADFD; goto out; } if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) { error = -EINVAL; goto out; } if (!vcc->qos.txtp.traffic_class && !vcc->qos.rxtp.traffic_class) { error = -EINVAL; goto out; } vcc->remote = *addr; set_bit(ATM_VF_WAITING, &vcc->flags); |
b7d9371be net/atm/svc.c: ch... |
200 |
sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote); |
1da177e4c Linux-2.6.12-rc2 |
201 |
if (flags & O_NONBLOCK) { |
1da177e4c Linux-2.6.12-rc2 |
202 203 204 205 206 |
sock->state = SS_CONNECTING; error = -EINPROGRESS; goto out; } error = 0; |
de713b579 atm/svc: Fix bloc... |
207 |
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1da177e4c Linux-2.6.12-rc2 |
208 209 210 |
while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { schedule(); if (!signal_pending(current)) { |
aa3951451 net: sk_sleep() h... |
211 |
prepare_to_wait(sk_sleep(sk), &wait, |
b7d9371be net/atm/svc.c: ch... |
212 |
TASK_INTERRUPTIBLE); |
1da177e4c Linux-2.6.12-rc2 |
213 214 |
continue; } |
522400623 [ATM]: Replace DP... |
215 216 |
pr_debug("*ABORT* "); |
1da177e4c Linux-2.6.12-rc2 |
217 218 219 220 |
/* * This is tricky: * Kernel ---close--> Demon * Kernel <--close--- Demon |
f7d57453d [NET] ATM: Fix wh... |
221 |
* or |
1da177e4c Linux-2.6.12-rc2 |
222 223 224 225 226 227 228 |
* Kernel ---close--> Demon * Kernel <--error--- Demon * or * Kernel ---close--> Demon * Kernel <--okay---- Demon * Kernel <--close--- Demon */ |
b7d9371be net/atm/svc.c: ch... |
229 |
sigd_enq(vcc, as_close, NULL, NULL, NULL); |
1da177e4c Linux-2.6.12-rc2 |
230 |
while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
aa3951451 net: sk_sleep() h... |
231 |
prepare_to_wait(sk_sleep(sk), &wait, |
b7d9371be net/atm/svc.c: ch... |
232 |
TASK_INTERRUPTIBLE); |
1da177e4c Linux-2.6.12-rc2 |
233 234 235 |
schedule(); } if (!sk->sk_err) |
b7d9371be net/atm/svc.c: ch... |
236 237 |
while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { |
aa3951451 net: sk_sleep() h... |
238 |
prepare_to_wait(sk_sleep(sk), &wait, |
b7d9371be net/atm/svc.c: ch... |
239 |
TASK_INTERRUPTIBLE); |
1da177e4c Linux-2.6.12-rc2 |
240 241 |
schedule(); } |
b7d9371be net/atm/svc.c: ch... |
242 243 244 |
clear_bit(ATM_VF_REGIS, &vcc->flags); clear_bit(ATM_VF_RELEASED, &vcc->flags); clear_bit(ATM_VF_CLOSE, &vcc->flags); |
1da177e4c Linux-2.6.12-rc2 |
245 246 247 248 |
/* we're gone now but may connect later */ error = -EINTR; break; } |
aa3951451 net: sk_sleep() h... |
249 |
finish_wait(sk_sleep(sk), &wait); |
1da177e4c Linux-2.6.12-rc2 |
250 251 252 253 254 255 256 257 258 259 260 |
if (error) goto out; if (!sigd) { error = -EUNATCH; goto out; } if (sk->sk_err) { error = -sk->sk_err; goto out; } } |
391296c90 atm: remove comme... |
261 |
|
1da177e4c Linux-2.6.12-rc2 |
262 263 264 |
vcc->qos.txtp.max_pcr = SELECT_TOP_PCR(vcc->qos.txtp); vcc->qos.txtp.pcr = 0; vcc->qos.txtp.min_pcr = 0; |
391296c90 atm: remove comme... |
265 |
|
b7d9371be net/atm/svc.c: ch... |
266 267 |
error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci); if (!error) |
1da177e4c Linux-2.6.12-rc2 |
268 269 |
sock->state = SS_CONNECTED; else |
b7d9371be net/atm/svc.c: ch... |
270 |
(void)svc_disconnect(vcc); |
1da177e4c Linux-2.6.12-rc2 |
271 272 273 274 |
out: release_sock(sk); return error; } |
b7d9371be net/atm/svc.c: ch... |
275 |
static int svc_listen(struct socket *sock, int backlog) |
1da177e4c Linux-2.6.12-rc2 |
276 277 278 279 280 |
{ DEFINE_WAIT(wait); struct sock *sk = sock->sk; struct atm_vcc *vcc = ATM_SD(sock); int error; |
99824461e net/atm: Convert ... |
281 282 |
pr_debug("%p ", vcc); |
1da177e4c Linux-2.6.12-rc2 |
283 284 |
lock_sock(sk); /* let server handle listen on unbound sockets */ |
b7d9371be net/atm/svc.c: ch... |
285 |
if (test_bit(ATM_VF_SESSION, &vcc->flags)) { |
1da177e4c Linux-2.6.12-rc2 |
286 287 288 |
error = -EINVAL; goto out; } |
17b24b3c9 ATM: CVE-2008-507... |
289 290 291 |
if (test_bit(ATM_VF_LISTEN, &vcc->flags)) { error = -EADDRINUSE; goto out; |
b7d9371be net/atm/svc.c: ch... |
292 |
} |
1da177e4c Linux-2.6.12-rc2 |
293 |
set_bit(ATM_VF_WAITING, &vcc->flags); |
b7d9371be net/atm/svc.c: ch... |
294 |
sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local); |
de713b579 atm/svc: Fix bloc... |
295 |
for (;;) { |
aa3951451 net: sk_sleep() h... |
296 |
prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
de713b579 atm/svc: Fix bloc... |
297 298 299 |
if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) break; schedule(); |
1da177e4c Linux-2.6.12-rc2 |
300 |
} |
aa3951451 net: sk_sleep() h... |
301 |
finish_wait(sk_sleep(sk), &wait); |
1da177e4c Linux-2.6.12-rc2 |
302 303 304 305 |
if (!sigd) { error = -EUNATCH; goto out; } |
b7d9371be net/atm/svc.c: ch... |
306 |
set_bit(ATM_VF_LISTEN, &vcc->flags); |
17b24b3c9 ATM: CVE-2008-507... |
307 |
vcc_insert_socket(sk); |
1da177e4c Linux-2.6.12-rc2 |
308 309 310 311 312 313 |
sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT; error = -sk->sk_err; out: release_sock(sk); return error; } |
cdfbabfb2 net: Work around ... |
314 315 |
static int svc_accept(struct socket *sock, struct socket *newsock, int flags, bool kern) |
1da177e4c Linux-2.6.12-rc2 |
316 317 318 319 320 321 322 323 324 |
{ struct sock *sk = sock->sk; struct sk_buff *skb; struct atmsvc_msg *msg; struct atm_vcc *old_vcc = ATM_SD(sock); struct atm_vcc *new_vcc; int error; lock_sock(sk); |
cdfbabfb2 net: Work around ... |
325 |
error = svc_create(sock_net(sk), newsock, 0, kern); |
1da177e4c Linux-2.6.12-rc2 |
326 327 328 329 |
if (error) goto out; new_vcc = ATM_SD(newsock); |
99824461e net/atm: Convert ... |
330 331 |
pr_debug("%p -> %p ", old_vcc, new_vcc); |
1da177e4c Linux-2.6.12-rc2 |
332 333 |
while (1) { DEFINE_WAIT(wait); |
aa3951451 net: sk_sleep() h... |
334 |
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1da177e4c Linux-2.6.12-rc2 |
335 336 |
while (!(skb = skb_dequeue(&sk->sk_receive_queue)) && sigd) { |
b7d9371be net/atm/svc.c: ch... |
337 338 339 |
if (test_bit(ATM_VF_RELEASED, &old_vcc->flags)) break; if (test_bit(ATM_VF_CLOSE, &old_vcc->flags)) { |
1da177e4c Linux-2.6.12-rc2 |
340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
error = -sk->sk_err; break; } if (flags & O_NONBLOCK) { error = -EAGAIN; break; } release_sock(sk); schedule(); lock_sock(sk); if (signal_pending(current)) { error = -ERESTARTSYS; break; } |
aa3951451 net: sk_sleep() h... |
354 |
prepare_to_wait(sk_sleep(sk), &wait, |
b7d9371be net/atm/svc.c: ch... |
355 |
TASK_INTERRUPTIBLE); |
1da177e4c Linux-2.6.12-rc2 |
356 |
} |
aa3951451 net: sk_sleep() h... |
357 |
finish_wait(sk_sleep(sk), &wait); |
1da177e4c Linux-2.6.12-rc2 |
358 359 360 361 362 363 |
if (error) goto out; if (!skb) { error = -EUNATCH; goto out; } |
b7d9371be net/atm/svc.c: ch... |
364 |
msg = (struct atmsvc_msg *)skb->data; |
1da177e4c Linux-2.6.12-rc2 |
365 |
new_vcc->qos = msg->qos; |
b7d9371be net/atm/svc.c: ch... |
366 |
set_bit(ATM_VF_HASQOS, &new_vcc->flags); |
1da177e4c Linux-2.6.12-rc2 |
367 368 369 370 |
new_vcc->remote = msg->svc; new_vcc->local = msg->local; new_vcc->sap = msg->sap; error = vcc_connect(newsock, msg->pvc.sap_addr.itf, |
b7d9371be net/atm/svc.c: ch... |
371 372 |
msg->pvc.sap_addr.vpi, msg->pvc.sap_addr.vci); |
1da177e4c Linux-2.6.12-rc2 |
373 374 375 |
dev_kfree_skb(skb); sk->sk_ack_backlog--; if (error) { |
b7d9371be net/atm/svc.c: ch... |
376 377 |
sigd_enq2(NULL, as_reject, old_vcc, NULL, NULL, &old_vcc->qos, error); |
1da177e4c Linux-2.6.12-rc2 |
378 379 380 381 382 |
error = error == -EAGAIN ? -EBUSY : error; goto out; } /* wait should be short, so we ignore the non-blocking flag */ set_bit(ATM_VF_WAITING, &new_vcc->flags); |
b7d9371be net/atm/svc.c: ch... |
383 |
sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL); |
de713b579 atm/svc: Fix bloc... |
384 385 386 387 388 |
for (;;) { prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, TASK_UNINTERRUPTIBLE); if (!test_bit(ATM_VF_WAITING, &new_vcc->flags) || !sigd) break; |
1da177e4c Linux-2.6.12-rc2 |
389 390 391 |
release_sock(sk); schedule(); lock_sock(sk); |
1da177e4c Linux-2.6.12-rc2 |
392 |
} |
aa3951451 net: sk_sleep() h... |
393 |
finish_wait(sk_sleep(sk_atm(new_vcc)), &wait); |
1da177e4c Linux-2.6.12-rc2 |
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 |
if (!sigd) { error = -EUNATCH; goto out; } if (!sk_atm(new_vcc)->sk_err) break; if (sk_atm(new_vcc)->sk_err != ERESTARTSYS) { error = -sk_atm(new_vcc)->sk_err; goto out; } } newsock->state = SS_CONNECTED; out: release_sock(sk); return error; } |
b7d9371be net/atm/svc.c: ch... |
410 411 |
static int svc_getname(struct socket *sock, struct sockaddr *sockaddr, int *sockaddr_len, int peer) |
1da177e4c Linux-2.6.12-rc2 |
412 413 414 415 416 |
{ struct sockaddr_atmsvc *addr; *sockaddr_len = sizeof(struct sockaddr_atmsvc); addr = (struct sockaddr_atmsvc *) sockaddr; |
b7d9371be net/atm/svc.c: ch... |
417 418 |
memcpy(addr, peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local, sizeof(struct sockaddr_atmsvc)); |
1da177e4c Linux-2.6.12-rc2 |
419 420 |
return 0; } |
b7d9371be net/atm/svc.c: ch... |
421 |
int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos) |
1da177e4c Linux-2.6.12-rc2 |
422 423 424 425 426 |
{ struct sock *sk = sk_atm(vcc); DEFINE_WAIT(wait); set_bit(ATM_VF_WAITING, &vcc->flags); |
b7d9371be net/atm/svc.c: ch... |
427 |
sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0); |
de713b579 atm/svc: Fix bloc... |
428 |
for (;;) { |
aa3951451 net: sk_sleep() h... |
429 |
prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
de713b579 atm/svc: Fix bloc... |
430 431 432 433 434 |
if (!test_bit(ATM_VF_WAITING, &vcc->flags) || test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd) { break; } schedule(); |
1da177e4c Linux-2.6.12-rc2 |
435 |
} |
aa3951451 net: sk_sleep() h... |
436 |
finish_wait(sk_sleep(sk), &wait); |
b7d9371be net/atm/svc.c: ch... |
437 438 |
if (!sigd) return -EUNATCH; |
1da177e4c Linux-2.6.12-rc2 |
439 440 |
return -sk->sk_err; } |
1da177e4c Linux-2.6.12-rc2 |
441 |
static int svc_setsockopt(struct socket *sock, int level, int optname, |
b7058842c net: Make setsock... |
442 |
char __user *optval, unsigned int optlen) |
1da177e4c Linux-2.6.12-rc2 |
443 444 445 446 447 448 449 |
{ struct sock *sk = sock->sk; struct atm_vcc *vcc = ATM_SD(sock); int value, error = 0; lock_sock(sk); switch (optname) { |
b7d9371be net/atm/svc.c: ch... |
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 |
case SO_ATMSAP: if (level != SOL_ATM || optlen != sizeof(struct atm_sap)) { error = -EINVAL; goto out; } if (copy_from_user(&vcc->sap, optval, optlen)) { error = -EFAULT; goto out; } set_bit(ATM_VF_HASSAP, &vcc->flags); break; case SO_MULTIPOINT: if (level != SOL_ATM || optlen != sizeof(int)) { error = -EINVAL; goto out; } if (get_user(value, (int __user *)optval)) { error = -EFAULT; goto out; } if (value == 1) set_bit(ATM_VF_SESSION, &vcc->flags); else if (value == 0) clear_bit(ATM_VF_SESSION, &vcc->flags); else error = -EINVAL; break; default: error = vcc_setsockopt(sock, level, optname, optval, optlen); |
1da177e4c Linux-2.6.12-rc2 |
479 480 481 482 483 484 |
} out: release_sock(sk); return error; } |
b7d9371be net/atm/svc.c: ch... |
485 486 |
static int svc_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) |
1da177e4c Linux-2.6.12-rc2 |
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 |
{ struct sock *sk = sock->sk; int error = 0, len; lock_sock(sk); if (!__SO_LEVEL_MATCH(optname, level) || optname != SO_ATMSAP) { error = vcc_getsockopt(sock, level, optname, optval, optlen); goto out; } 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; } |
1da177e4c Linux-2.6.12-rc2 |
512 513 514 515 516 517 518 519 520 521 |
static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr, int sockaddr_len, int flags) { DEFINE_WAIT(wait); struct sock *sk = sock->sk; struct atm_vcc *vcc = ATM_SD(sock); int error; lock_sock(sk); set_bit(ATM_VF_WAITING, &vcc->flags); |
1da177e4c Linux-2.6.12-rc2 |
522 |
sigd_enq(vcc, as_addparty, NULL, NULL, |
f7d57453d [NET] ATM: Fix wh... |
523 |
(struct sockaddr_atmsvc *) sockaddr); |
1da177e4c Linux-2.6.12-rc2 |
524 |
if (flags & O_NONBLOCK) { |
1da177e4c Linux-2.6.12-rc2 |
525 526 527 |
error = -EINPROGRESS; goto out; } |
99824461e net/atm: Convert ... |
528 529 |
pr_debug("added wait queue "); |
de713b579 atm/svc: Fix bloc... |
530 |
for (;;) { |
aa3951451 net: sk_sleep() h... |
531 |
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
de713b579 atm/svc: Fix bloc... |
532 533 534 |
if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) break; schedule(); |
1da177e4c Linux-2.6.12-rc2 |
535 |
} |
aa3951451 net: sk_sleep() h... |
536 |
finish_wait(sk_sleep(sk), &wait); |
c685293aa net/atm: sk_err_s... |
537 |
error = -xchg(&sk->sk_err_soft, 0); |
1da177e4c Linux-2.6.12-rc2 |
538 539 540 541 |
out: release_sock(sk); return error; } |
1da177e4c Linux-2.6.12-rc2 |
542 543 544 545 546 547 548 549 550 |
static int svc_dropparty(struct socket *sock, int ep_ref) { DEFINE_WAIT(wait); struct sock *sk = sock->sk; struct atm_vcc *vcc = ATM_SD(sock); int error; lock_sock(sk); set_bit(ATM_VF_WAITING, &vcc->flags); |
1da177e4c Linux-2.6.12-rc2 |
551 |
sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref); |
de713b579 atm/svc: Fix bloc... |
552 |
for (;;) { |
aa3951451 net: sk_sleep() h... |
553 |
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
de713b579 atm/svc: Fix bloc... |
554 555 556 |
if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) break; schedule(); |
1da177e4c Linux-2.6.12-rc2 |
557 |
} |
aa3951451 net: sk_sleep() h... |
558 |
finish_wait(sk_sleep(sk), &wait); |
1da177e4c Linux-2.6.12-rc2 |
559 560 561 562 |
if (!sigd) { error = -EUNATCH; goto out; } |
c685293aa net/atm: sk_err_s... |
563 |
error = -xchg(&sk->sk_err_soft, 0); |
1da177e4c Linux-2.6.12-rc2 |
564 565 566 567 |
out: release_sock(sk); return error; } |
1da177e4c Linux-2.6.12-rc2 |
568 569 |
static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { |
f7d57453d [NET] ATM: Fix wh... |
570 571 |
int error, ep_ref; struct sockaddr_atmsvc sa; |
1da177e4c Linux-2.6.12-rc2 |
572 |
struct atm_vcc *vcc = ATM_SD(sock); |
f7d57453d [NET] ATM: Fix wh... |
573 |
|
1da177e4c Linux-2.6.12-rc2 |
574 |
switch (cmd) { |
b7d9371be net/atm/svc.c: ch... |
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 |
case ATM_ADDPARTY: if (!test_bit(ATM_VF_SESSION, &vcc->flags)) return -EINVAL; if (copy_from_user(&sa, (void __user *) arg, sizeof(sa))) return -EFAULT; error = svc_addparty(sock, (struct sockaddr *)&sa, sizeof(sa), 0); break; case ATM_DROPPARTY: if (!test_bit(ATM_VF_SESSION, &vcc->flags)) return -EINVAL; if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int))) return -EFAULT; error = svc_dropparty(sock, ep_ref); break; default: error = vcc_ioctl(sock, cmd, arg); |
1da177e4c Linux-2.6.12-rc2 |
592 593 594 595 |
} return error; } |
8865c418c atm: 32-bit ioctl... |
596 |
#ifdef CONFIG_COMPAT |
b7d9371be net/atm/svc.c: ch... |
597 598 |
static int svc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
8865c418c atm: 32-bit ioctl... |
599 600 601 602 603 604 605 606 607 608 609 610 611 |
{ /* The definition of ATM_ADDPARTY uses the size of struct atm_iobuf. But actually it takes a struct sockaddr_atmsvc, which doesn't need compat handling. So all we have to do is fix up cmd... */ if (cmd == COMPAT_ATM_ADDPARTY) cmd = ATM_ADDPARTY; if (cmd == ATM_ADDPARTY || cmd == ATM_DROPPARTY) return svc_ioctl(sock, cmd, arg); else return vcc_compat_ioctl(sock, cmd, arg); } #endif /* CONFIG_COMPAT */ |
90ddc4f04 [NET]: move struc... |
612 |
static const struct proto_ops svc_proto_ops = { |
1da177e4c Linux-2.6.12-rc2 |
613 614 615 616 617 618 619 620 621 622 623 |
.family = PF_ATMSVC, .owner = THIS_MODULE, .release = svc_release, .bind = svc_bind, .connect = svc_connect, .socketpair = sock_no_socketpair, .accept = svc_accept, .getname = svc_getname, .poll = vcc_poll, .ioctl = svc_ioctl, |
8865c418c atm: 32-bit ioctl... |
624 625 626 |
#ifdef CONFIG_COMPAT .compat_ioctl = svc_compat_ioctl, #endif |
1da177e4c Linux-2.6.12-rc2 |
627 628 629 630 631 632 633 634 635 |
.listen = svc_listen, .shutdown = svc_shutdown, .setsockopt = svc_setsockopt, .getsockopt = svc_getsockopt, .sendmsg = vcc_sendmsg, .recvmsg = vcc_recvmsg, .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, }; |
3f378b684 net: pass kern to... |
636 637 |
static int svc_create(struct net *net, struct socket *sock, int protocol, int kern) |
1da177e4c Linux-2.6.12-rc2 |
638 639 |
{ int error; |
09ad9bc75 net: use net_eq t... |
640 |
if (!net_eq(net, &init_net)) |
1b8d7ae42 [NET]: Make socke... |
641 |
return -EAFNOSUPPORT; |
1da177e4c Linux-2.6.12-rc2 |
642 |
sock->ops = &svc_proto_ops; |
11aa9c28b net: Pass kern fr... |
643 |
error = vcc_create(net, sock, protocol, AF_ATMSVC, kern); |
b7d9371be net/atm/svc.c: ch... |
644 645 |
if (error) return error; |
1da177e4c Linux-2.6.12-rc2 |
646 647 648 649 |
ATM_SD(sock)->local.sas_family = AF_ATMSVC; ATM_SD(sock)->remote.sas_family = AF_ATMSVC; return 0; } |
ec1b4cf74 net: mark net_pro... |
650 |
static const struct net_proto_family svc_family_ops = { |
1da177e4c Linux-2.6.12-rc2 |
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 |
.family = PF_ATMSVC, .create = svc_create, .owner = THIS_MODULE, }; /* * Initialize the ATM SVC protocol family */ int __init atmsvc_init(void) { return sock_register(&svc_family_ops); } void atmsvc_exit(void) { sock_unregister(PF_ATMSVC); } |