1 /* ATM ioctl handling */ 2 3 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ 4 /* 2003 John Levon <levon@movementarian.org> */ 5 6 7 #include <linux/module.h> 8 #include <linux/kmod.h> 9 #include <linux/net.h> /* struct socket, struct proto_ops */ 10 #include <linux/atm.h> /* ATM stuff */ 11 #include <linux/atmdev.h> 12 #include <linux/atmclip.h> /* CLIP_*ENCAP */ 13 #include <linux/atmarp.h> /* manifest constants */ 14 #include <linux/capability.h> 15 #include <linux/sonet.h> /* for ioctls */ 16 #include <linux/atmsvc.h> 17 #include <linux/atmmpc.h> 18 #include <net/atmclip.h> 19 #include <linux/atmlec.h> 20 #include <linux/mutex.h> 21 #include <asm/ioctls.h> 22 23 #include "resources.h" 24 #include "signaling.h" /* for WAITING and sigd_attach */ 25 #include "common.h" 26 27 28 static DEFINE_MUTEX(ioctl_mutex); 29 static LIST_HEAD(ioctl_list); 30 31 32 void register_atm_ioctl(struct atm_ioctl *ioctl) 33 { 34 mutex_lock(&ioctl_mutex); 35 list_add_tail(&ioctl->list, &ioctl_list); 36 mutex_unlock(&ioctl_mutex); 37 } 38 39 void deregister_atm_ioctl(struct atm_ioctl *ioctl) 40 { 41 mutex_lock(&ioctl_mutex); 42 list_del(&ioctl->list); 43 mutex_unlock(&ioctl_mutex); 44 } 45 46 EXPORT_SYMBOL(register_atm_ioctl); 47 EXPORT_SYMBOL(deregister_atm_ioctl); 48 49 int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 50 { 51 struct sock *sk = sock->sk; 52 struct atm_vcc *vcc; 53 int error; 54 struct list_head * pos; 55 void __user *argp = (void __user *)arg; 56 57 vcc = ATM_SD(sock); 58 switch (cmd) { 59 case SIOCOUTQ: 60 if (sock->state != SS_CONNECTED || 61 !test_bit(ATM_VF_READY, &vcc->flags)) { 62 error = -EINVAL; 63 goto done; 64 } 65 error = put_user(sk->sk_sndbuf - 66 atomic_read(&sk->sk_wmem_alloc), 67 (int __user *) argp) ? -EFAULT : 0; 68 goto done; 69 case SIOCINQ: 70 { 71 struct sk_buff *skb; 72 73 if (sock->state != SS_CONNECTED) { 74 error = -EINVAL; 75 goto done; 76 } 77 skb = skb_peek(&sk->sk_receive_queue); 78 error = put_user(skb ? skb->len : 0, 79 (int __user *)argp) ? -EFAULT : 0; 80 goto done; 81 } 82 case SIOCGSTAMP: /* borrowed from IP */ 83 error = sock_get_timestamp(sk, argp); 84 goto done; 85 case SIOCGSTAMPNS: /* borrowed from IP */ 86 error = sock_get_timestampns(sk, argp); 87 goto done; 88 case ATM_SETSC: 89 printk(KERN_WARNING "ATM_SETSC is obsolete\n"); 90 error = 0; 91 goto done; 92 case ATMSIGD_CTRL: 93 if (!capable(CAP_NET_ADMIN)) { 94 error = -EPERM; 95 goto done; 96 } 97 /* 98 * The user/kernel protocol for exchanging signalling 99 * info uses kernel pointers as opaque references, 100 * so the holder of the file descriptor can scribble 101 * on the kernel... so we should make sure that we 102 * have the same privledges that /proc/kcore needs 103 */ 104 if (!capable(CAP_SYS_RAWIO)) { 105 error = -EPERM; 106 goto done; 107 } 108 error = sigd_attach(vcc); 109 if (!error) 110 sock->state = SS_CONNECTED; 111 goto done; 112 case ATM_SETBACKEND: 113 case ATM_NEWBACKENDIF: 114 { 115 atm_backend_t backend; 116 error = get_user(backend, (atm_backend_t __user *) argp); 117 if (error) 118 goto done; 119 switch (backend) { 120 case ATM_BACKEND_PPP: 121 request_module("pppoatm"); 122 break; 123 case ATM_BACKEND_BR2684: 124 request_module("br2684"); 125 break; 126 } 127 } 128 break; 129 case ATMMPC_CTRL: 130 case ATMMPC_DATA: 131 request_module("mpoa"); 132 break; 133 case ATMARPD_CTRL: 134 request_module("clip"); 135 break; 136 case ATMLEC_CTRL: 137 request_module("lec"); 138 break; 139 } 140 141 error = -ENOIOCTLCMD; 142 143 mutex_lock(&ioctl_mutex); 144 list_for_each(pos, &ioctl_list) { 145 struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list); 146 if (try_module_get(ic->owner)) { 147 error = ic->ioctl(sock, cmd, arg); 148 module_put(ic->owner); 149 if (error != -ENOIOCTLCMD) 150 break; 151 } 152 } 153 mutex_unlock(&ioctl_mutex); 154 155 if (error != -ENOIOCTLCMD) 156 goto done; 157 158 error = atm_dev_ioctl(cmd, argp); 159 160 done: 161 return error; 162 } 163