diff options
Diffstat (limited to 'net/atm/ioctl.c')
-rw-r--r-- | net/atm/ioctl.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c new file mode 100644 index 000000000000..4dbb5af34a5e --- /dev/null +++ b/net/atm/ioctl.c | |||
@@ -0,0 +1,139 @@ | |||
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 | |||
25 | |||
26 | static DECLARE_MUTEX(ioctl_mutex); | ||
27 | static LIST_HEAD(ioctl_list); | ||
28 | |||
29 | |||
30 | void register_atm_ioctl(struct atm_ioctl *ioctl) | ||
31 | { | ||
32 | down(&ioctl_mutex); | ||
33 | list_add_tail(&ioctl->list, &ioctl_list); | ||
34 | up(&ioctl_mutex); | ||
35 | } | ||
36 | |||
37 | void deregister_atm_ioctl(struct atm_ioctl *ioctl) | ||
38 | { | ||
39 | down(&ioctl_mutex); | ||
40 | list_del(&ioctl->list); | ||
41 | up(&ioctl_mutex); | ||
42 | } | ||
43 | |||
44 | EXPORT_SYMBOL(register_atm_ioctl); | ||
45 | EXPORT_SYMBOL(deregister_atm_ioctl); | ||
46 | |||
47 | int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
48 | { | ||
49 | struct sock *sk = sock->sk; | ||
50 | struct atm_vcc *vcc; | ||
51 | int error; | ||
52 | struct list_head * pos; | ||
53 | void __user *argp = (void __user *)arg; | ||
54 | |||
55 | vcc = ATM_SD(sock); | ||
56 | switch (cmd) { | ||
57 | case SIOCOUTQ: | ||
58 | if (sock->state != SS_CONNECTED || | ||
59 | !test_bit(ATM_VF_READY, &vcc->flags)) { | ||
60 | error = -EINVAL; | ||
61 | goto done; | ||
62 | } | ||
63 | error = put_user(sk->sk_sndbuf - | ||
64 | atomic_read(&sk->sk_wmem_alloc), | ||
65 | (int __user *) argp) ? -EFAULT : 0; | ||
66 | goto done; | ||
67 | case SIOCINQ: | ||
68 | { | ||
69 | struct sk_buff *skb; | ||
70 | |||
71 | if (sock->state != SS_CONNECTED) { | ||
72 | error = -EINVAL; | ||
73 | goto done; | ||
74 | } | ||
75 | skb = skb_peek(&sk->sk_receive_queue); | ||
76 | error = put_user(skb ? skb->len : 0, | ||
77 | (int __user *)argp) ? -EFAULT : 0; | ||
78 | goto done; | ||
79 | } | ||
80 | case SIOCGSTAMP: /* borrowed from IP */ | ||
81 | error = sock_get_timestamp(sk, argp); | ||
82 | goto done; | ||
83 | case ATM_SETSC: | ||
84 | printk(KERN_WARNING "ATM_SETSC is obsolete\n"); | ||
85 | error = 0; | ||
86 | goto done; | ||
87 | case ATMSIGD_CTRL: | ||
88 | if (!capable(CAP_NET_ADMIN)) { | ||
89 | error = -EPERM; | ||
90 | goto done; | ||
91 | } | ||
92 | /* | ||
93 | * The user/kernel protocol for exchanging signalling | ||
94 | * info uses kernel pointers as opaque references, | ||
95 | * so the holder of the file descriptor can scribble | ||
96 | * on the kernel... so we should make sure that we | ||
97 | * have the same privledges that /proc/kcore needs | ||
98 | */ | ||
99 | if (!capable(CAP_SYS_RAWIO)) { | ||
100 | error = -EPERM; | ||
101 | goto done; | ||
102 | } | ||
103 | error = sigd_attach(vcc); | ||
104 | if (!error) | ||
105 | sock->state = SS_CONNECTED; | ||
106 | goto done; | ||
107 | default: | ||
108 | break; | ||
109 | } | ||
110 | |||
111 | if (cmd == ATMMPC_CTRL || cmd == ATMMPC_DATA) | ||
112 | request_module("mpoa"); | ||
113 | if (cmd == ATMARPD_CTRL) | ||
114 | request_module("clip"); | ||
115 | if (cmd == ATMLEC_CTRL) | ||
116 | request_module("lec"); | ||
117 | |||
118 | error = -ENOIOCTLCMD; | ||
119 | |||
120 | down(&ioctl_mutex); | ||
121 | list_for_each(pos, &ioctl_list) { | ||
122 | struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list); | ||
123 | if (try_module_get(ic->owner)) { | ||
124 | error = ic->ioctl(sock, cmd, arg); | ||
125 | module_put(ic->owner); | ||
126 | if (error != -ENOIOCTLCMD) | ||
127 | break; | ||
128 | } | ||
129 | } | ||
130 | up(&ioctl_mutex); | ||
131 | |||
132 | if (error != -ENOIOCTLCMD) | ||
133 | goto done; | ||
134 | |||
135 | error = atm_dev_ioctl(cmd, argp); | ||
136 | |||
137 | done: | ||
138 | return error; | ||
139 | } | ||