1 /* net/atm/common.c - ATM sockets (common part for PVC and SVC) */
3 /* Written 1995-1999 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 <net/sock.h> /* struct sock */
24 #include <asm/uaccess.h>
27 #ifdef CONFIG_MMU_HACKS
28 #include <linux/mmuio.h>
29 #include <linux/uio.h>
32 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
33 #include <linux/atmlec.h>
36 struct atm_lane_ops atm_lane_ops
;
38 #ifdef CONFIG_ATM_LANE_MODULE
39 EXPORT_SYMBOL(atm_lane_ops
);
42 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
43 #include <linux/atmmpc.h>
45 struct atm_mpoa_ops atm_mpoa_ops
;
47 #ifdef CONFIG_ATM_MPOA_MODULE
48 EXPORT_SYMBOL(atm_mpoa_ops
);
49 #ifndef CONFIG_ATM_LANE_MODULE
50 EXPORT_SYMBOL(atm_lane_ops
);
54 #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
55 #include <linux/atm_tcp.h>
56 #ifdef CONFIG_ATM_TCP_MODULE
57 struct atm_tcp_ops atm_tcp_ops
;
58 EXPORT_SYMBOL(atm_tcp_ops
);
62 #include "resources.h" /* atm_find_dev */
63 #include "common.h" /* prototypes */
64 #include "protocols.h" /* atm_init_<transport> */
65 #include "tunable.h" /* tunable parameters */
66 #include "addr.h" /* address registry */
67 #ifdef CONFIG_ATM_CLIP
68 #include <net/atmclip.h> /* for clip_create */
70 #include "signaling.h" /* for WAITING and sigd_attach */
74 #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
76 #define DPRINTK(format,args...)
80 static struct sk_buff
*alloc_tx(struct atm_vcc
*vcc
,unsigned int size
)
84 if (atomic_read(&vcc
->tx_inuse
) && size
+atomic_read(&vcc
->tx_inuse
)+
85 ATM_PDU_OVHD
> vcc
->tx_quota
) {
86 DPRINTK("Sorry: tx_inuse = %d, size = %d, tx_quota = %ld\n",
87 atomic_read(&vcc
->tx_inuse
),size
,vcc
->tx_quota
);
90 while (!(skb
= alloc_skb(size
,GFP_KERNEL
))) schedule();
91 DPRINTK("AlTx %d += %d\n",atomic_read(&vcc
->tx_inuse
),skb
->truesize
);
92 atomic_add(skb
->truesize
+ATM_PDU_OVHD
,&vcc
->tx_inuse
);
97 int atm_create(struct socket
*sock
,int protocol
,int family
)
103 if (sock
->type
== SOCK_STREAM
) return -EINVAL
;
104 if (!(sk
= alloc_atm_vcc_sk(family
))) return -ENOMEM
;
105 vcc
= sk
->protinfo
.af_atm
;
106 vcc
->flags
= ATM_VF_SCRX
| ATM_VF_SCTX
;
108 vcc
->family
= sock
->ops
->family
;
109 vcc
->alloc_tx
= alloc_tx
;
110 vcc
->callback
= NULL
;
111 memset(&vcc
->local
,0,sizeof(struct sockaddr_atmsvc
));
112 memset(&vcc
->remote
,0,sizeof(struct sockaddr_atmsvc
));
113 vcc
->tx_quota
= ATM_TXBQ_DEF
;
114 vcc
->rx_quota
= ATM_RXBQ_DEF
;
115 atomic_set(&vcc
->tx_inuse
,0);
116 atomic_set(&vcc
->rx_inuse
,0);
119 vcc
->push_oam
= NULL
;
120 vcc
->vpi
= vcc
->vci
= 0; /* no VCI/VPI yet */
121 vcc
->atm_options
= vcc
->aal_options
= 0;
122 vcc
->timestamp
.tv_sec
= vcc
->timestamp
.tv_usec
= 0;
123 init_waitqueue_head(&vcc
->sleep
);
124 init_waitqueue_head(&vcc
->wsleep
);
125 skb_queue_head_init(&vcc
->recvq
);
126 skb_queue_head_init(&vcc
->listenq
);
132 void atm_release_vcc_sk(struct sock
*sk
,int free_sk
)
137 vcc
= sk
->protinfo
.af_atm
;
138 vcc
->flags
&= ~ATM_VF_READY
;
140 if (vcc
->dev
->ops
->close
) vcc
->dev
->ops
->close(vcc
);
141 if (vcc
->push
) vcc
->push(vcc
,NULL
); /* atmarpd has no push */
142 while ((skb
= skb_dequeue(&vcc
->recvq
))) {
143 atm_return(vcc
,skb
->truesize
);
144 if (vcc
->dev
->ops
->free_rx_skb
)
145 vcc
->dev
->ops
->free_rx_skb(vcc
,skb
);
148 if (atomic_read(&vcc
->rx_inuse
))
149 printk(KERN_WARNING
"atm_release_vcc: strange ... "
150 "rx_inuse == %d after closing\n",
151 atomic_read(&vcc
->rx_inuse
));
154 if (free_sk
) free_atm_vcc_sk(sk
);
158 int atm_release(struct socket
*sock
)
161 atm_release_vcc_sk(sock
->sk
,1);
166 void atm_async_release_vcc(struct atm_vcc
*vcc
,int reply
)
168 vcc
->flags
|= ATM_VF_CLOSE
;
170 /*vcc->flags &= ~ATM_VF_READY;*/
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
))
216 switch (vcc
->qos
.aal
) {
218 error
= atm_init_aal0(vcc
);
219 vcc
->stats
= &dev
->stats
.aal0
;
222 error
= atm_init_aal34(vcc
);
223 vcc
->stats
= &dev
->stats
.aal34
;
226 /* ATM_AAL5 is also used in the "0 for default" case */
227 vcc
->qos
.aal
= ATM_AAL5
;
230 error
= atm_init_aal5(vcc
);
231 vcc
->stats
= &dev
->stats
.aal5
;
236 if (!error
) error
= adjust_tp(&vcc
->qos
.txtp
,vcc
->qos
.aal
);
237 if (!error
) error
= adjust_tp(&vcc
->qos
.rxtp
,vcc
->qos
.aal
);
238 if (error
) return error
;
240 DPRINTK("VCC %d.%d, AAL %d\n",vpi
,vci
,vcc
->qos
.aal
);
241 DPRINTK(" TX: %d, PCR %d..%d, SDU %d\n",vcc
->qos
.txtp
.traffic_class
,
242 vcc
->qos
.txtp
.min_pcr
,vcc
->qos
.txtp
.max_pcr
,vcc
->qos
.txtp
.max_sdu
);
243 DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc
->qos
.rxtp
.traffic_class
,
244 vcc
->qos
.rxtp
.min_pcr
,vcc
->qos
.rxtp
.max_pcr
,vcc
->qos
.rxtp
.max_sdu
);
245 if (dev
->ops
->open
) {
246 error
= dev
->ops
->open(vcc
,vpi
,vci
);
256 static int atm_do_connect(struct atm_vcc
*vcc
,int itf
,int vpi
,int vci
)
260 dev
= atm_find_dev(itf
);
261 if (!dev
) return -ENODEV
;
262 return atm_do_connect_dev(vcc
,dev
,vpi
,vci
);
266 int atm_connect_vcc(struct atm_vcc
*vcc
,int itf
,short vpi
,int vci
)
268 if (vpi
!= ATM_VPI_UNSPEC
&& vci
!= ATM_VCI_UNSPEC
)
269 vcc
->flags
&= ~ATM_VF_PARTIAL
;
270 else if (vcc
->flags
& ATM_VF_PARTIAL
) return -EINVAL
;
271 printk(KERN_DEBUG
"atm_connect (TX: cl %d,bw %d-%d,sdu %d; "
272 "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n",
273 vcc
->qos
.txtp
.traffic_class
,vcc
->qos
.txtp
.min_pcr
,
274 vcc
->qos
.txtp
.max_pcr
,vcc
->qos
.txtp
.max_sdu
,
275 vcc
->qos
.rxtp
.traffic_class
,vcc
->qos
.rxtp
.min_pcr
,
276 vcc
->qos
.rxtp
.max_pcr
,vcc
->qos
.rxtp
.max_sdu
,
277 vcc
->qos
.aal
== ATM_AAL5
? "" : vcc
->qos
.aal
== ATM_AAL0
? "" :
278 " ??? code ",vcc
->qos
.aal
== ATM_AAL0
? 0 : vcc
->qos
.aal
);
279 if (!(vcc
->flags
& ATM_VF_HASQOS
)) return -EBADFD
;
280 if (vcc
->qos
.txtp
.traffic_class
== ATM_ANYCLASS
||
281 vcc
->qos
.rxtp
.traffic_class
== ATM_ANYCLASS
)
283 if (itf
!= ATM_ITF_ANY
) {
286 error
= atm_do_connect(vcc
,itf
,vpi
,vci
);
287 if (error
) return error
;
292 for (dev
= atm_devs
; dev
; dev
= dev
->next
)
293 if (!atm_do_connect_dev(vcc
,dev
,vpi
,vci
)) break;
294 if (!dev
) return -ENODEV
;
296 if (vpi
== ATM_VPI_UNSPEC
|| vci
== ATM_VCI_UNSPEC
)
297 vcc
->flags
|= ATM_VF_PARTIAL
;
302 int atm_connect(struct socket
*sock
,int itf
,short vpi
,int vci
)
306 DPRINTK("atm_connect (vpi %d, vci %d)\n",vpi
,vci
);
307 if (sock
->state
== SS_CONNECTED
) return -EISCONN
;
308 if (sock
->state
!= SS_UNCONNECTED
) return -EINVAL
;
309 if (!(vpi
|| vci
)) return -EINVAL
;
310 error
= atm_connect_vcc(ATM_SD(sock
),itf
,vpi
,vci
);
311 if (error
) return error
;
312 if (ATM_SD(sock
)->flags
& ATM_VF_READY
) sock
->state
= SS_CONNECTED
;
317 int atm_recvmsg(struct socket
*sock
,struct msghdr
*m
,int total_len
,
318 int flags
,struct scm_cookie
*scm
)
322 unsigned long cpu_flags
;
328 if (sock
->state
!= SS_CONNECTED
) return -ENOTCONN
;
329 if (flags
& ~MSG_DONTWAIT
) return -EOPNOTSUPP
;
330 if (m
->msg_iovlen
!= 1) return -ENOSYS
; /* fix this later @@@ */
331 buff
= m
->msg_iov
->iov_base
;
332 size
= m
->msg_iov
->iov_len
;
334 save_flags(cpu_flags
);
336 while (!(skb
= skb_dequeue(&vcc
->recvq
))) {
337 if (vcc
->flags
& (ATM_VF_RELEASED
| ATM_VF_CLOSE
)) {
338 restore_flags(cpu_flags
);
341 if (!(vcc
->flags
& ATM_VF_READY
)) {
342 restore_flags(cpu_flags
);
345 if (flags
& MSG_DONTWAIT
) {
346 restore_flags(cpu_flags
);
349 interruptible_sleep_on(&vcc
->sleep
);
350 if (signal_pending(current
)) {
351 restore_flags(cpu_flags
);
355 restore_flags(cpu_flags
);
356 vcc
->timestamp
= skb
->stamp
;
357 eff_len
= skb
->len
> size
? size
: skb
->len
;
358 if (vcc
->dev
->ops
->feedback
)
359 vcc
->dev
->ops
->feedback(vcc
,skb
,(unsigned long) skb
->data
,
360 (unsigned long) buff
,eff_len
);
361 DPRINTK("RcvM %d -= %d\n",atomic_read(&vcc
->rx_inuse
),skb
->truesize
);
362 atm_return(vcc
,skb
->truesize
);
363 if (ATM_SKB(skb
)->iovcnt
) { /* @@@ hack */
364 /* iovcnt set, use scatter-gather for receive */
366 struct iovec
*iov
= (struct iovec
*)skb
->data
;
367 unsigned char *p
= (unsigned char *)buff
;
371 for (cnt
= 0; (cnt
< ATM_SKB(skb
)->iovcnt
) && el
; cnt
++) {
372 /*printk("s-g???: %p -> %p (%d)\n",iov->iov_base,p,iov->iov_len);*/
373 error
= copy_to_user(p
,iov
->iov_base
,
374 (iov
->iov_len
> el
) ? el
: iov
->iov_len
) ?
378 el
-= (iov
->iov_len
> el
)?el
:iov
->iov_len
;
381 if (!vcc
->dev
->ops
->free_rx_skb
) kfree_skb(skb
);
382 else vcc
->dev
->ops
->free_rx_skb(vcc
, skb
);
383 return error
? error
: eff_len
;
385 #ifdef CONFIG_MMU_HACKS
386 if (vcc
->flags
& ATM_VF_SCRX
) {
387 mmucp_tofs((unsigned long) buff
,eff_len
,skb
,
388 (unsigned long) skb
->data
);
394 error
= copy_to_user(buff
,skb
->data
,eff_len
) ? -EFAULT
: 0;
395 if (!vcc
->dev
->ops
->free_rx_skb
) kfree_skb(skb
);
396 else vcc
->dev
->ops
->free_rx_skb(vcc
, skb
);
398 return error
? error
: eff_len
;
402 int atm_sendmsg(struct socket
*sock
,struct msghdr
*m
,int total_len
,
403 struct scm_cookie
*scm
)
412 if (sock
->state
!= SS_CONNECTED
) return -ENOTCONN
;
413 if (m
->msg_name
) return -EISCONN
;
414 if (m
->msg_iovlen
!= 1) return -ENOSYS
; /* fix this later @@@ */
415 buff
= m
->msg_iov
->iov_base
;
416 size
= m
->msg_iov
->iov_len
;
418 if (vcc
->flags
& (ATM_VF_RELEASED
| ATM_VF_CLOSE
)) return vcc
->reply
;
419 if (!(vcc
->flags
& ATM_VF_READY
)) return -EPIPE
;
421 /* verify_area is done by net/socket.c */
422 #ifdef CONFIG_MMU_HACKS
423 if ((vcc
->flags
& ATM_VF_SCTX
) && vcc
->dev
->ops
->sg_send
&&
424 vcc
->dev
->ops
->sg_send(vcc
,(unsigned long) buff
,size
)) {
427 max_iov
= 2+size
/PAGE_SIZE
;
429 * Doesn't use alloc_tx yet - this will change later. @@@
431 while (!(skb
= alloc_skb(sizeof(struct iovec
)*max_iov
,
433 if (m
->msg_flags
& MSG_DONTWAIT
) return -EAGAIN
;
434 interruptible_sleep_on(&vcc
->wsleep
);
435 if (signal_pending(current
)) return -ERESTARTSYS
;
438 res
= lock_user((unsigned long) buff
,size
,max_iov
,
439 (struct iovec
*) skb
->data
);
442 if (res
!= -EAGAIN
) return res
;
445 DPRINTK("res is %d\n",res
);
446 DPRINTK("Asnd %d += %d\n",vcc
->tx_inuse
,skb
->truesize
);
447 atomic_add(skb
->truesize
+ATM_PDU_OVHD
,&vcc
->tx_inuse
);
448 ATM_SKB(skb
)->iovcnt
= res
;
449 error
= vcc
->dev
->ops
->send(vcc
,skb
);
450 /* FIXME: security: may send up to 3 "garbage" bytes */
451 return error
? error
: size
;
455 eff
= (size
+3) & ~3; /* align to word boundary */
456 while (!(skb
= vcc
->alloc_tx(vcc
,eff
))) {
457 if (m
->msg_flags
& MSG_DONTWAIT
) return -EAGAIN
;
458 interruptible_sleep_on(&vcc
->wsleep
);
459 if (signal_pending(current
)) return -ERESTARTSYS
;
460 if (vcc
->flags
& (ATM_VF_RELEASED
| ATM_VF_CLOSE
))
462 if (!(vcc
->flags
& ATM_VF_READY
)) return -EPIPE
;
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
);
483 poll_wait(file
,&vcc
->wsleep
,wait
);
485 if (skb_peek(&vcc
->recvq
) || skb_peek(&vcc
->listenq
))
486 mask
|= POLLIN
| POLLRDNORM
;
487 if (vcc
->flags
& (ATM_VF_RELEASED
| ATM_VF_CLOSE
)) mask
|= POLLHUP
;
488 if (sock
->state
!= SS_CONNECTING
) {
489 if (vcc
->qos
.txtp
.traffic_class
!= ATM_NONE
&&
490 vcc
->qos
.txtp
.max_sdu
+atomic_read(&vcc
->tx_inuse
)+
491 ATM_PDU_OVHD
<= vcc
->tx_quota
)
492 mask
|= POLLOUT
| POLLWRNORM
;
494 else if (vcc
->reply
!= WAITING
) {
495 mask
|= POLLOUT
| POLLWRNORM
;
496 if (vcc
->reply
) mask
|= POLLERR
;
502 static int fetch_stats(struct atm_dev
*dev
,struct atm_dev_stats
*arg
,int zero
)
511 error
= copy_to_user(arg
,&dev
->stats
,
512 sizeof(struct atm_dev_stats
));
514 memset(&dev
->stats
,0,sizeof(struct atm_dev_stats
));
515 restore_flags(flags
);
516 return error
? -EFAULT
: 0;
520 int atm_ioctl(struct socket
*sock
,unsigned int cmd
,unsigned long arg
)
526 int error
,len
,size
,number
;
531 if (sock
->state
!= SS_CONNECTED
||
532 !(vcc
->flags
& ATM_VF_READY
)) return -EINVAL
;
533 return put_user(vcc
->tx_quota
-
534 atomic_read(&vcc
->tx_inuse
)-ATM_PDU_OVHD
,
535 (int *) arg
) ? -EFAULT
: 0;
540 if (sock
->state
!= SS_CONNECTED
)
542 skb
= skb_peek(&vcc
->recvq
);
543 return put_user(skb
? skb
->len
: 0,(int *) arg
)
548 &((struct atm_iobuf
*) arg
)->buffer
))
551 &((struct atm_iobuf
*) arg
)->length
))
554 for (dev
= atm_devs
; dev
; dev
= dev
->next
)
556 if (size
> len
) return -E2BIG
;
557 tmp_buf
= kmalloc(size
,GFP_KERNEL
);
558 if (!tmp_buf
) return -ENOMEM
;
559 for (dev
= atm_devs
; dev
; dev
= dev
->next
)
560 *tmp_buf
++ = dev
->number
;
561 if (copy_to_user(buf
,(char *) tmp_buf
-size
,size
))
563 return put_user(size
,
564 &((struct atm_iobuf
*) arg
)->length
) ? -EFAULT
: 0;
565 case SIOCGSTAMP
: /* borrowed from IP */
566 if (!vcc
->timestamp
.tv_sec
) return -ENOENT
;
567 vcc
->timestamp
.tv_sec
+= vcc
->timestamp
.tv_usec
/1000000;
568 vcc
->timestamp
.tv_usec
%= 1000000;
569 return copy_to_user((void *) arg
,&vcc
->timestamp
,
570 sizeof(struct timeval
)) ? -EFAULT
: 0;
572 if (arg
& ~(ATM_VF_SCRX
| ATM_VF_SCTX
)) return -EINVAL
;
573 /* @@@ race condition - should split flags into
574 "volatile" and non-volatile part */
575 vcc
->flags
= (vcc
->flags
& ~(ATM_VF_SCRX
|
579 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
580 error
= sigd_attach(vcc
);
581 if (!error
) sock
->state
= SS_CONNECTED
;
583 #ifdef WE_DONT_SUPPORT_P2MP_YET
584 case ATM_CREATE_LEAF
:
586 struct socket
*session
;
588 if (!(session
= sockfd_lookup(arg
,&error
)))
590 if (sock
->ops
->family
!= PF_ATMSVC
||
591 session
->ops
->family
!= PF_ATMSVC
)
593 return create_leaf(sock
,session
);
596 #ifdef CONFIG_ATM_CLIP
598 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
599 return clip_create(arg
);
601 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
602 error
= atm_init_atmarp(vcc
);
603 if (!error
) sock
->state
= SS_CONNECTED
;
606 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
607 return clip_mkip(vcc
,arg
);
608 case ATMARP_SETENTRY
:
609 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
610 return clip_setentry(vcc
,arg
);
612 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
613 return clip_encap(vcc
,arg
);
615 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
617 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
618 if (atm_lane_ops
.lecd_attach
== NULL
)
620 if (atm_lane_ops
.lecd_attach
== NULL
) /* try again */
622 error
= atm_lane_ops
.lecd_attach(vcc
, (int)arg
);
623 if (error
>= 0) sock
->state
= SS_CONNECTED
;
626 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
627 return atm_lane_ops
.mcast_attach(vcc
, (int)arg
);
629 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
630 return atm_lane_ops
.vcc_attach(vcc
, (void*)arg
);
632 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
634 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
635 if (atm_mpoa_ops
.mpoad_attach
== NULL
)
637 if (atm_mpoa_ops
.mpoad_attach
== NULL
) /* try again */
639 error
= atm_mpoa_ops
.mpoad_attach(vcc
, (int)arg
);
640 if (error
>= 0) sock
->state
= SS_CONNECTED
;
643 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
644 return atm_mpoa_ops
.vcc_attach(vcc
, arg
);
646 #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
648 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
649 if (!atm_tcp_ops
.attach
) return -ENOPKG
;
650 error
= atm_tcp_ops
.attach(vcc
,(int) arg
);
651 if (error
>= 0) sock
->state
= SS_CONNECTED
;
654 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
655 if (!atm_tcp_ops
.create_persistent
) return -ENOPKG
;
656 return atm_tcp_ops
.create_persistent((int) arg
);
658 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
659 if (!atm_tcp_ops
.remove_persistent
) return -ENOPKG
;
660 return atm_tcp_ops
.remove_persistent((int) arg
);
665 if (get_user(buf
,&((struct atmif_sioc
*) arg
)->arg
)) return -EFAULT
;
666 if (get_user(len
,&((struct atmif_sioc
*) arg
)->length
)) return -EFAULT
;
667 if (get_user(number
,&((struct atmif_sioc
*) arg
)->number
))
669 if (!(dev
= atm_find_dev(number
))) return -ENODEV
;
673 size
= strlen(dev
->type
)+1;
674 if (copy_to_user(buf
,dev
->type
,size
)) return -EFAULT
;
678 if (copy_to_user(buf
,dev
->esi
,size
)) return -EFAULT
;
684 for (i
= 0; i
< ESI_LEN
; i
++)
685 if (dev
->esi
[i
]) return -EEXIST
;
690 unsigned char esi
[ESI_LEN
];
692 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
693 if (copy_from_user(esi
,buf
,ESI_LEN
))
695 memcpy(dev
->esi
,esi
,ESI_LEN
);
699 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
702 size
= sizeof(struct atm_dev_stats
);
703 error
= fetch_stats(dev
,buf
,cmd
== ATM_GETSTATZ
);
704 if (error
) return error
;
707 size
= sizeof(struct atm_cirange
);
708 if (copy_to_user(buf
,&dev
->ci_range
,size
))
711 case ATM_GETLINKRATE
:
713 if (copy_to_user(buf
,&dev
->link_rate
,size
))
717 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
722 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
724 struct sockaddr_atmsvc addr
;
726 if (copy_from_user(&addr
,buf
,sizeof(addr
)))
728 if (cmd
== ATM_ADDADDR
)
729 return add_addr(dev
,&addr
);
730 else return del_addr(dev
,&addr
);
733 size
= get_addr(dev
,buf
,len
);
734 if (size
< 0) return size
;
735 /* may return 0, but later on size == 0 means "don't
737 return put_user(size
,
738 &((struct atmif_sioc
*) arg
)->length
) ? -EFAULT
: 0;
743 case SONET_SETFRAMING
:
744 if (!capable(CAP_NET_ADMIN
)) return -EPERM
;
747 if (!dev
->ops
->ioctl
) return -EINVAL
;
748 size
= dev
->ops
->ioctl(dev
,cmd
,buf
);
749 if (size
< 0) return size
;
752 return put_user(size
,&((struct atmif_sioc
*) arg
)->length
) ?
757 int atm_change_qos(struct atm_vcc
*vcc
,struct atm_qos
*qos
)
759 if (!vcc
->dev
->ops
->change_qos
) return -EOPNOTSUPP
;
760 if (vcc
->family
== AF_ATMPVC
)
761 return vcc
->dev
->ops
->change_qos(vcc
,qos
,ATM_MF_SET
);
762 return svc_change_qos(vcc
,qos
);
766 static int check_tp(struct atm_trafprm
*tp
)
768 /* @@@ Should be merged with adjust_tp */
769 if (!tp
->traffic_class
|| tp
->traffic_class
== ATM_ANYCLASS
) return 0;
770 if (tp
->traffic_class
!= ATM_UBR
&& !tp
->min_pcr
&& !tp
->pcr
&&
771 !tp
->max_pcr
) return -EINVAL
;
772 if (tp
->min_pcr
== ATM_MAX_PCR
) return -EINVAL
;
773 if (tp
->min_pcr
&& tp
->max_pcr
&& tp
->max_pcr
!= ATM_MAX_PCR
&&
774 tp
->min_pcr
> tp
->max_pcr
) return -EINVAL
;
776 * We allow pcr to be outside [min_pcr,max_pcr], because later
777 * adjustment may still push it in the valid range.
783 static int check_qos(struct atm_qos
*qos
)
787 if (!qos
->txtp
.traffic_class
&& !qos
->rxtp
.traffic_class
)
789 if (qos
->txtp
.traffic_class
!= qos
->rxtp
.traffic_class
&&
790 qos
->txtp
.traffic_class
&& qos
->rxtp
.traffic_class
&&
791 qos
->txtp
.traffic_class
!= ATM_ANYCLASS
&&
792 qos
->rxtp
.traffic_class
!= ATM_ANYCLASS
) return -EINVAL
;
793 error
= check_tp(&qos
->txtp
);
794 if (error
) return error
;
795 return check_tp(&qos
->rxtp
);
799 static int atm_do_setsockopt(struct socket
*sock
,int level
,int optname
,
800 void *optval
,int optlen
)
809 if (get_user(value
,(unsigned long *) optval
))
811 if (!value
) value
= ATM_TXBQ_DEF
;
812 if (value
< ATM_TXBQ_MIN
) value
= ATM_TXBQ_MIN
;
813 if (value
> ATM_TXBQ_MAX
) value
= ATM_TXBQ_MAX
;
814 vcc
->tx_quota
= value
;
817 if (get_user(value
,(unsigned long *) optval
))
819 if (!value
) value
= ATM_RXBQ_DEF
;
820 if (value
< ATM_RXBQ_MIN
) value
= ATM_RXBQ_MIN
;
821 if (value
> ATM_RXBQ_MAX
) value
= ATM_RXBQ_MAX
;
822 vcc
->rx_quota
= value
;
828 if (copy_from_user(&qos
,optval
,sizeof(qos
)))
830 error
= check_qos(&qos
);
831 if (error
) return error
;
832 if (sock
->state
== SS_CONNECTED
)
833 return atm_change_qos(vcc
,&qos
);
834 if (sock
->state
!= SS_UNCONNECTED
)
837 vcc
->flags
|= ATM_VF_HASQOS
;
841 if (get_user(value
,(unsigned long *) optval
))
843 if (value
) vcc
->atm_options
|= ATM_ATMOPT_CLP
;
844 else vcc
->atm_options
&= ~ATM_ATMOPT_CLP
;
847 if (level
== SOL_SOCKET
) return -EINVAL
;
850 if (!vcc
->dev
|| !vcc
->dev
->ops
->setsockopt
) return -EINVAL
;
851 return vcc
->dev
->ops
->setsockopt(vcc
,level
,optname
,optval
,optlen
);
855 static int atm_do_getsockopt(struct socket
*sock
,int level
,int optname
,
856 void *optval
,int optlen
)
863 return put_user(vcc
->tx_quota
,(unsigned long *) optval
)
866 return put_user(vcc
->rx_quota
,(unsigned long *) optval
)
871 printk(KERN_WARNING
"Warning: SO_BCTXOPT/SO_BCRXOPT "
875 if (!(vcc
->flags
& ATM_VF_HASQOS
)) return -EINVAL
;
876 return copy_to_user(optval
,&vcc
->qos
,sizeof(vcc
->qos
)) ?
879 return put_user(vcc
->atm_options
& ATM_ATMOPT_CLP
? 1 :
880 0,(unsigned long *) optval
) ? -EFAULT
: 0;
883 struct sockaddr_atmpvc pvc
;
885 if (!vcc
->dev
|| !(vcc
->flags
& ATM_VF_ADDR
))
887 pvc
.sap_family
= AF_ATMPVC
;
888 pvc
.sap_addr
.itf
= vcc
->dev
->number
;
889 pvc
.sap_addr
.vpi
= vcc
->vpi
;
890 pvc
.sap_addr
.vci
= vcc
->vci
;
891 return copy_to_user(optval
,&pvc
,sizeof(pvc
)) ?
895 if (level
== SOL_SOCKET
) return -EINVAL
;
898 if (!vcc
->dev
|| !vcc
->dev
->ops
->getsockopt
) return -EINVAL
;
899 return vcc
->dev
->ops
->getsockopt(vcc
,level
,optname
,optval
,optlen
);
903 int atm_setsockopt(struct socket
*sock
,int level
,int optname
,char *optval
,
906 if (__SO_LEVEL_MATCH(optname
, level
) && optlen
!= __SO_SIZE(optname
))
908 return atm_do_setsockopt(sock
,level
,optname
,optval
,optlen
);
912 int atm_getsockopt(struct socket
*sock
,int level
,int optname
,
913 char *optval
,int *optlen
)
917 if (get_user(len
,optlen
)) return -EFAULT
;
918 if (__SO_LEVEL_MATCH(optname
, level
) && len
!= __SO_SIZE(optname
))
920 return atm_do_getsockopt(sock
,level
,optname
,optval
,len
);