1 /* net/atm/pvc.c - ATM PVC sockets */
3 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
6 #include <linux/net.h> /* struct socket, struct proto_ops */
7 #include <linux/atm.h> /* ATM stuff */
8 #include <linux/atmdev.h> /* ATM devices */
9 #include <linux/errno.h> /* error codes */
10 #include <linux/kernel.h> /* printk */
11 #include <linux/init.h>
12 #include <linux/skbuff.h>
13 #include <linux/bitops.h>
14 #include <linux/export.h>
15 #include <net/sock.h> /* for sock_no_* */
17 #include "resources.h" /* devs and vccs */
18 #include "common.h" /* common for PVCs and SVCs */
21 static int pvc_shutdown(struct socket
*sock
, int how
)
26 static int pvc_bind(struct socket
*sock
, struct sockaddr
*sockaddr
,
29 struct sock
*sk
= sock
->sk
;
30 struct sockaddr_atmpvc
*addr
;
34 if (sockaddr_len
!= sizeof(struct sockaddr_atmpvc
))
36 addr
= (struct sockaddr_atmpvc
*)sockaddr
;
37 if (addr
->sap_family
!= AF_ATMPVC
)
41 if (!test_bit(ATM_VF_HASQOS
, &vcc
->flags
)) {
45 if (test_bit(ATM_VF_PARTIAL
, &vcc
->flags
)) {
46 if (vcc
->vpi
!= ATM_VPI_UNSPEC
)
47 addr
->sap_addr
.vpi
= vcc
->vpi
;
48 if (vcc
->vci
!= ATM_VCI_UNSPEC
)
49 addr
->sap_addr
.vci
= vcc
->vci
;
51 error
= vcc_connect(sock
, addr
->sap_addr
.itf
, addr
->sap_addr
.vpi
,
58 static int pvc_connect(struct socket
*sock
, struct sockaddr
*sockaddr
,
59 int sockaddr_len
, int flags
)
61 return pvc_bind(sock
, sockaddr
, sockaddr_len
);
64 static int pvc_setsockopt(struct socket
*sock
, int level
, int optname
,
65 char __user
*optval
, unsigned int optlen
)
67 struct sock
*sk
= sock
->sk
;
71 error
= vcc_setsockopt(sock
, level
, optname
, optval
, optlen
);
76 static int pvc_getsockopt(struct socket
*sock
, int level
, int optname
,
77 char __user
*optval
, int __user
*optlen
)
79 struct sock
*sk
= sock
->sk
;
83 error
= vcc_getsockopt(sock
, level
, optname
, optval
, optlen
);
88 static int pvc_getname(struct socket
*sock
, struct sockaddr
*sockaddr
,
89 int *sockaddr_len
, int peer
)
91 struct sockaddr_atmpvc
*addr
;
92 struct atm_vcc
*vcc
= ATM_SD(sock
);
94 if (!vcc
->dev
|| !test_bit(ATM_VF_ADDR
, &vcc
->flags
))
96 *sockaddr_len
= sizeof(struct sockaddr_atmpvc
);
97 addr
= (struct sockaddr_atmpvc
*)sockaddr
;
98 memset(addr
, 0, sizeof(*addr
));
99 addr
->sap_family
= AF_ATMPVC
;
100 addr
->sap_addr
.itf
= vcc
->dev
->number
;
101 addr
->sap_addr
.vpi
= vcc
->vpi
;
102 addr
->sap_addr
.vci
= vcc
->vci
;
106 static const struct proto_ops pvc_proto_ops
= {
108 .owner
= THIS_MODULE
,
110 .release
= vcc_release
,
112 .connect
= pvc_connect
,
113 .socketpair
= sock_no_socketpair
,
114 .accept
= sock_no_accept
,
115 .getname
= pvc_getname
,
119 .compat_ioctl
= vcc_compat_ioctl
,
121 .listen
= sock_no_listen
,
122 .shutdown
= pvc_shutdown
,
123 .setsockopt
= pvc_setsockopt
,
124 .getsockopt
= pvc_getsockopt
,
125 .sendmsg
= vcc_sendmsg
,
126 .recvmsg
= vcc_recvmsg
,
127 .mmap
= sock_no_mmap
,
128 .sendpage
= sock_no_sendpage
,
132 static int pvc_create(struct net
*net
, struct socket
*sock
, int protocol
,
135 if (net
!= &init_net
)
136 return -EAFNOSUPPORT
;
138 sock
->ops
= &pvc_proto_ops
;
139 return vcc_create(net
, sock
, protocol
, PF_ATMPVC
, kern
);
142 static const struct net_proto_family pvc_family_ops
= {
144 .create
= pvc_create
,
145 .owner
= THIS_MODULE
,
150 * Initialize the ATM PVC protocol family
154 int __init
atmpvc_init(void)
156 return sock_register(&pvc_family_ops
);
159 void atmpvc_exit(void)
161 sock_unregister(PF_ATMPVC
);