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/kmod.h>
9 #include <linux/net.h> /* struct socket, struct proto_ops */
10 #include <linux/atm.h> /* ATM stuff */
11 #include <linux/atmdev.h>
12 #include <linux/socket.h> /* SOL_SOCKET */
13 #include <linux/errno.h> /* error codes */
14 #include <linux/capability.h>
15 #include <linux/mm.h> /* verify_area */
16 #include <linux/sched.h>
17 #include <linux/time.h> /* struct timeval */
18 #include <linux/skbuff.h>
19 #include <linux/bitops.h>
20 #include <linux/init.h>
21 #include <net/sock.h> /* struct sock */
23 #include <asm/uaccess.h>
24 #include <asm/atomic.h>
28 #include "resources.h" /* atm_find_dev */
29 #include "common.h" /* prototypes */
30 #include "protocols.h" /* atm_init_<transport> */
31 #include "addr.h" /* address registry */
32 #include "signaling.h" /* for WAITING and sigd_attach */
36 #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
38 #define DPRINTK(format,args...)
41 struct hlist_head vcc_hash
[VCC_HTABLE_SIZE
];
42 rwlock_t vcc_sklist_lock
= RW_LOCK_UNLOCKED
;
44 void __vcc_insert_socket(struct sock
*sk
)
46 struct atm_vcc
*vcc
= atm_sk(sk
);
47 struct hlist_head
*head
= &vcc_hash
[vcc
->vci
&
48 (VCC_HTABLE_SIZE
- 1)];
49 sk
->sk_hashent
= vcc
->vci
& (VCC_HTABLE_SIZE
- 1);
50 sk_add_node(sk
, head
);
53 void vcc_insert_socket(struct sock
*sk
)
55 write_lock_irq(&vcc_sklist_lock
);
56 __vcc_insert_socket(sk
);
57 write_unlock_irq(&vcc_sklist_lock
);
60 void vcc_remove_socket(struct sock
*sk
)
62 write_lock_irq(&vcc_sklist_lock
);
64 write_unlock_irq(&vcc_sklist_lock
);
68 static struct sk_buff
*alloc_tx(struct atm_vcc
*vcc
,unsigned int size
)
72 if (atomic_read(&vcc
->sk
->sk_wmem_alloc
) && !atm_may_send(vcc
, size
)) {
73 DPRINTK("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
74 atomic_read(&vcc
->sk
->sk_wmem_alloc
), size
,
78 while (!(skb
= alloc_skb(size
,GFP_KERNEL
))) schedule();
79 DPRINTK("AlTx %d += %d\n", atomic_read(&vcc
->sk
->sk_wmem_alloc
),
81 atomic_add(skb
->truesize
, &vcc
->sk
->sk_wmem_alloc
);
86 EXPORT_SYMBOL(vcc_hash
);
87 EXPORT_SYMBOL(vcc_sklist_lock
);
88 EXPORT_SYMBOL(vcc_insert_socket
);
89 EXPORT_SYMBOL(vcc_remove_socket
);
91 static void vcc_sock_destruct(struct sock
*sk
)
93 struct atm_vcc
*vcc
= atm_sk(sk
);
95 if (atomic_read(&vcc
->sk
->sk_rmem_alloc
))
96 printk(KERN_DEBUG
"vcc_sock_destruct: rmem leakage (%d bytes) detected.\n", atomic_read(&sk
->sk_rmem_alloc
));
98 if (atomic_read(&vcc
->sk
->sk_wmem_alloc
))
99 printk(KERN_DEBUG
"vcc_sock_destruct: wmem leakage (%d bytes) detected.\n", atomic_read(&sk
->sk_wmem_alloc
));
101 kfree(sk
->sk_protinfo
);
104 static void vcc_def_wakeup(struct sock
*sk
)
106 read_lock(&sk
->sk_callback_lock
);
107 if (sk
->sk_sleep
&& waitqueue_active(sk
->sk_sleep
))
108 wake_up(sk
->sk_sleep
);
109 read_unlock(&sk
->sk_callback_lock
);
112 static inline int vcc_writable(struct sock
*sk
)
114 struct atm_vcc
*vcc
= atm_sk(sk
);
116 return (vcc
->qos
.txtp
.max_sdu
+
117 atomic_read(&sk
->sk_wmem_alloc
)) <= sk
->sk_sndbuf
;
120 static void vcc_write_space(struct sock
*sk
)
122 read_lock(&sk
->sk_callback_lock
);
124 if (vcc_writable(sk
)) {
125 if (sk
->sk_sleep
&& waitqueue_active(sk
->sk_sleep
))
126 wake_up_interruptible(sk
->sk_sleep
);
128 sk_wake_async(sk
, 2, POLL_OUT
);
131 read_unlock(&sk
->sk_callback_lock
);
135 int vcc_create(struct socket
*sock
, int protocol
, int family
)
141 if (sock
->type
== SOCK_STREAM
)
143 sk
= sk_alloc(family
, GFP_KERNEL
, 1, NULL
);
146 sock_init_data(sock
, sk
);
147 sk_set_owner(sk
, THIS_MODULE
);
148 sk
->sk_state_change
= vcc_def_wakeup
;
149 sk
->sk_write_space
= vcc_write_space
;
151 vcc
= sk
->sk_protinfo
= kmalloc(sizeof(*vcc
), GFP_KERNEL
);
157 memset(vcc
, 0, sizeof(*vcc
));
160 memset(&vcc
->local
,0,sizeof(struct sockaddr_atmsvc
));
161 memset(&vcc
->remote
,0,sizeof(struct sockaddr_atmsvc
));
162 vcc
->qos
.txtp
.max_sdu
= 1 << 16; /* for meta VCs */
163 atomic_set(&vcc
->sk
->sk_wmem_alloc
, 0);
164 atomic_set(&vcc
->sk
->sk_rmem_alloc
, 0);
167 vcc
->push_oam
= NULL
;
168 vcc
->vpi
= vcc
->vci
= 0; /* no VCI/VPI yet */
169 vcc
->atm_options
= vcc
->aal_options
= 0;
170 sk
->sk_destruct
= vcc_sock_destruct
;
176 static void vcc_destroy_socket(struct sock
*sk
)
178 struct atm_vcc
*vcc
= atm_sk(sk
);
181 clear_bit(ATM_VF_READY
, &vcc
->flags
);
183 if (vcc
->dev
->ops
->close
)
184 vcc
->dev
->ops
->close(vcc
);
186 vcc
->push(vcc
, NULL
); /* atmarpd has no push */
188 vcc_remove_socket(sk
); /* no more receive */
190 while ((skb
= skb_dequeue(&vcc
->sk
->sk_receive_queue
)) != NULL
) {
191 atm_return(vcc
,skb
->truesize
);
195 module_put(vcc
->dev
->ops
->owner
);
196 atm_dev_put(vcc
->dev
);
201 int vcc_release(struct socket
*sock
)
203 struct sock
*sk
= sock
->sk
;
207 vcc_destroy_socket(sock
->sk
);
216 void vcc_release_async(struct atm_vcc
*vcc
, int reply
)
218 set_bit(ATM_VF_CLOSE
, &vcc
->flags
);
219 vcc
->sk
->sk_err
= -reply
;
220 clear_bit(ATM_VF_WAITING
, &vcc
->flags
);
221 vcc
->sk
->sk_state_change(vcc
->sk
);
225 EXPORT_SYMBOL(vcc_release_async
);
228 static int adjust_tp(struct atm_trafprm
*tp
,unsigned char aal
)
232 if (!tp
->traffic_class
) return 0;
235 max_sdu
= ATM_CELL_SIZE
-1;
238 max_sdu
= ATM_MAX_AAL34_PDU
;
241 printk(KERN_WARNING
"ATM: AAL problems ... "
245 max_sdu
= ATM_MAX_AAL5_PDU
;
247 if (!tp
->max_sdu
) tp
->max_sdu
= max_sdu
;
248 else if (tp
->max_sdu
> max_sdu
) return -EINVAL
;
249 if (!tp
->max_cdv
) tp
->max_cdv
= ATM_MAX_CDV
;
254 static int check_ci(struct atm_vcc
*vcc
, short vpi
, int vci
)
256 struct hlist_head
*head
= &vcc_hash
[vci
&
257 (VCC_HTABLE_SIZE
- 1)];
258 struct hlist_node
*node
;
260 struct atm_vcc
*walk
;
262 sk_for_each(s
, node
, head
) {
264 if (walk
->dev
!= vcc
->dev
)
266 if (test_bit(ATM_VF_ADDR
, &walk
->flags
) && walk
->vpi
== vpi
&&
267 walk
->vci
== vci
&& ((walk
->qos
.txtp
.traffic_class
!=
268 ATM_NONE
&& vcc
->qos
.txtp
.traffic_class
!= ATM_NONE
) ||
269 (walk
->qos
.rxtp
.traffic_class
!= ATM_NONE
&&
270 vcc
->qos
.rxtp
.traffic_class
!= ATM_NONE
)))
274 /* allow VCCs with same VPI/VCI iff they don't collide on
275 TX/RX (but we may refuse such sharing for other reasons,
276 e.g. if protocol requires to have both channels) */
282 static int find_ci(struct atm_vcc
*vcc
, short *vpi
, int *vci
)
284 static short p
; /* poor man's per-device cache */
290 if (*vpi
!= ATM_VPI_ANY
&& *vci
!= ATM_VCI_ANY
) {
291 err
= check_ci(vcc
, *vpi
, *vci
);
294 /* last scan may have left values out of bounds for current device */
295 if (*vpi
!= ATM_VPI_ANY
)
297 else if (p
>= 1 << vcc
->dev
->ci_range
.vpi_bits
)
299 if (*vci
!= ATM_VCI_ANY
)
301 else if (c
< ATM_NOT_RSV_VCI
|| c
>= 1 << vcc
->dev
->ci_range
.vci_bits
)
306 if (!check_ci(vcc
, p
, c
)) {
311 if (*vci
== ATM_VCI_ANY
) {
313 if (c
>= 1 << vcc
->dev
->ci_range
.vci_bits
)
316 if ((c
== ATM_NOT_RSV_VCI
|| *vci
!= ATM_VCI_ANY
) &&
317 *vpi
== ATM_VPI_ANY
) {
319 if (p
>= 1 << vcc
->dev
->ci_range
.vpi_bits
) p
= 0;
322 while (old_p
!= p
|| old_c
!= c
);
327 static int __vcc_connect(struct atm_vcc
*vcc
, struct atm_dev
*dev
, short vpi
,
332 if ((vpi
!= ATM_VPI_UNSPEC
&& vpi
!= ATM_VPI_ANY
&&
333 vpi
>> dev
->ci_range
.vpi_bits
) || (vci
!= ATM_VCI_UNSPEC
&&
334 vci
!= ATM_VCI_ANY
&& vci
>> dev
->ci_range
.vci_bits
))
336 if (vci
> 0 && vci
< ATM_NOT_RSV_VCI
&& !capable(CAP_NET_BIND_SERVICE
))
339 if (!try_module_get(dev
->ops
->owner
))
342 write_lock_irq(&vcc_sklist_lock
);
343 if ((error
= find_ci(vcc
, &vpi
, &vci
))) {
344 write_unlock_irq(&vcc_sklist_lock
);
345 goto fail_module_put
;
349 __vcc_insert_socket(vcc
->sk
);
350 write_unlock_irq(&vcc_sklist_lock
);
351 switch (vcc
->qos
.aal
) {
353 error
= atm_init_aal0(vcc
);
354 vcc
->stats
= &dev
->stats
.aal0
;
357 error
= atm_init_aal34(vcc
);
358 vcc
->stats
= &dev
->stats
.aal34
;
361 /* ATM_AAL5 is also used in the "0 for default" case */
362 vcc
->qos
.aal
= ATM_AAL5
;
365 error
= atm_init_aal5(vcc
);
366 vcc
->stats
= &dev
->stats
.aal5
;
371 if (!error
) error
= adjust_tp(&vcc
->qos
.txtp
,vcc
->qos
.aal
);
372 if (!error
) error
= adjust_tp(&vcc
->qos
.rxtp
,vcc
->qos
.aal
);
375 DPRINTK("VCC %d.%d, AAL %d\n",vpi
,vci
,vcc
->qos
.aal
);
376 DPRINTK(" TX: %d, PCR %d..%d, SDU %d\n",vcc
->qos
.txtp
.traffic_class
,
377 vcc
->qos
.txtp
.min_pcr
,vcc
->qos
.txtp
.max_pcr
,vcc
->qos
.txtp
.max_sdu
);
378 DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc
->qos
.rxtp
.traffic_class
,
379 vcc
->qos
.rxtp
.min_pcr
,vcc
->qos
.rxtp
.max_pcr
,vcc
->qos
.rxtp
.max_sdu
);
381 if (dev
->ops
->open
) {
382 if ((error
= dev
->ops
->open(vcc
)))
388 vcc_remove_socket(vcc
->sk
);
390 module_put(dev
->ops
->owner
);
391 /* ensure we get dev module ref count correct */
397 int vcc_connect(struct socket
*sock
, int itf
, short vpi
, int vci
)
400 struct atm_vcc
*vcc
= ATM_SD(sock
);
403 DPRINTK("vcc_connect (vpi %d, vci %d)\n",vpi
,vci
);
404 if (sock
->state
== SS_CONNECTED
)
406 if (sock
->state
!= SS_UNCONNECTED
)
411 if (vpi
!= ATM_VPI_UNSPEC
&& vci
!= ATM_VCI_UNSPEC
)
412 clear_bit(ATM_VF_PARTIAL
,&vcc
->flags
);
414 if (test_bit(ATM_VF_PARTIAL
,&vcc
->flags
))
416 DPRINTK("vcc_connect (TX: cl %d,bw %d-%d,sdu %d; "
417 "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n",
418 vcc
->qos
.txtp
.traffic_class
,vcc
->qos
.txtp
.min_pcr
,
419 vcc
->qos
.txtp
.max_pcr
,vcc
->qos
.txtp
.max_sdu
,
420 vcc
->qos
.rxtp
.traffic_class
,vcc
->qos
.rxtp
.min_pcr
,
421 vcc
->qos
.rxtp
.max_pcr
,vcc
->qos
.rxtp
.max_sdu
,
422 vcc
->qos
.aal
== ATM_AAL5
? "" : vcc
->qos
.aal
== ATM_AAL0
? "" :
423 " ??? code ",vcc
->qos
.aal
== ATM_AAL0
? 0 : vcc
->qos
.aal
);
424 if (!test_bit(ATM_VF_HASQOS
, &vcc
->flags
))
426 if (vcc
->qos
.txtp
.traffic_class
== ATM_ANYCLASS
||
427 vcc
->qos
.rxtp
.traffic_class
== ATM_ANYCLASS
)
429 if (itf
!= ATM_ITF_ANY
) {
430 dev
= atm_dev_lookup(itf
);
433 error
= __vcc_connect(vcc
, dev
, vpi
, vci
);
439 struct list_head
*p
, *next
;
442 spin_lock(&atm_dev_lock
);
443 list_for_each_safe(p
, next
, &atm_devs
) {
444 dev
= list_entry(p
, struct atm_dev
, dev_list
);
446 spin_unlock(&atm_dev_lock
);
447 if (!__vcc_connect(vcc
, dev
, vpi
, vci
))
451 spin_lock(&atm_dev_lock
);
453 spin_unlock(&atm_dev_lock
);
457 if (vpi
== ATM_VPI_UNSPEC
|| vci
== ATM_VCI_UNSPEC
)
458 set_bit(ATM_VF_PARTIAL
,&vcc
->flags
);
459 if (test_bit(ATM_VF_READY
,&ATM_SD(sock
)->flags
))
460 sock
->state
= SS_CONNECTED
;
465 int vcc_recvmsg(struct kiocb
*iocb
, struct socket
*sock
, struct msghdr
*msg
,
466 size_t size
, int flags
)
468 struct sock
*sk
= sock
->sk
;
471 int copied
, error
= -EINVAL
;
473 if (sock
->state
!= SS_CONNECTED
)
475 if (flags
& ~MSG_DONTWAIT
) /* only handle MSG_DONTWAIT */
478 if (test_bit(ATM_VF_RELEASED
,&vcc
->flags
) ||
479 test_bit(ATM_VF_CLOSE
,&vcc
->flags
) ||
480 !test_bit(ATM_VF_READY
, &vcc
->flags
))
483 skb
= skb_recv_datagram(sk
, flags
, flags
& MSG_DONTWAIT
, &error
);
490 msg
->msg_flags
|= MSG_TRUNC
;
493 error
= skb_copy_datagram_iovec(skb
, 0, msg
->msg_iov
, copied
);
496 sock_recv_timestamp(msg
, sk
, skb
);
497 DPRINTK("RcvM %d -= %d\n", atomic_read(&vcc
->sk
->rmem_alloc
), skb
->truesize
);
498 atm_return(vcc
, skb
->truesize
);
499 skb_free_datagram(sk
, skb
);
504 int vcc_sendmsg(struct kiocb
*iocb
, struct socket
*sock
, struct msghdr
*m
,
507 struct sock
*sk
= sock
->sk
;
512 const void __user
*buff
;
516 if (sock
->state
!= SS_CONNECTED
) {
524 if (m
->msg_iovlen
!= 1) {
525 error
= -ENOSYS
; /* fix this later @@@ */
528 buff
= m
->msg_iov
->iov_base
;
529 size
= m
->msg_iov
->iov_len
;
531 if (test_bit(ATM_VF_RELEASED
, &vcc
->flags
) ||
532 test_bit(ATM_VF_CLOSE
, &vcc
->flags
) ||
533 !test_bit(ATM_VF_READY
, &vcc
->flags
)) {
535 send_sig(SIGPIPE
, current
, 0);
542 if (size
< 0 || size
> vcc
->qos
.txtp
.max_sdu
) {
546 /* verify_area is done by net/socket.c */
547 eff
= (size
+3) & ~3; /* align to word boundary */
548 prepare_to_wait(sk
->sk_sleep
, &wait
, TASK_INTERRUPTIBLE
);
550 while (!(skb
= alloc_tx(vcc
,eff
))) {
551 if (m
->msg_flags
& MSG_DONTWAIT
) {
556 if (signal_pending(current
)) {
557 error
= -ERESTARTSYS
;
560 if (test_bit(ATM_VF_RELEASED
,&vcc
->flags
) ||
561 test_bit(ATM_VF_CLOSE
,&vcc
->flags
) ||
562 !test_bit(ATM_VF_READY
,&vcc
->flags
)) {
564 send_sig(SIGPIPE
, current
, 0);
567 prepare_to_wait(sk
->sk_sleep
, &wait
, TASK_INTERRUPTIBLE
);
569 finish_wait(sk
->sk_sleep
, &wait
);
572 skb
->dev
= NULL
; /* for paths shared with net_device interfaces */
573 ATM_SKB(skb
)->atm_options
= vcc
->atm_options
;
574 if (copy_from_user(skb_put(skb
,size
),buff
,size
)) {
579 if (eff
!= size
) memset(skb
->data
+size
,0,eff
-size
);
580 error
= vcc
->dev
->ops
->send(vcc
,skb
);
581 error
= error
? error
: size
;
588 unsigned int vcc_poll(struct file
*file
, struct socket
*sock
, poll_table
*wait
)
590 struct sock
*sk
= sock
->sk
;
594 poll_wait(file
, sk
->sk_sleep
, wait
);
599 /* exceptional events */
603 if (test_bit(ATM_VF_RELEASED
, &vcc
->flags
) ||
604 test_bit(ATM_VF_CLOSE
, &vcc
->flags
))
608 if (!skb_queue_empty(&sk
->sk_receive_queue
))
609 mask
|= POLLIN
| POLLRDNORM
;
612 if (sock
->state
== SS_CONNECTING
&&
613 test_bit(ATM_VF_WAITING
, &vcc
->flags
))
616 if (vcc
->qos
.txtp
.traffic_class
!= ATM_NONE
&&
617 vcc_writable(vcc
->sk
))
618 mask
|= POLLOUT
| POLLWRNORM
| POLLWRBAND
;
624 static int atm_change_qos(struct atm_vcc
*vcc
,struct atm_qos
*qos
)
629 * Don't let the QoS change the already connected AAL type nor the
632 if (qos
->aal
!= vcc
->qos
.aal
||
633 qos
->rxtp
.traffic_class
!= vcc
->qos
.rxtp
.traffic_class
||
634 qos
->txtp
.traffic_class
!= vcc
->qos
.txtp
.traffic_class
)
636 error
= adjust_tp(&qos
->txtp
,qos
->aal
);
637 if (!error
) error
= adjust_tp(&qos
->rxtp
,qos
->aal
);
638 if (error
) return error
;
639 if (!vcc
->dev
->ops
->change_qos
) return -EOPNOTSUPP
;
640 if (vcc
->sk
->sk_family
== AF_ATMPVC
)
641 return vcc
->dev
->ops
->change_qos(vcc
,qos
,ATM_MF_SET
);
642 return svc_change_qos(vcc
,qos
);
646 static int check_tp(struct atm_trafprm
*tp
)
648 /* @@@ Should be merged with adjust_tp */
649 if (!tp
->traffic_class
|| tp
->traffic_class
== ATM_ANYCLASS
) return 0;
650 if (tp
->traffic_class
!= ATM_UBR
&& !tp
->min_pcr
&& !tp
->pcr
&&
651 !tp
->max_pcr
) return -EINVAL
;
652 if (tp
->min_pcr
== ATM_MAX_PCR
) return -EINVAL
;
653 if (tp
->min_pcr
&& tp
->max_pcr
&& tp
->max_pcr
!= ATM_MAX_PCR
&&
654 tp
->min_pcr
> tp
->max_pcr
) return -EINVAL
;
656 * We allow pcr to be outside [min_pcr,max_pcr], because later
657 * adjustment may still push it in the valid range.
663 static int check_qos(struct atm_qos
*qos
)
667 if (!qos
->txtp
.traffic_class
&& !qos
->rxtp
.traffic_class
)
669 if (qos
->txtp
.traffic_class
!= qos
->rxtp
.traffic_class
&&
670 qos
->txtp
.traffic_class
&& qos
->rxtp
.traffic_class
&&
671 qos
->txtp
.traffic_class
!= ATM_ANYCLASS
&&
672 qos
->rxtp
.traffic_class
!= ATM_ANYCLASS
) return -EINVAL
;
673 error
= check_tp(&qos
->txtp
);
674 if (error
) return error
;
675 return check_tp(&qos
->rxtp
);
678 int vcc_setsockopt(struct socket
*sock
, int level
, int optname
,
679 char __user
*optval
, int optlen
)
685 if (__SO_LEVEL_MATCH(optname
, level
) && optlen
!= __SO_SIZE(optname
))
694 if (copy_from_user(&qos
,optval
,sizeof(qos
)))
696 error
= check_qos(&qos
);
697 if (error
) return error
;
698 if (sock
->state
== SS_CONNECTED
)
699 return atm_change_qos(vcc
,&qos
);
700 if (sock
->state
!= SS_UNCONNECTED
)
703 set_bit(ATM_VF_HASQOS
,&vcc
->flags
);
707 if (get_user(value
,(unsigned long __user
*)optval
))
709 if (value
) vcc
->atm_options
|= ATM_ATMOPT_CLP
;
710 else vcc
->atm_options
&= ~ATM_ATMOPT_CLP
;
713 if (level
== SOL_SOCKET
) return -EINVAL
;
716 if (!vcc
->dev
|| !vcc
->dev
->ops
->setsockopt
) return -EINVAL
;
717 return vcc
->dev
->ops
->setsockopt(vcc
,level
,optname
,optval
,optlen
);
721 int vcc_getsockopt(struct socket
*sock
, int level
, int optname
,
722 char __user
*optval
, int __user
*optlen
)
727 if (get_user(len
, optlen
))
729 if (__SO_LEVEL_MATCH(optname
, level
) && len
!= __SO_SIZE(optname
))
735 if (!test_bit(ATM_VF_HASQOS
,&vcc
->flags
))
737 return copy_to_user(optval
,&vcc
->qos
,sizeof(vcc
->qos
)) ?
740 return put_user(vcc
->atm_options
& ATM_ATMOPT_CLP
? 1 :
741 0,(unsigned long __user
*)optval
) ? -EFAULT
: 0;
744 struct sockaddr_atmpvc pvc
;
747 !test_bit(ATM_VF_ADDR
,&vcc
->flags
))
749 pvc
.sap_family
= AF_ATMPVC
;
750 pvc
.sap_addr
.itf
= vcc
->dev
->number
;
751 pvc
.sap_addr
.vpi
= vcc
->vpi
;
752 pvc
.sap_addr
.vci
= vcc
->vci
;
753 return copy_to_user(optval
,&pvc
,sizeof(pvc
)) ?
757 if (level
== SOL_SOCKET
) return -EINVAL
;
760 if (!vcc
->dev
|| !vcc
->dev
->ops
->getsockopt
) return -EINVAL
;
761 return vcc
->dev
->ops
->getsockopt(vcc
, level
, optname
, optval
, len
);
765 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
766 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
768 struct net_bridge_fdb_entry
*(*br_fdb_get_hook
)(struct net_bridge
*br
,
769 unsigned char *addr
) = NULL
;
770 void (*br_fdb_put_hook
)(struct net_bridge_fdb_entry
*ent
) = NULL
;
771 #if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE)
772 EXPORT_SYMBOL(br_fdb_get_hook
);
773 EXPORT_SYMBOL(br_fdb_put_hook
);
774 #endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */
775 #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
776 #endif /* defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) */
779 static int __init
atm_init(void)
783 if ((error
= atmpvc_init()) < 0) {
784 printk(KERN_ERR
"atmpvc_init() failed with %d\n", error
);
787 if ((error
= atmsvc_init()) < 0) {
788 printk(KERN_ERR
"atmsvc_init() failed with %d\n", error
);
791 if ((error
= atm_proc_init()) < 0) {
792 printk(KERN_ERR
"atm_proc_init() failed with %d\n",error
);
803 static void __exit
atm_exit(void)
810 module_init(atm_init
);
811 module_exit(atm_exit
);
813 MODULE_LICENSE("GPL");
814 MODULE_ALIAS_NETPROTO(PF_ATMPVC
);
815 MODULE_ALIAS_NETPROTO(PF_ATMSVC
);