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 default: 109 break; 110 } 111 112 if (cmd == ATMMPC_CTRL || cmd == ATMMPC_DATA) 113 request_module("mpoa"); 114 if (cmd == ATMARPD_CTRL) 115 request_module("clip"); 116 if (cmd == ATMLEC_CTRL) 117 request_module("lec"); 118 119 error = -ENOIOCTLCMD; 120 121 down(&ioctl_mutex); 122 list_for_each(pos, &ioctl_list) { 123 struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list); 124 if (try_module_get(ic->owner)) { 125 error = ic->ioctl(sock, cmd, arg); 126 module_put(ic->owner); 127 if (error != -ENOIOCTLCMD) 128 break; 129 } 130 } 131 up(&ioctl_mutex); 132 133 if (error != -ENOIOCTLCMD) 134 goto done; 135 136 error = atm_dev_ioctl(cmd, argp); 137 138 done: 139 return error; 140 } 141