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 ATM_SETSC: 86 printk(KERN_WARNING "ATM_SETSC is obsolete\n"); 87 error = 0; 88 goto done; 89 case ATMSIGD_CTRL: 90 if (!capable(CAP_NET_ADMIN)) { 91 error = -EPERM; 92 goto done; 93 } 94 /* 95 * The user/kernel protocol for exchanging signalling 96 * info uses kernel pointers as opaque references, 97 * so the holder of the file descriptor can scribble 98 * on the kernel... so we should make sure that we 99 * have the same privledges that /proc/kcore needs 100 */ 101 if (!capable(CAP_SYS_RAWIO)) { 102 error = -EPERM; 103 goto done; 104 } 105 error = sigd_attach(vcc); 106 if (!error) 107 sock->state = SS_CONNECTED; 108 goto done; 109 case ATM_SETBACKEND: 110 case ATM_NEWBACKENDIF: 111 { 112 atm_backend_t backend; 113 error = get_user(backend, (atm_backend_t __user *) argp); 114 if (error) 115 goto done; 116 switch (backend) { 117 case ATM_BACKEND_PPP: 118 request_module("pppoatm"); 119 break; 120 case ATM_BACKEND_BR2684: 121 request_module("br2684"); 122 break; 123 } 124 } 125 break; 126 case ATMMPC_CTRL: 127 case ATMMPC_DATA: 128 request_module("mpoa"); 129 break; 130 case ATMARPD_CTRL: 131 request_module("clip"); 132 break; 133 case ATMLEC_CTRL: 134 request_module("lec"); 135 break; 136 } 137 138 error = -ENOIOCTLCMD; 139 140 mutex_lock(&ioctl_mutex); 141 list_for_each(pos, &ioctl_list) { 142 struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list); 143 if (try_module_get(ic->owner)) { 144 error = ic->ioctl(sock, cmd, arg); 145 module_put(ic->owner); 146 if (error != -ENOIOCTLCMD) 147 break; 148 } 149 } 150 mutex_unlock(&ioctl_mutex); 151 152 if (error != -ENOIOCTLCMD) 153 goto done; 154 155 error = atm_dev_ioctl(cmd, argp); 156 157 done: 158 return error; 159 } 160