pvc.c revision 1b8d7ae42d02e483ad94035cca851e4f7fbecb40
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> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/sock.h> /* for sock_no_* */ 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "resources.h" /* devs and vccs */ 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "common.h" /* common for PVCs and SVCs */ 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pvc_shutdown(struct socket *sock,int how) 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pvc_bind(struct socket *sock,struct sockaddr *sockaddr, 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 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 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sockaddr_len != sizeof(struct sockaddr_atmpvc)) return -EINVAL; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = (struct sockaddr_atmpvc *) sockaddr; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (addr->sap_family != AF_ATMPVC) return -EAFNOSUPPORT; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vcc = ATM_SD(sock); 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) { 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = -EBADFD; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) { 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vcc->vpi != ATM_VPI_UNSPEC) addr->sap_addr.vpi = vcc->vpi; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vcc->vci != ATM_VCI_UNSPEC) addr->sap_addr.vci = vcc->vci; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = vcc_connect(sock, addr->sap_addr.itf, addr->sap_addr.vpi, 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr->sap_addr.vci); 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pvc_connect(struct socket *sock,struct sockaddr *sockaddr, 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int sockaddr_len,int flags) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pvc_bind(sock,sockaddr,sockaddr_len); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pvc_setsockopt(struct socket *sock, int level, int optname, 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char __user *optval, int optlen) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = vcc_setsockopt(sock, level, optname, optval, optlen); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pvc_getsockopt(struct socket *sock, int level, int optname, 75f7d57453d20e27de69ecafd121005e9d13a0f427YOSHIFUJI Hideaki char __user *optval, int __user *optlen) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = vcc_getsockopt(sock, level, optname, optval, optlen); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pvc_getname(struct socket *sock,struct sockaddr *sockaddr, 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int *sockaddr_len,int peer) 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sockaddr_atmpvc *addr; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct atm_vcc *vcc = ATM_SD(sock); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!vcc->dev || !test_bit(ATM_VF_ADDR,&vcc->flags)) return -ENOTCONN; 94f7d57453d20e27de69ecafd121005e9d13a0f427YOSHIFUJI Hideaki *sockaddr_len = sizeof(struct sockaddr_atmpvc); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = (struct sockaddr_atmpvc *) sockaddr; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr->sap_family = AF_ATMPVC; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr->sap_addr.itf = vcc->dev->number; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr->sap_addr.vpi = vcc->vpi; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr->sap_addr.vci = vcc->vci; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10490ddc4f0470427df306f308ad03db6b6b21644b8Eric Dumazetstatic const struct proto_ops pvc_proto_ops = { 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .family = PF_ATMPVC, 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = vcc_release, 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bind = pvc_bind, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .connect = pvc_connect, 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .socketpair = sock_no_socketpair, 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .accept = sock_no_accept, 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .getname = pvc_getname, 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .poll = vcc_poll, 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ioctl = vcc_ioctl, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .listen = sock_no_listen, 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .shutdown = pvc_shutdown, 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .setsockopt = pvc_setsockopt, 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .getsockopt = pvc_getsockopt, 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sendmsg = vcc_sendmsg, 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .recvmsg = vcc_recvmsg, 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mmap = sock_no_mmap, 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sendpage = sock_no_sendpage, 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biedermanstatic int pvc_create(struct net *net, struct socket *sock,int protocol) 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1291b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biederman if (net != &init_net) 1301b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biederman return -EAFNOSUPPORT; 1311b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biederman 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock->ops = &pvc_proto_ops; 1331b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biederman return vcc_create(net, sock, protocol, PF_ATMPVC); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_proto_family pvc_family_ops = { 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .family = PF_ATMPVC, 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .create = pvc_create, 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize the ATM PVC protocol family 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init atmpvc_init(void) 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sock_register(&pvc_family_ops); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid atmpvc_exit(void) 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_unregister(PF_ATMPVC); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 158