Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pvc.c
Go to the documentation of this file.
1 /* net/atm/pvc.c - ATM PVC sockets */
2 
3 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4 
5 
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_* */
16 
17 #include "resources.h" /* devs and vccs */
18 #include "common.h" /* common for PVCs and SVCs */
19 
20 
21 static int pvc_shutdown(struct socket *sock, int how)
22 {
23  return 0;
24 }
25 
26 static int pvc_bind(struct socket *sock, struct sockaddr *sockaddr,
27  int sockaddr_len)
28 {
29  struct sock *sk = sock->sk;
30  struct sockaddr_atmpvc *addr;
31  struct atm_vcc *vcc;
32  int error;
33 
34  if (sockaddr_len != sizeof(struct sockaddr_atmpvc))
35  return -EINVAL;
36  addr = (struct sockaddr_atmpvc *)sockaddr;
37  if (addr->sap_family != AF_ATMPVC)
38  return -EAFNOSUPPORT;
39  lock_sock(sk);
40  vcc = ATM_SD(sock);
41  if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) {
42  error = -EBADFD;
43  goto out;
44  }
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;
50  }
51  error = vcc_connect(sock, addr->sap_addr.itf, addr->sap_addr.vpi,
52  addr->sap_addr.vci);
53 out:
54  release_sock(sk);
55  return error;
56 }
57 
58 static int pvc_connect(struct socket *sock, struct sockaddr *sockaddr,
59  int sockaddr_len, int flags)
60 {
61  return pvc_bind(sock, sockaddr, sockaddr_len);
62 }
63 
64 static int pvc_setsockopt(struct socket *sock, int level, int optname,
65  char __user *optval, unsigned int optlen)
66 {
67  struct sock *sk = sock->sk;
68  int error;
69 
70  lock_sock(sk);
71  error = vcc_setsockopt(sock, level, optname, optval, optlen);
72  release_sock(sk);
73  return error;
74 }
75 
76 static int pvc_getsockopt(struct socket *sock, int level, int optname,
77  char __user *optval, int __user *optlen)
78 {
79  struct sock *sk = sock->sk;
80  int error;
81 
82  lock_sock(sk);
83  error = vcc_getsockopt(sock, level, optname, optval, optlen);
84  release_sock(sk);
85  return error;
86 }
87 
88 static int pvc_getname(struct socket *sock, struct sockaddr *sockaddr,
89  int *sockaddr_len, int peer)
90 {
91  struct sockaddr_atmpvc *addr;
92  struct atm_vcc *vcc = ATM_SD(sock);
93 
94  if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags))
95  return -ENOTCONN;
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;
103  return 0;
104 }
105 
106 static const struct proto_ops pvc_proto_ops = {
107  .family = PF_ATMPVC,
108  .owner = THIS_MODULE,
109 
110  .release = vcc_release,
111  .bind = pvc_bind,
112  .connect = pvc_connect,
113  .socketpair = sock_no_socketpair,
114  .accept = sock_no_accept,
115  .getname = pvc_getname,
116  .poll = vcc_poll,
117  .ioctl = vcc_ioctl,
118 #ifdef CONFIG_COMPAT
119  .compat_ioctl = vcc_compat_ioctl,
120 #endif
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,
129 };
130 
131 
132 static int pvc_create(struct net *net, struct socket *sock, int protocol,
133  int kern)
134 {
135  if (net != &init_net)
136  return -EAFNOSUPPORT;
137 
138  sock->ops = &pvc_proto_ops;
139  return vcc_create(net, sock, protocol, PF_ATMPVC);
140 }
141 
142 static const struct net_proto_family pvc_family_ops = {
143  .family = PF_ATMPVC,
144  .create = pvc_create,
145  .owner = THIS_MODULE,
146 };
147 
148 
149 /*
150  * Initialize the ATM PVC protocol family
151  */
152 
153 
155 {
156  return sock_register(&pvc_family_ops);
157 }
158 
159 void atmpvc_exit(void)
160 {
162 }