11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* net/atm/pvc.c - ATM PVC sockets */ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/net.h> /* struct socket, struct proto_ops */ 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/atm.h> /* ATM stuff */ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/atmdev.h> /* ATM devices */ 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> /* error codes */ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> /* printk */ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 14bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker#include <linux/export.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/sock.h> /* for sock_no_* */ 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "resources.h" /* devs and vccs */ 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "common.h" /* common for PVCs and SVCs */ 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 216b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perchesstatic int pvc_shutdown(struct socket *sock, int how) 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 266b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perchesstatic int pvc_bind(struct socket *sock, struct sockaddr *sockaddr, 276b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches int sockaddr_len) 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sockaddr_atmpvc *addr; 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct atm_vcc *vcc; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 346b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches if (sockaddr_len != sizeof(struct sockaddr_atmpvc)) 356b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches return -EINVAL; 366b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches addr = (struct sockaddr_atmpvc *)sockaddr; 376b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches if (addr->sap_family != AF_ATMPVC) 386b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches return -EAFNOSUPPORT; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vcc = ATM_SD(sock); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) { 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = -EBADFD; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 456b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches if (test_bit(ATM_VF_PARTIAL, &vcc->flags)) { 466b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches if (vcc->vpi != ATM_VPI_UNSPEC) 476b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches addr->sap_addr.vpi = vcc->vpi; 486b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches if (vcc->vci != ATM_VCI_UNSPEC) 496b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches addr->sap_addr.vci = vcc->vci; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = vcc_connect(sock, addr->sap_addr.itf, addr->sap_addr.vpi, 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr->sap_addr.vci); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 586b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perchesstatic int pvc_connect(struct socket *sock, struct sockaddr *sockaddr, 596b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches int sockaddr_len, int flags) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 616b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches return pvc_bind(sock, sockaddr, sockaddr_len); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pvc_setsockopt(struct socket *sock, int level, int optname, 65b7058842c940ad2c08dd829b21e5c92ebe3b8758David S. Miller char __user *optval, unsigned int optlen) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = vcc_setsockopt(sock, level, optname, optval, optlen); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pvc_getsockopt(struct socket *sock, int level, int optname, 77f7d57453d20e27de69ecafd121005e9d13a0f427YOSHIFUJI Hideaki char __user *optval, int __user *optlen) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = vcc_getsockopt(sock, level, optname, optval, optlen); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 886b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perchesstatic int pvc_getname(struct socket *sock, struct sockaddr *sockaddr, 896b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches int *sockaddr_len, int peer) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sockaddr_atmpvc *addr; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct atm_vcc *vcc = ATM_SD(sock); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 946b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags)) 956b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches return -ENOTCONN; 96f7d57453d20e27de69ecafd121005e9d13a0f427YOSHIFUJI Hideaki *sockaddr_len = sizeof(struct sockaddr_atmpvc); 976b6dd498f409463635c4f29a3a49585bc7e5d43eJoe Perches addr = (struct sockaddr_atmpvc *)sockaddr; 983c0c5cfdcd4d69ffc4b9c0907cec99039f30a50aMathias Krause memset(addr, 0, sizeof(*addr)); 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr->sap_family = AF_ATMPVC; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr->sap_addr.itf = vcc->dev->number; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr->sap_addr.vpi = vcc->vpi; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr->sap_addr.vci = vcc->vci; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10690ddc4f0470427df306f308ad03db6b6b21644b8Eric Dumazetstatic const struct proto_ops pvc_proto_ops = { 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .family = PF_ATMPVC, 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = vcc_release, 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bind = pvc_bind, 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .connect = pvc_connect, 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .socketpair = sock_no_socketpair, 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .accept = sock_no_accept, 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .getname = pvc_getname, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .poll = vcc_poll, 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ioctl = vcc_ioctl, 1188865c418caf4e9dd2c24bdfae3a5a4106e143e60David Woodhouse#ifdef CONFIG_COMPAT 1198865c418caf4e9dd2c24bdfae3a5a4106e143e60David Woodhouse .compat_ioctl = vcc_compat_ioctl, 1208865c418caf4e9dd2c24bdfae3a5a4106e143e60David Woodhouse#endif 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .listen = sock_no_listen, 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .shutdown = pvc_shutdown, 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .setsockopt = pvc_setsockopt, 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .getsockopt = pvc_getsockopt, 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sendmsg = vcc_sendmsg, 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .recvmsg = vcc_recvmsg, 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mmap = sock_no_mmap, 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sendpage = sock_no_sendpage, 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1323f378b684453f2a028eda463ce383370545d9cc9Eric Parisstatic int pvc_create(struct net *net, struct socket *sock, int protocol, 1333f378b684453f2a028eda463ce383370545d9cc9Eric Paris int kern) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1351b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biederman if (net != &init_net) 1361b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biederman return -EAFNOSUPPORT; 1371b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biederman 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock->ops = &pvc_proto_ops; 1391b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biederman return vcc_create(net, sock, protocol, PF_ATMPVC); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 142ec1b4cf74c81bfd0fbe5bf62bafc86c45917e72fStephen Hemmingerstatic const struct net_proto_family pvc_family_ops = { 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .family = PF_ATMPVC, 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .create = pvc_create, 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize the ATM PVC protocol family 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init atmpvc_init(void) 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sock_register(&pvc_family_ops); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid atmpvc_exit(void) 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_unregister(PF_ATMPVC); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 163