1 /* net/atm/pvc.c - ATM PVC sockets */ 2 3 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ 4 5 6 #include <linux/config.h> 7 #include <linux/net.h> /* struct socket, struct proto_ops */ 8 #include <linux/atm.h> /* ATM stuff */ 9 #include <linux/atmdev.h> /* ATM devices */ 10 #include <linux/errno.h> /* error codes */ 11 #include <linux/kernel.h> /* printk */ 12 #include <linux/init.h> 13 #include <linux/skbuff.h> 14 #include <linux/bitops.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 27 static int pvc_bind(struct socket *sock,struct sockaddr *sockaddr, 28 int sockaddr_len) 29 { 30 struct sock *sk = sock->sk; 31 struct sockaddr_atmpvc *addr; 32 struct atm_vcc *vcc; 33 int error; 34 35 if (sockaddr_len != sizeof(struct sockaddr_atmpvc)) return -EINVAL; 36 addr = (struct sockaddr_atmpvc *) sockaddr; 37 if (addr->sap_family != AF_ATMPVC) return -EAFNOSUPPORT; 38 lock_sock(sk); 39 vcc = ATM_SD(sock); 40 if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) { 41 error = -EBADFD; 42 goto out; 43 } 44 if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) { 45 if (vcc->vpi != ATM_VPI_UNSPEC) addr->sap_addr.vpi = vcc->vpi; 46 if (vcc->vci != ATM_VCI_UNSPEC) addr->sap_addr.vci = vcc->vci; 47 } 48 error = vcc_connect(sock, addr->sap_addr.itf, addr->sap_addr.vpi, 49 addr->sap_addr.vci); 50 out: 51 release_sock(sk); 52 return error; 53 } 54 55 56 static int pvc_connect(struct socket *sock,struct sockaddr *sockaddr, 57 int sockaddr_len,int flags) 58 { 59 return pvc_bind(sock,sockaddr,sockaddr_len); 60 } 61 62 static int pvc_setsockopt(struct socket *sock, int level, int optname, 63 char __user *optval, int optlen) 64 { 65 struct sock *sk = sock->sk; 66 int error; 67 68 lock_sock(sk); 69 error = vcc_setsockopt(sock, level, optname, optval, optlen); 70 release_sock(sk); 71 return error; 72 } 73 74 75 static int pvc_getsockopt(struct socket *sock, int level, int optname, 76 char __user *optval, int __user *optlen) 77 { 78 struct sock *sk = sock->sk; 79 int error; 80 81 lock_sock(sk); 82 error = vcc_getsockopt(sock, level, optname, optval, optlen); 83 release_sock(sk); 84 return error; 85 } 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)) return -ENOTCONN; 95 *sockaddr_len = sizeof(struct sockaddr_atmpvc); 96 addr = (struct sockaddr_atmpvc *) sockaddr; 97 addr->sap_family = AF_ATMPVC; 98 addr->sap_addr.itf = vcc->dev->number; 99 addr->sap_addr.vpi = vcc->vpi; 100 addr->sap_addr.vci = vcc->vci; 101 return 0; 102 } 103 104 105 static struct proto_ops pvc_proto_ops = { 106 .family = PF_ATMPVC, 107 .owner = THIS_MODULE, 108 109 .release = vcc_release, 110 .bind = pvc_bind, 111 .connect = pvc_connect, 112 .socketpair = sock_no_socketpair, 113 .accept = sock_no_accept, 114 .getname = pvc_getname, 115 .poll = vcc_poll, 116 .ioctl = vcc_ioctl, 117 .listen = sock_no_listen, 118 .shutdown = pvc_shutdown, 119 .setsockopt = pvc_setsockopt, 120 .getsockopt = pvc_getsockopt, 121 .sendmsg = vcc_sendmsg, 122 .recvmsg = vcc_recvmsg, 123 .mmap = sock_no_mmap, 124 .sendpage = sock_no_sendpage, 125 }; 126 127 128 static int pvc_create(struct socket *sock,int protocol) 129 { 130 sock->ops = &pvc_proto_ops; 131 return vcc_create(sock, protocol, PF_ATMPVC); 132 } 133 134 135 static struct net_proto_family pvc_family_ops = { 136 .family = PF_ATMPVC, 137 .create = pvc_create, 138 .owner = THIS_MODULE, 139 }; 140 141 142 /* 143 * Initialize the ATM PVC protocol family 144 */ 145 146 147 int __init atmpvc_init(void) 148 { 149 return sock_register(&pvc_family_ops); 150 } 151 152 void atmpvc_exit(void) 153 { 154 sock_unregister(PF_ATMPVC); 155 } 156