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
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>
29 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
30 #include <linux/atmlec.h>
33 struct atm_lane_ops atm_lane_ops
;
35 #ifdef CONFIG_ATM_LANE_MODULE
36 EXPORT_SYMBOL(atm_lane_ops
);
39 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
40 #include <linux/atmmpc.h>
42 struct atm_mpoa_ops atm_mpoa_ops
;
44 #ifdef CONFIG_ATM_MPOA_MODULE
45 EXPORT_SYMBOL(atm_mpoa_ops
);
46 #ifndef CONFIG_ATM_LANE_MODULE
47 EXPORT_SYMBOL(atm_lane_ops
);
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
);
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 */
66 #include "signaling.h" /* for WAITING and sigd_attach */
70 #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
72 #define DPRINTK(format,args...)
75 spinlock_t atm_dev_lock
= SPIN_LOCK_UNLOCKED
;
77 static struct sk_buff
*alloc_tx(struct atm_vcc
*vcc
,unsigned int size
)
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
);
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
);
93 int atm_create(struct socket
*sock
,int protocol
,int family
)
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
));
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);
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
;
127 void atm_release_vcc_sk(struct sock
*sk
,int free_sk
)
132 vcc
= sk
->protinfo
.af_atm
;
133 clear_bit(ATM_VF_READY
,&vcc
->flags
);
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
);
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
));
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
)
162 atm_release_vcc_sk(sock
->sk
,1);
167 void atm_async_release_vcc(struct atm_vcc
*vcc
,int reply
)
169 set_bit(ATM_VF_CLOSE
,&vcc
->flags
);
171 wake_up(&vcc
->sleep
);
175 EXPORT_SYMBOL(atm_async_release_vcc
);
178 static int adjust_tp(struct atm_trafprm
*tp
,unsigned char aal
)
182 if (!tp
->traffic_class
) return 0;
185 max_sdu
= ATM_CELL_SIZE
-1;
188 max_sdu
= ATM_MAX_AAL34_PDU
;
191 printk(KERN_WARNING
"ATM: AAL problems ... "
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
;
204 static int atm_do_connect_dev(struct atm_vcc
*vcc
,struct atm_dev
*dev
,int vpi
,
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
))
213 if (vci
> 0 && vci
< ATM_NOT_RSV_VCI
&& !capable(CAP_NET_BIND_SERVICE
))
217 switch (vcc
->qos
.aal
) {
219 error
= atm_init_aal0(vcc
);
220 vcc
->stats
= &dev
->stats
.aal0
;
223 error
= atm_init_aal34(vcc
);
224 vcc
->stats
= &dev
->stats
.aal34
;
227 /* ATM_AAL5 is also used in the "0 for default" case */
228 vcc
->qos
.aal
= ATM_AAL5
;
231 error
= atm_init_aal5(vcc
);
232 vcc
->stats
= &dev
->stats
.aal5
;
237 if (!error
) error
= adjust_tp(&vcc
->qos
.txtp
,vcc
->qos
.aal
);
238 if (!error
) error
= adjust_tp(&vcc
->qos
.rxtp
,vcc
->qos
.aal
);
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
);
249 if (dev
->ops
->open
) {
250 error
= dev
->ops
->open(vcc
,vpi
,vci
);
261 static int atm_do_connect(struct atm_vcc
*vcc
,int itf
,int vpi
,int vci
)
266 spin_lock (&atm_dev_lock
);
267 dev
= atm_find_dev(itf
);
269 return_val
= -ENODEV
;
271 return_val
= atm_do_connect_dev(vcc
,dev
,vpi
,vci
);
273 spin_unlock (&atm_dev_lock
);
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
)
296 if (itf
!= ATM_ITF_ANY
) {
299 error
= atm_do_connect(vcc
,itf
,vpi
,vci
);
300 if (error
) return error
;
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
);
317 int atm_connect(struct socket
*sock
,int itf
,short vpi
,int vci
)
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
;
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
);
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
;
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
)) {
358 if (!test_bit(ATM_VF_READY
,&vcc
->flags
)) {
362 if (flags
& MSG_DONTWAIT
) {
367 set_current_state(TASK_INTERRUPTIBLE
);
368 if (signal_pending(current
)) {
369 error
= -ERESTARTSYS
;
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 */
386 struct iovec
*iov
= (struct iovec
*)skb
->data
;
387 unsigned char *p
= (unsigned char *)buff
;
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
) ?
398 el
-= (iov
->iov_len
> el
)?el
:iov
->iov_len
;
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
);
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
;
428 if (test_bit(ATM_VF_RELEASED
,&vcc
->flags
) ||
429 test_bit(ATM_VF_CLOSE
,&vcc
->flags
))
431 if (!test_bit(ATM_VF_READY
,&vcc
->flags
)) return -EPIPE
;
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
);
439 while (!(skb
= vcc
->alloc_tx(vcc
,eff
))) {
440 if (m
->msg_flags
& MSG_DONTWAIT
) {
445 set_current_state(TASK_INTERRUPTIBLE
);
446 if (signal_pending(current
)) {
447 error
= -ERESTARTSYS
;
450 if (test_bit(ATM_VF_RELEASED
,&vcc
->flags
) ||
451 test_bit(ATM_VF_CLOSE
,&vcc
->flags
)) {
455 if (!test_bit(ATM_VF_READY
,&vcc
->flags
)) {
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
)) {
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
)
482 poll_wait(file
,&vcc
->sleep
,wait
);
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
))
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
;
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)
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)
521 static int fetch_stats(struct atm_dev
*dev
,struct atm_dev_stats
*arg
,int zero
)
523 struct atm_dev_stats tmp
;
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
)
545 int error
,len
,size
,number
, ret_val
;
548 spin_lock (&atm_dev_lock
);
552 if (sock
->state
!= SS_CONNECTED
||
553 !test_bit(ATM_VF_READY
,&vcc
->flags
)) {
557 ret_val
= put_user(vcc
->sk
->sndbuf
-
558 atomic_read(&vcc
->tx_inuse
)-ATM_PDU_OVHD
,
559 (int *) arg
) ? -EFAULT
: 0;
565 if (sock
->state
!= SS_CONNECTED
) {
569 skb
= skb_peek(&vcc
->recvq
);
570 ret_val
= put_user(skb
? skb
->len
: 0,(int *) arg
)
576 &((struct atm_iobuf
*) arg
)->buffer
)) {
581 &((struct atm_iobuf
*) arg
)->length
)) {
586 for (dev
= atm_devs
; dev
; dev
= dev
->next
)
592 tmp_buf
= kmalloc(size
,GFP_KERNEL
);
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
)) {
603 ret_val
= put_user(size
,
604 &((struct atm_iobuf
*) arg
)->length
) ? -EFAULT
: 0;
606 case SIOCGSTAMP
: /* borrowed from IP */
607 if (!vcc
->timestamp
.tv_sec
) {
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;
617 printk(KERN_WARNING
"ATM_SETSC is obsolete\n");
621 if (!capable(CAP_NET_ADMIN
)) {
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
)) {
636 error
= sigd_attach(vcc
);
637 if (!error
) sock
->state
= SS_CONNECTED
;
640 #ifdef CONFIG_ATM_CLIP
642 if (!capable(CAP_NET_ADMIN
))
645 ret_val
= clip_create(arg
);
648 if (!capable(CAP_NET_ADMIN
)) {
652 error
= atm_init_atmarp(vcc
);
653 if (!error
) sock
->state
= SS_CONNECTED
;
657 if (!capable(CAP_NET_ADMIN
))
660 ret_val
= clip_mkip(vcc
,arg
);
662 case ATMARP_SETENTRY
:
663 if (!capable(CAP_NET_ADMIN
))
666 ret_val
= clip_setentry(vcc
,arg
);
669 if (!capable(CAP_NET_ADMIN
))
672 ret_val
= clip_encap(vcc
,arg
);
675 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
677 if (!capable(CAP_NET_ADMIN
)) {
681 if (atm_lane_ops
.lecd_attach
== NULL
)
683 if (atm_lane_ops
.lecd_attach
== NULL
) { /* try again */
687 error
= atm_lane_ops
.lecd_attach(vcc
, (int)arg
);
688 if (error
>= 0) sock
->state
= SS_CONNECTED
;
692 if (!capable(CAP_NET_ADMIN
))
695 ret_val
= atm_lane_ops
.mcast_attach(vcc
, (int)arg
);
698 if (!capable(CAP_NET_ADMIN
))
701 ret_val
= atm_lane_ops
.vcc_attach(vcc
, (void*)arg
);
704 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
706 if (!capable(CAP_NET_ADMIN
)) {
710 if (atm_mpoa_ops
.mpoad_attach
== NULL
)
712 if (atm_mpoa_ops
.mpoad_attach
== NULL
) { /* try again */
716 error
= atm_mpoa_ops
.mpoad_attach(vcc
, (int)arg
);
717 if (error
>= 0) sock
->state
= SS_CONNECTED
;
721 if (!capable(CAP_NET_ADMIN
))
724 ret_val
= atm_mpoa_ops
.vcc_attach(vcc
, arg
);
727 #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
729 if (!capable(CAP_NET_ADMIN
)) {
733 if (!atm_tcp_ops
.attach
) {
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
);
744 if (!capable(CAP_NET_ADMIN
)) {
748 if (!atm_tcp_ops
.create_persistent
) {
752 error
= atm_tcp_ops
.create_persistent((int) arg
);
753 if (error
< 0) fops_put (&atm_tcp_ops
);
757 if (!capable(CAP_NET_ADMIN
)) {
761 if (!atm_tcp_ops
.remove_persistent
) {
765 error
= atm_tcp_ops
.remove_persistent((int) arg
);
766 fops_put (&atm_tcp_ops
);
773 if (get_user(buf
,&((struct atmif_sioc
*) arg
)->arg
)) {
777 if (get_user(len
,&((struct atmif_sioc
*) arg
)->length
)) {
781 if (get_user(number
,&((struct atmif_sioc
*) arg
)->number
)) {
785 if (!(dev
= atm_find_dev(number
))) {
793 size
= strlen(dev
->type
)+1;
794 if (copy_to_user(buf
,dev
->type
,size
)) {
801 if (copy_to_user(buf
,dev
->esi
,size
)) {
810 for (i
= 0; i
< ESI_LEN
; i
++)
819 unsigned char esi
[ESI_LEN
];
821 if (!capable(CAP_NET_ADMIN
)) {
825 if (copy_from_user(esi
,buf
,ESI_LEN
)) {
829 memcpy(dev
->esi
,esi
,ESI_LEN
);
834 if (!capable(CAP_NET_ADMIN
)) {
840 size
= sizeof(struct atm_dev_stats
);
841 error
= fetch_stats(dev
,buf
,cmd
== ATM_GETSTATZ
);
848 size
= sizeof(struct atm_cirange
);
849 if (copy_to_user(buf
,&dev
->ci_range
,size
)) {
854 case ATM_GETLINKRATE
:
856 if (copy_to_user(buf
,&dev
->link_rate
,size
)) {
862 if (!capable(CAP_NET_ADMIN
)) {
870 if (!capable(CAP_NET_ADMIN
)) {
875 struct sockaddr_atmsvc addr
;
877 if (copy_from_user(&addr
,buf
,sizeof(addr
))) {
881 if (cmd
== ATM_ADDADDR
)
882 ret_val
= add_addr(dev
,&addr
);
884 ret_val
= del_addr(dev
,&addr
);
888 size
= get_addr(dev
,buf
,len
);
892 /* may return 0, but later on size == 0 means "don't
894 ret_val
= put_user(size
,
895 &((struct atmif_sioc
*) arg
)->length
) ? -EFAULT
: 0;
898 if (__ATM_LM_XTRMT((int) (long) buf
) &&
899 __ATM_LM_XTLOC((int) (long) buf
) >
900 __ATM_LM_XTRMT((int) (long) buf
)) {
909 case SONET_SETFRAMING
:
910 if (!capable(CAP_NET_ADMIN
)) {
916 if (!dev
->ops
->ioctl
) {
920 size
= dev
->ops
->ioctl(dev
,cmd
,buf
);
922 ret_val
= (size
== -ENOIOCTLCMD
? -EINVAL
: size
);
928 ret_val
= put_user(size
,&((struct atmif_sioc
*) arg
)->length
) ?
932 spin_unlock (&atm_dev_lock
);
937 static int atm_change_qos(struct atm_vcc
*vcc
,struct atm_qos
*qos
)
942 * Don't let the QoS change the already connected AAL type nor the
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
)
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.
976 static int check_qos(struct atm_qos
*qos
)
980 if (!qos
->txtp
.traffic_class
&& !qos
->rxtp
.traffic_class
)
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
)
1005 if (copy_from_user(&qos
,optval
,sizeof(qos
)))
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
)
1014 set_bit(ATM_VF_HASQOS
,&vcc
->flags
);
1018 if (get_user(value
,(unsigned long *) optval
))
1020 if (value
) vcc
->atm_options
|= ATM_ATMOPT_CLP
;
1021 else vcc
->atm_options
&= ~ATM_ATMOPT_CLP
;
1024 if (level
== SOL_SOCKET
) return -EINVAL
;
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
;
1040 if (!test_bit(ATM_VF_HASQOS
,&vcc
->flags
))
1042 return copy_to_user(optval
,&vcc
->qos
,sizeof(vcc
->qos
)) ?
1045 return put_user(vcc
->atm_options
& ATM_ATMOPT_CLP
? 1 :
1046 0,(unsigned long *) optval
) ? -EFAULT
: 0;
1049 struct sockaddr_atmpvc pvc
;
1052 !test_bit(ATM_VF_ADDR
,&vcc
->flags
))
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
)) ?
1062 if (level
== SOL_SOCKET
) return -EINVAL
;
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
,
1073 if (__SO_LEVEL_MATCH(optname
, level
) && optlen
!= __SO_SIZE(optname
))
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
)
1084 if (get_user(len
,optlen
)) return -EFAULT
;
1085 if (__SO_LEVEL_MATCH(optname
, level
) && len
!= __SO_SIZE(optname
))
1087 return atm_do_getsockopt(sock
,level
,optname
,optval
,len
);