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