Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / net / atm / common.c
blobea0ad690a57a16b5657a265d1683b97647ebc81a
1 /* net/atm/common.c - ATM sockets (common part for PVC and SVC) */
3 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
6 #include <linux/config.h>
7 #include <linux/module.h>
8 #include <linux/net.h> /* struct socket, struct net_proto, struct
9 proto_ops */
10 #include <linux/atm.h> /* ATM stuff */
11 #include <linux/atmdev.h>
12 #include <linux/atmclip.h> /* CLIP_*ENCAP */
13 #include <linux/atmarp.h> /* manifest constants */
14 #include <linux/sonet.h> /* for ioctls */
15 #include <linux/socket.h> /* SOL_SOCKET */
16 #include <linux/errno.h> /* error codes */
17 #include <linux/capability.h>
18 #include <linux/mm.h> /* verify_area */
19 #include <linux/sched.h>
20 #include <linux/time.h> /* struct timeval */
21 #include <linux/skbuff.h>
22 #include <linux/bitops.h>
23 #include <net/sock.h> /* struct sock */
25 #include <asm/uaccess.h>
26 #include <asm/atomic.h>
27 #include <asm/poll.h>
29 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
30 #include <linux/atmlec.h>
31 #include "lec.h"
32 #include "lec_arpc.h"
33 struct atm_lane_ops atm_lane_ops;
34 #endif
35 #ifdef CONFIG_ATM_LANE_MODULE
36 EXPORT_SYMBOL(atm_lane_ops);
37 #endif
39 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
40 #include <linux/atmmpc.h>
41 #include "mpc.h"
42 struct atm_mpoa_ops atm_mpoa_ops;
43 #endif
44 #ifdef CONFIG_ATM_MPOA_MODULE
45 EXPORT_SYMBOL(atm_mpoa_ops);
46 #ifndef CONFIG_ATM_LANE_MODULE
47 EXPORT_SYMBOL(atm_lane_ops);
48 #endif
49 #endif
51 #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
52 #include <linux/atm_tcp.h>
53 #ifdef CONFIG_ATM_TCP_MODULE
54 struct atm_tcp_ops atm_tcp_ops;
55 EXPORT_SYMBOL(atm_tcp_ops);
56 #endif
57 #endif
59 #include "resources.h" /* atm_find_dev */
60 #include "common.h" /* prototypes */
61 #include "protocols.h" /* atm_init_<transport> */
62 #include "addr.h" /* address registry */
63 #ifdef CONFIG_ATM_CLIP
64 #include <net/atmclip.h> /* for clip_create */
65 #endif
66 #include "signaling.h" /* for WAITING and sigd_attach */
69 #if 0
70 #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
71 #else
72 #define DPRINTK(format,args...)
73 #endif
75 spinlock_t atm_dev_lock = SPIN_LOCK_UNLOCKED;
77 static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
79 struct sk_buff *skb;
81 if (atomic_read(&vcc->tx_inuse) && !atm_may_send(vcc,size)) {
82 DPRINTK("Sorry: tx_inuse = %d, size = %d, sndbuf = %d\n",
83 atomic_read(&vcc->tx_inuse),size,vcc->sk->sndbuf);
84 return NULL;
86 while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
87 DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->tx_inuse),skb->truesize);
88 atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
89 return skb;
93 int atm_create(struct socket *sock,int protocol,int family)
95 struct sock *sk;
96 struct atm_vcc *vcc;
98 sock->sk = NULL;
99 if (sock->type == SOCK_STREAM) return -EINVAL;
100 if (!(sk = alloc_atm_vcc_sk(family))) return -ENOMEM;
101 vcc = sk->protinfo.af_atm;
102 memset(&vcc->flags,0,sizeof(vcc->flags));
103 vcc->dev = NULL;
104 vcc->family = sock->ops->family;
105 vcc->alloc_tx = alloc_tx;
106 vcc->callback = NULL;
107 memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
108 memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
109 vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
110 atomic_set(&vcc->tx_inuse,0);
111 atomic_set(&vcc->rx_inuse,0);
112 vcc->push = NULL;
113 vcc->pop = NULL;
114 vcc->push_oam = NULL;
115 vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
116 vcc->atm_options = vcc->aal_options = 0;
117 vcc->timestamp.tv_sec = vcc->timestamp.tv_usec = 0;
118 init_waitqueue_head(&vcc->sleep);
119 skb_queue_head_init(&vcc->recvq);
120 skb_queue_head_init(&vcc->listenq);
121 sk->sleep = &vcc->sleep;
122 sock->sk = sk;
123 return 0;
127 void atm_release_vcc_sk(struct sock *sk,int free_sk)
129 struct atm_vcc *vcc;
130 struct sk_buff *skb;
132 vcc = sk->protinfo.af_atm;
133 clear_bit(ATM_VF_READY,&vcc->flags);
134 if (vcc->dev) {
135 if (vcc->dev->ops->close) vcc->dev->ops->close(vcc);
136 if (vcc->push) vcc->push(vcc,NULL); /* atmarpd has no push */
137 while ((skb = skb_dequeue(&vcc->recvq))) {
138 atm_return(vcc,skb->truesize);
139 if (vcc->dev->ops->free_rx_skb)
140 vcc->dev->ops->free_rx_skb(vcc,skb);
141 else kfree_skb(skb);
143 spin_lock (&atm_dev_lock);
144 fops_put (vcc->dev->ops);
145 if (atomic_read(&vcc->rx_inuse))
146 printk(KERN_WARNING "atm_release_vcc: strange ... "
147 "rx_inuse == %d after closing\n",
148 atomic_read(&vcc->rx_inuse));
149 bind_vcc(vcc,NULL);
150 } else
151 spin_lock (&atm_dev_lock);
153 if (free_sk) free_atm_vcc_sk(sk);
155 spin_unlock (&atm_dev_lock);
159 int atm_release(struct socket *sock)
161 if (sock->sk)
162 atm_release_vcc_sk(sock->sk,1);
163 return 0;
167 void atm_async_release_vcc(struct atm_vcc *vcc,int reply)
169 set_bit(ATM_VF_CLOSE,&vcc->flags);
170 vcc->reply = reply;
171 wake_up(&vcc->sleep);
175 EXPORT_SYMBOL(atm_async_release_vcc);
178 static int adjust_tp(struct atm_trafprm *tp,unsigned char aal)
180 int max_sdu;
182 if (!tp->traffic_class) return 0;
183 switch (aal) {
184 case ATM_AAL0:
185 max_sdu = ATM_CELL_SIZE-1;
186 break;
187 case ATM_AAL34:
188 max_sdu = ATM_MAX_AAL34_PDU;
189 break;
190 default:
191 printk(KERN_WARNING "ATM: AAL problems ... "
192 "(%d)\n",aal);
193 /* fall through */
194 case ATM_AAL5:
195 max_sdu = ATM_MAX_AAL5_PDU;
197 if (!tp->max_sdu) tp->max_sdu = max_sdu;
198 else if (tp->max_sdu > max_sdu) return -EINVAL;
199 if (!tp->max_cdv) tp->max_cdv = ATM_MAX_CDV;
200 return 0;
204 static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
205 int vci)
207 int error;
209 if ((vpi != ATM_VPI_UNSPEC && vpi != ATM_VPI_ANY &&
210 vpi >> dev->ci_range.vpi_bits) || (vci != ATM_VCI_UNSPEC &&
211 vci != ATM_VCI_ANY && vci >> dev->ci_range.vci_bits))
212 return -EINVAL;
213 if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE))
214 return -EPERM;
215 error = 0;
216 bind_vcc(vcc,dev);
217 switch (vcc->qos.aal) {
218 case ATM_AAL0:
219 error = atm_init_aal0(vcc);
220 vcc->stats = &dev->stats.aal0;
221 break;
222 case ATM_AAL34:
223 error = atm_init_aal34(vcc);
224 vcc->stats = &dev->stats.aal34;
225 break;
226 case ATM_NO_AAL:
227 /* ATM_AAL5 is also used in the "0 for default" case */
228 vcc->qos.aal = ATM_AAL5;
229 /* fall through */
230 case ATM_AAL5:
231 error = atm_init_aal5(vcc);
232 vcc->stats = &dev->stats.aal5;
233 break;
234 default:
235 error = -EPROTOTYPE;
237 if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal);
238 if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal);
239 if (error) {
240 bind_vcc(vcc,NULL);
241 return error;
243 DPRINTK("VCC %d.%d, AAL %d\n",vpi,vci,vcc->qos.aal);
244 DPRINTK(" TX: %d, PCR %d..%d, SDU %d\n",vcc->qos.txtp.traffic_class,
245 vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu);
246 DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class,
247 vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu);
248 fops_get (dev->ops);
249 if (dev->ops->open) {
250 error = dev->ops->open(vcc,vpi,vci);
251 if (error) {
252 fops_put (dev->ops);
253 bind_vcc(vcc,NULL);
254 return error;
257 return 0;
261 static int atm_do_connect(struct atm_vcc *vcc,int itf,int vpi,int vci)
263 struct atm_dev *dev;
264 int return_val;
266 spin_lock (&atm_dev_lock);
267 dev = atm_find_dev(itf);
268 if (!dev)
269 return_val = -ENODEV;
270 else
271 return_val = atm_do_connect_dev(vcc,dev,vpi,vci);
273 spin_unlock (&atm_dev_lock);
275 return return_val;
279 int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci)
281 if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC)
282 clear_bit(ATM_VF_PARTIAL,&vcc->flags);
283 else if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) return -EINVAL;
284 printk(KERN_DEBUG "atm_connect (TX: cl %d,bw %d-%d,sdu %d; "
285 "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n",
286 vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr,
287 vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu,
288 vcc->qos.rxtp.traffic_class,vcc->qos.rxtp.min_pcr,
289 vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu,
290 vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" :
291 " ??? code ",vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal);
292 if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD;
293 if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS ||
294 vcc->qos.rxtp.traffic_class == ATM_ANYCLASS)
295 return -EINVAL;
296 if (itf != ATM_ITF_ANY) {
297 int error;
299 error = atm_do_connect(vcc,itf,vpi,vci);
300 if (error) return error;
302 else {
303 struct atm_dev *dev;
305 spin_lock (&atm_dev_lock);
306 for (dev = atm_devs; dev; dev = dev->next)
307 if (!atm_do_connect_dev(vcc,dev,vpi,vci)) break;
308 spin_unlock (&atm_dev_lock);
309 if (!dev) return -ENODEV;
311 if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
312 set_bit(ATM_VF_PARTIAL,&vcc->flags);
313 return 0;
317 int atm_connect(struct socket *sock,int itf,short vpi,int vci)
319 int error;
321 DPRINTK("atm_connect (vpi %d, vci %d)\n",vpi,vci);
322 if (sock->state == SS_CONNECTED) return -EISCONN;
323 if (sock->state != SS_UNCONNECTED) return -EINVAL;
324 if (!(vpi || vci)) return -EINVAL;
325 error = atm_connect_vcc(ATM_SD(sock),itf,vpi,vci);
326 if (error) return error;
327 if (test_bit(ATM_VF_READY,&ATM_SD(sock)->flags))
328 sock->state = SS_CONNECTED;
329 return 0;
333 int atm_recvmsg(struct socket *sock,struct msghdr *m,int total_len,
334 int flags,struct scm_cookie *scm)
336 DECLARE_WAITQUEUE(wait,current);
337 struct atm_vcc *vcc;
338 struct sk_buff *skb;
339 int eff_len,error;
340 void *buff;
341 int size;
343 if (sock->state != SS_CONNECTED) return -ENOTCONN;
344 if (flags & ~MSG_DONTWAIT) return -EOPNOTSUPP;
345 if (m->msg_iovlen != 1) return -ENOSYS; /* fix this later @@@ */
346 buff = m->msg_iov->iov_base;
347 size = m->msg_iov->iov_len;
348 vcc = ATM_SD(sock);
349 add_wait_queue(&vcc->sleep,&wait);
350 set_current_state(TASK_INTERRUPTIBLE);
351 error = 1; /* <= 0 is error */
352 while (!(skb = skb_dequeue(&vcc->recvq))) {
353 if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
354 test_bit(ATM_VF_CLOSE,&vcc->flags)) {
355 error = vcc->reply;
356 break;
358 if (!test_bit(ATM_VF_READY,&vcc->flags)) {
359 error = 0;
360 break;
362 if (flags & MSG_DONTWAIT) {
363 error = -EAGAIN;
364 break;
366 schedule();
367 set_current_state(TASK_INTERRUPTIBLE);
368 if (signal_pending(current)) {
369 error = -ERESTARTSYS;
370 break;
373 set_current_state(TASK_RUNNING);
374 remove_wait_queue(&vcc->sleep,&wait);
375 if (error <= 0) return error;
376 vcc->timestamp = skb->stamp;
377 eff_len = skb->len > size ? size : skb->len;
378 if (vcc->dev->ops->feedback)
379 vcc->dev->ops->feedback(vcc,skb,(unsigned long) skb->data,
380 (unsigned long) buff,eff_len);
381 DPRINTK("RcvM %d -= %d\n",atomic_read(&vcc->rx_inuse),skb->truesize);
382 atm_return(vcc,skb->truesize);
383 if (ATM_SKB(skb)->iovcnt) { /* @@@ hack */
384 /* iovcnt set, use scatter-gather for receive */
385 int el, cnt;
386 struct iovec *iov = (struct iovec *)skb->data;
387 unsigned char *p = (unsigned char *)buff;
389 el = eff_len;
390 error = 0;
391 for (cnt = 0; (cnt < ATM_SKB(skb)->iovcnt) && el; cnt++) {
392 /*printk("s-g???: %p -> %p (%d)\n",iov->iov_base,p,iov->iov_len);*/
393 error = copy_to_user(p,iov->iov_base,
394 (iov->iov_len > el) ? el : iov->iov_len) ?
395 -EFAULT : 0;
396 if (error) break;
397 p += iov->iov_len;
398 el -= (iov->iov_len > el)?el:iov->iov_len;
399 iov++;
401 if (!vcc->dev->ops->free_rx_skb) kfree_skb(skb);
402 else vcc->dev->ops->free_rx_skb(vcc, skb);
403 return error ? error : eff_len;
405 error = copy_to_user(buff,skb->data,eff_len) ? -EFAULT : 0;
406 if (!vcc->dev->ops->free_rx_skb) kfree_skb(skb);
407 else vcc->dev->ops->free_rx_skb(vcc, skb);
408 return error ? error : eff_len;
412 int atm_sendmsg(struct socket *sock,struct msghdr *m,int total_len,
413 struct scm_cookie *scm)
415 DECLARE_WAITQUEUE(wait,current);
416 struct atm_vcc *vcc;
417 struct sk_buff *skb;
418 int eff,error;
419 const void *buff;
420 int size;
422 if (sock->state != SS_CONNECTED) return -ENOTCONN;
423 if (m->msg_name) return -EISCONN;
424 if (m->msg_iovlen != 1) return -ENOSYS; /* fix this later @@@ */
425 buff = m->msg_iov->iov_base;
426 size = m->msg_iov->iov_len;
427 vcc = ATM_SD(sock);
428 if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
429 test_bit(ATM_VF_CLOSE,&vcc->flags))
430 return vcc->reply;
431 if (!test_bit(ATM_VF_READY,&vcc->flags)) return -EPIPE;
432 if (!size) return 0;
433 if (size < 0 || size > vcc->qos.txtp.max_sdu) return -EMSGSIZE;
434 /* verify_area is done by net/socket.c */
435 eff = (size+3) & ~3; /* align to word boundary */
436 add_wait_queue(&vcc->sleep,&wait);
437 set_current_state(TASK_INTERRUPTIBLE);
438 error = 0;
439 while (!(skb = vcc->alloc_tx(vcc,eff))) {
440 if (m->msg_flags & MSG_DONTWAIT) {
441 error = -EAGAIN;
442 break;
444 schedule();
445 set_current_state(TASK_INTERRUPTIBLE);
446 if (signal_pending(current)) {
447 error = -ERESTARTSYS;
448 break;
450 if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
451 test_bit(ATM_VF_CLOSE,&vcc->flags)) {
452 error = vcc->reply;
453 break;
455 if (!test_bit(ATM_VF_READY,&vcc->flags)) {
456 error = -EPIPE;
457 break;
460 set_current_state(TASK_RUNNING);
461 remove_wait_queue(&vcc->sleep,&wait);
462 if (error) return error;
463 skb->dev = NULL; /* for paths shared with net_device interfaces */
464 ATM_SKB(skb)->iovcnt = 0;
465 ATM_SKB(skb)->atm_options = vcc->atm_options;
466 if (copy_from_user(skb_put(skb,size),buff,size)) {
467 kfree_skb(skb);
468 return -EFAULT;
470 if (eff != size) memset(skb->data+size,0,eff-size);
471 error = vcc->dev->ops->send(vcc,skb);
472 return error ? error : size;
476 unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait)
478 struct atm_vcc *vcc;
479 unsigned int mask;
481 vcc = ATM_SD(sock);
482 poll_wait(file,&vcc->sleep,wait);
483 mask = 0;
484 if (skb_peek(&vcc->recvq) || skb_peek(&vcc->listenq))
485 mask |= POLLIN | POLLRDNORM;
486 if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
487 test_bit(ATM_VF_CLOSE,&vcc->flags))
488 mask |= POLLHUP;
489 if (sock->state != SS_CONNECTING) {
490 if (vcc->qos.txtp.traffic_class != ATM_NONE &&
491 vcc->qos.txtp.max_sdu+atomic_read(&vcc->tx_inuse)+
492 ATM_PDU_OVHD <= vcc->sk->sndbuf)
493 mask |= POLLOUT | POLLWRNORM;
495 else if (vcc->reply != WAITING) {
496 mask |= POLLOUT | POLLWRNORM;
497 if (vcc->reply) mask |= POLLERR;
499 return mask;
503 static void copy_aal_stats(struct k_atm_aal_stats *from,
504 struct atm_aal_stats *to)
506 #define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
507 __AAL_STAT_ITEMS
508 #undef __HANDLE_ITEM
512 static void subtract_aal_stats(struct k_atm_aal_stats *from,
513 struct atm_aal_stats *to)
515 #define __HANDLE_ITEM(i) atomic_sub(to->i,&from->i)
516 __AAL_STAT_ITEMS
517 #undef __HANDLE_ITEM
521 static int fetch_stats(struct atm_dev *dev,struct atm_dev_stats *arg,int zero)
523 struct atm_dev_stats tmp;
524 int error = 0;
526 copy_aal_stats(&dev->stats.aal0,&tmp.aal0);
527 copy_aal_stats(&dev->stats.aal34,&tmp.aal34);
528 copy_aal_stats(&dev->stats.aal5,&tmp.aal5);
529 if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp));
530 if (zero && !error) {
531 subtract_aal_stats(&dev->stats.aal0,&tmp.aal0);
532 subtract_aal_stats(&dev->stats.aal34,&tmp.aal34);
533 subtract_aal_stats(&dev->stats.aal5,&tmp.aal5);
535 return error ? -EFAULT : 0;
539 int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
541 struct atm_dev *dev;
542 struct atm_vcc *vcc;
543 int *tmp_buf;
544 void *buf;
545 int error,len,size,number, ret_val;
547 ret_val = 0;
548 spin_lock (&atm_dev_lock);
549 vcc = ATM_SD(sock);
550 switch (cmd) {
551 case SIOCOUTQ:
552 if (sock->state != SS_CONNECTED ||
553 !test_bit(ATM_VF_READY,&vcc->flags)) {
554 ret_val = -EINVAL;
555 goto done;
557 ret_val = put_user(vcc->sk->sndbuf-
558 atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD,
559 (int *) arg) ? -EFAULT : 0;
560 goto done;
561 case SIOCINQ:
563 struct sk_buff *skb;
565 if (sock->state != SS_CONNECTED) {
566 ret_val = -EINVAL;
567 goto done;
569 skb = skb_peek(&vcc->recvq);
570 ret_val = put_user(skb ? skb->len : 0,(int *) arg)
571 ? -EFAULT : 0;
572 goto done;
574 case ATM_GETNAMES:
575 if (get_user(buf,
576 &((struct atm_iobuf *) arg)->buffer)) {
577 ret_val = -EFAULT;
578 goto done;
580 if (get_user(len,
581 &((struct atm_iobuf *) arg)->length)) {
582 ret_val = -EFAULT;
583 goto done;
585 size = 0;
586 for (dev = atm_devs; dev; dev = dev->next)
587 size += sizeof(int);
588 if (size > len) {
589 ret_val = -E2BIG;
590 goto done;
592 tmp_buf = kmalloc(size,GFP_KERNEL);
593 if (!tmp_buf) {
594 ret_val = -ENOMEM;
595 goto done;
597 for (dev = atm_devs; dev; dev = dev->next)
598 *tmp_buf++ = dev->number;
599 if (copy_to_user(buf,(char *) tmp_buf-size,size)) {
600 ret_val = -EFAULT;
601 goto done;
603 ret_val = put_user(size,
604 &((struct atm_iobuf *) arg)->length) ? -EFAULT : 0;
605 goto done;
606 case SIOCGSTAMP: /* borrowed from IP */
607 if (!vcc->timestamp.tv_sec) {
608 ret_val = -ENOENT;
609 goto done;
611 vcc->timestamp.tv_sec += vcc->timestamp.tv_usec/1000000;
612 vcc->timestamp.tv_usec %= 1000000;
613 ret_val = copy_to_user((void *) arg,&vcc->timestamp,
614 sizeof(struct timeval)) ? -EFAULT : 0;
615 goto done;
616 case ATM_SETSC:
617 printk(KERN_WARNING "ATM_SETSC is obsolete\n");
618 ret_val = 0;
619 goto done;
620 case ATMSIGD_CTRL:
621 if (!capable(CAP_NET_ADMIN)) {
622 ret_val = -EPERM;
623 goto done;
626 * The user/kernel protocol for exchanging signalling
627 * info uses kernel pointers as opaque references,
628 * so the holder of the file descriptor can scribble
629 * on the kernel... so we should make sure that we
630 * have the same privledges that /proc/kcore needs
632 if (!capable(CAP_SYS_RAWIO)) {
633 ret_val = -EPERM;
634 goto done;
636 error = sigd_attach(vcc);
637 if (!error) sock->state = SS_CONNECTED;
638 ret_val = error;
639 goto done;
640 #ifdef CONFIG_ATM_CLIP
641 case SIOCMKCLIP:
642 if (!capable(CAP_NET_ADMIN))
643 ret_val = -EPERM;
644 else
645 ret_val = clip_create(arg);
646 goto done;
647 case ATMARPD_CTRL:
648 if (!capable(CAP_NET_ADMIN)) {
649 ret_val = -EPERM;
650 goto done;
652 error = atm_init_atmarp(vcc);
653 if (!error) sock->state = SS_CONNECTED;
654 ret_val = error;
655 goto done;
656 case ATMARP_MKIP:
657 if (!capable(CAP_NET_ADMIN))
658 ret_val = -EPERM;
659 else
660 ret_val = clip_mkip(vcc,arg);
661 goto done;
662 case ATMARP_SETENTRY:
663 if (!capable(CAP_NET_ADMIN))
664 ret_val = -EPERM;
665 else
666 ret_val = clip_setentry(vcc,arg);
667 goto done;
668 case ATMARP_ENCAP:
669 if (!capable(CAP_NET_ADMIN))
670 ret_val = -EPERM;
671 else
672 ret_val = clip_encap(vcc,arg);
673 goto done;
674 #endif
675 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
676 case ATMLEC_CTRL:
677 if (!capable(CAP_NET_ADMIN)) {
678 ret_val = -EPERM;
679 goto done;
681 if (atm_lane_ops.lecd_attach == NULL)
682 atm_lane_init();
683 if (atm_lane_ops.lecd_attach == NULL) { /* try again */
684 ret_val = -ENOSYS;
685 goto done;
687 error = atm_lane_ops.lecd_attach(vcc, (int)arg);
688 if (error >= 0) sock->state = SS_CONNECTED;
689 ret_val = error;
690 goto done;
691 case ATMLEC_MCAST:
692 if (!capable(CAP_NET_ADMIN))
693 ret_val = -EPERM;
694 else
695 ret_val = atm_lane_ops.mcast_attach(vcc, (int)arg);
696 goto done;
697 case ATMLEC_DATA:
698 if (!capable(CAP_NET_ADMIN))
699 ret_val = -EPERM;
700 else
701 ret_val = atm_lane_ops.vcc_attach(vcc, (void*)arg);
702 goto done;
703 #endif
704 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
705 case ATMMPC_CTRL:
706 if (!capable(CAP_NET_ADMIN)) {
707 ret_val = -EPERM;
708 goto done;
710 if (atm_mpoa_ops.mpoad_attach == NULL)
711 atm_mpoa_init();
712 if (atm_mpoa_ops.mpoad_attach == NULL) { /* try again */
713 ret_val = -ENOSYS;
714 goto done;
716 error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
717 if (error >= 0) sock->state = SS_CONNECTED;
718 ret_val = error;
719 goto done;
720 case ATMMPC_DATA:
721 if (!capable(CAP_NET_ADMIN))
722 ret_val = -EPERM;
723 else
724 ret_val = atm_mpoa_ops.vcc_attach(vcc, arg);
725 goto done;
726 #endif
727 #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
728 case SIOCSIFATMTCP:
729 if (!capable(CAP_NET_ADMIN)) {
730 ret_val = -EPERM;
731 goto done;
733 if (!atm_tcp_ops.attach) {
734 ret_val = -ENOPKG;
735 goto done;
737 fops_get (&atm_tcp_ops);
738 error = atm_tcp_ops.attach(vcc,(int) arg);
739 if (error >= 0) sock->state = SS_CONNECTED;
740 else fops_put (&atm_tcp_ops);
741 ret_val = error;
742 goto done;
743 case ATMTCP_CREATE:
744 if (!capable(CAP_NET_ADMIN)) {
745 ret_val = -EPERM;
746 goto done;
748 if (!atm_tcp_ops.create_persistent) {
749 ret_val = -ENOPKG;
750 goto done;
752 error = atm_tcp_ops.create_persistent((int) arg);
753 if (error < 0) fops_put (&atm_tcp_ops);
754 ret_val = error;
755 goto done;
756 case ATMTCP_REMOVE:
757 if (!capable(CAP_NET_ADMIN)) {
758 ret_val = -EPERM;
759 goto done;
761 if (!atm_tcp_ops.remove_persistent) {
762 ret_val = -ENOPKG;
763 goto done;
765 error = atm_tcp_ops.remove_persistent((int) arg);
766 fops_put (&atm_tcp_ops);
767 ret_val = error;
768 goto done;
769 #endif
770 default:
771 break;
773 if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) {
774 ret_val = -EFAULT;
775 goto done;
777 if (get_user(len,&((struct atmif_sioc *) arg)->length)) {
778 ret_val = -EFAULT;
779 goto done;
781 if (get_user(number,&((struct atmif_sioc *) arg)->number)) {
782 ret_val = -EFAULT;
783 goto done;
785 if (!(dev = atm_find_dev(number))) {
786 ret_val = -ENODEV;
787 goto done;
790 size = 0;
791 switch (cmd) {
792 case ATM_GETTYPE:
793 size = strlen(dev->type)+1;
794 if (copy_to_user(buf,dev->type,size)) {
795 ret_val = -EFAULT;
796 goto done;
798 break;
799 case ATM_GETESI:
800 size = ESI_LEN;
801 if (copy_to_user(buf,dev->esi,size)) {
802 ret_val = -EFAULT;
803 goto done;
805 break;
806 case ATM_SETESI:
808 int i;
810 for (i = 0; i < ESI_LEN; i++)
811 if (dev->esi[i]) {
812 ret_val = -EEXIST;
813 goto done;
816 /* fall through */
817 case ATM_SETESIF:
819 unsigned char esi[ESI_LEN];
821 if (!capable(CAP_NET_ADMIN)) {
822 ret_val = -EPERM;
823 goto done;
825 if (copy_from_user(esi,buf,ESI_LEN)) {
826 ret_val = -EFAULT;
827 goto done;
829 memcpy(dev->esi,esi,ESI_LEN);
830 ret_val = ESI_LEN;
831 goto done;
833 case ATM_GETSTATZ:
834 if (!capable(CAP_NET_ADMIN)) {
835 ret_val = -EPERM;
836 goto done;
838 /* fall through */
839 case ATM_GETSTAT:
840 size = sizeof(struct atm_dev_stats);
841 error = fetch_stats(dev,buf,cmd == ATM_GETSTATZ);
842 if (error) {
843 ret_val = error;
844 goto done;
846 break;
847 case ATM_GETCIRANGE:
848 size = sizeof(struct atm_cirange);
849 if (copy_to_user(buf,&dev->ci_range,size)) {
850 ret_val = -EFAULT;
851 goto done;
853 break;
854 case ATM_GETLINKRATE:
855 size = sizeof(int);
856 if (copy_to_user(buf,&dev->link_rate,size)) {
857 ret_val = -EFAULT;
858 goto done;
860 break;
861 case ATM_RSTADDR:
862 if (!capable(CAP_NET_ADMIN)) {
863 ret_val = -EPERM;
864 goto done;
866 reset_addr(dev);
867 break;
868 case ATM_ADDADDR:
869 case ATM_DELADDR:
870 if (!capable(CAP_NET_ADMIN)) {
871 ret_val = -EPERM;
872 goto done;
875 struct sockaddr_atmsvc addr;
877 if (copy_from_user(&addr,buf,sizeof(addr))) {
878 ret_val = -EFAULT;
879 goto done;
881 if (cmd == ATM_ADDADDR)
882 ret_val = add_addr(dev,&addr);
883 else
884 ret_val = del_addr(dev,&addr);
885 goto done;
887 case ATM_GETADDR:
888 size = get_addr(dev,buf,len);
889 if (size < 0)
890 ret_val = size;
891 else
892 /* may return 0, but later on size == 0 means "don't
893 write the length" */
894 ret_val = put_user(size,
895 &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0;
896 goto done;
897 case ATM_SETLOOP:
898 if (__ATM_LM_XTRMT((int) (long) buf) &&
899 __ATM_LM_XTLOC((int) (long) buf) >
900 __ATM_LM_XTRMT((int) (long) buf)) {
901 ret_val = -EINVAL;
902 goto done;
904 /* fall through */
905 case ATM_SETCIRANGE:
906 case SONET_GETSTATZ:
907 case SONET_SETDIAG:
908 case SONET_CLRDIAG:
909 case SONET_SETFRAMING:
910 if (!capable(CAP_NET_ADMIN)) {
911 ret_val = -EPERM;
912 goto done;
914 /* fall through */
915 default:
916 if (!dev->ops->ioctl) {
917 ret_val = -EINVAL;
918 goto done;
920 size = dev->ops->ioctl(dev,cmd,buf);
921 if (size < 0) {
922 ret_val = (size == -ENOIOCTLCMD ? -EINVAL : size);
923 goto done;
927 if (size)
928 ret_val = put_user(size,&((struct atmif_sioc *) arg)->length) ?
929 -EFAULT : 0;
931 done:
932 spin_unlock (&atm_dev_lock);
933 return ret_val;
937 static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
939 int error;
942 * Don't let the QoS change the already connected AAL type nor the
943 * traffic class.
945 if (qos->aal != vcc->qos.aal ||
946 qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class ||
947 qos->txtp.traffic_class != vcc->qos.txtp.traffic_class)
948 return -EINVAL;
949 error = adjust_tp(&qos->txtp,qos->aal);
950 if (!error) error = adjust_tp(&qos->rxtp,qos->aal);
951 if (error) return error;
952 if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP;
953 if (vcc->family == AF_ATMPVC)
954 return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET);
955 return svc_change_qos(vcc,qos);
959 static int check_tp(struct atm_trafprm *tp)
961 /* @@@ Should be merged with adjust_tp */
962 if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS) return 0;
963 if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr &&
964 !tp->max_pcr) return -EINVAL;
965 if (tp->min_pcr == ATM_MAX_PCR) return -EINVAL;
966 if (tp->min_pcr && tp->max_pcr && tp->max_pcr != ATM_MAX_PCR &&
967 tp->min_pcr > tp->max_pcr) return -EINVAL;
969 * We allow pcr to be outside [min_pcr,max_pcr], because later
970 * adjustment may still push it in the valid range.
972 return 0;
976 static int check_qos(struct atm_qos *qos)
978 int error;
980 if (!qos->txtp.traffic_class && !qos->rxtp.traffic_class)
981 return -EINVAL;
982 if (qos->txtp.traffic_class != qos->rxtp.traffic_class &&
983 qos->txtp.traffic_class && qos->rxtp.traffic_class &&
984 qos->txtp.traffic_class != ATM_ANYCLASS &&
985 qos->rxtp.traffic_class != ATM_ANYCLASS) return -EINVAL;
986 error = check_tp(&qos->txtp);
987 if (error) return error;
988 return check_tp(&qos->rxtp);
992 static int atm_do_setsockopt(struct socket *sock,int level,int optname,
993 void *optval,int optlen)
995 struct atm_vcc *vcc;
996 unsigned long value;
997 int error;
999 vcc = ATM_SD(sock);
1000 switch (optname) {
1001 case SO_ATMQOS:
1003 struct atm_qos qos;
1005 if (copy_from_user(&qos,optval,sizeof(qos)))
1006 return -EFAULT;
1007 error = check_qos(&qos);
1008 if (error) return error;
1009 if (sock->state == SS_CONNECTED)
1010 return atm_change_qos(vcc,&qos);
1011 if (sock->state != SS_UNCONNECTED)
1012 return -EBADFD;
1013 vcc->qos = qos;
1014 set_bit(ATM_VF_HASQOS,&vcc->flags);
1015 return 0;
1017 case SO_SETCLP:
1018 if (get_user(value,(unsigned long *) optval))
1019 return -EFAULT;
1020 if (value) vcc->atm_options |= ATM_ATMOPT_CLP;
1021 else vcc->atm_options &= ~ATM_ATMOPT_CLP;
1022 return 0;
1023 default:
1024 if (level == SOL_SOCKET) return -EINVAL;
1025 break;
1027 if (!vcc->dev || !vcc->dev->ops->setsockopt) return -EINVAL;
1028 return vcc->dev->ops->setsockopt(vcc,level,optname,optval,optlen);
1032 static int atm_do_getsockopt(struct socket *sock,int level,int optname,
1033 void *optval,int optlen)
1035 struct atm_vcc *vcc;
1037 vcc = ATM_SD(sock);
1038 switch (optname) {
1039 case SO_ATMQOS:
1040 if (!test_bit(ATM_VF_HASQOS,&vcc->flags))
1041 return -EINVAL;
1042 return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ?
1043 -EFAULT : 0;
1044 case SO_SETCLP:
1045 return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 :
1046 0,(unsigned long *) optval) ? -EFAULT : 0;
1047 case SO_ATMPVC:
1049 struct sockaddr_atmpvc pvc;
1051 if (!vcc->dev ||
1052 !test_bit(ATM_VF_ADDR,&vcc->flags))
1053 return -ENOTCONN;
1054 pvc.sap_family = AF_ATMPVC;
1055 pvc.sap_addr.itf = vcc->dev->number;
1056 pvc.sap_addr.vpi = vcc->vpi;
1057 pvc.sap_addr.vci = vcc->vci;
1058 return copy_to_user(optval,&pvc,sizeof(pvc)) ?
1059 -EFAULT : 0;
1061 default:
1062 if (level == SOL_SOCKET) return -EINVAL;
1063 break;
1065 if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL;
1066 return vcc->dev->ops->getsockopt(vcc,level,optname,optval,optlen);
1070 int atm_setsockopt(struct socket *sock,int level,int optname,char *optval,
1071 int optlen)
1073 if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
1074 return -EINVAL;
1075 return atm_do_setsockopt(sock,level,optname,optval,optlen);
1079 int atm_getsockopt(struct socket *sock,int level,int optname,
1080 char *optval,int *optlen)
1082 int len;
1084 if (get_user(len,optlen)) return -EFAULT;
1085 if (__SO_LEVEL_MATCH(optname, level) && len != __SO_SIZE(optname))
1086 return -EINVAL;
1087 return atm_do_getsockopt(sock,level,optname,optval,len);