Blame view

net/atm/ioctl.c 4.63 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
  /* ATM ioctl handling */
  
  /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
  /* 2003 John Levon  <levon@movementarian.org> */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
  #include <linux/module.h>
  #include <linux/kmod.h>
  #include <linux/net.h>		/* struct socket, struct proto_ops */
  #include <linux/atm.h>		/* ATM stuff */
  #include <linux/atmdev.h>
  #include <linux/atmclip.h>	/* CLIP_*ENCAP */
  #include <linux/atmarp.h>	/* manifest constants */
4fc268d24   Randy Dunlap   [PATCH] capable/c...
12
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
16
17
  #include <linux/sonet.h>	/* for ioctls */
  #include <linux/atmsvc.h>
  #include <linux/atmmpc.h>
  #include <net/atmclip.h>
  #include <linux/atmlec.h>
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
18
  #include <linux/mutex.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  #include <asm/ioctls.h>
8865c418c   David Woodhouse   atm: 32-bit ioctl...
20
  #include <net/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
  
  #include "resources.h"
  #include "signaling.h"		/* for WAITING and sigd_attach */
295098e9f   Adrian Bunk   [ATM]: net/atm/io...
24
  #include "common.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25

4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
26
  static DEFINE_MUTEX(ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
  static LIST_HEAD(ioctl_list);
  
  
  void register_atm_ioctl(struct atm_ioctl *ioctl)
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
32
  	mutex_lock(&ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  	list_add_tail(&ioctl->list, &ioctl_list);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
34
  	mutex_unlock(&ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
  }
  
  void deregister_atm_ioctl(struct atm_ioctl *ioctl)
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
39
  	mutex_lock(&ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  	list_del(&ioctl->list);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
41
  	mutex_unlock(&ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
  }
  
  EXPORT_SYMBOL(register_atm_ioctl);
  EXPORT_SYMBOL(deregister_atm_ioctl);
8865c418c   David Woodhouse   atm: 32-bit ioctl...
46
  static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg, int compat)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  {
  	struct sock *sk = sock->sk;
  	struct atm_vcc *vcc;
  	int error;
  	struct list_head * pos;
  	void __user *argp = (void __user *)arg;
  
  	vcc = ATM_SD(sock);
  	switch (cmd) {
  		case SIOCOUTQ:
  			if (sock->state != SS_CONNECTED ||
  			    !test_bit(ATM_VF_READY, &vcc->flags)) {
  				error =  -EINVAL;
  				goto done;
  			}
  			error = put_user(sk->sk_sndbuf -
  					 atomic_read(&sk->sk_wmem_alloc),
  					 (int __user *) argp) ? -EFAULT : 0;
  			goto done;
  		case SIOCINQ:
  			{
  				struct sk_buff *skb;
  
  				if (sock->state != SS_CONNECTED) {
  					error = -EINVAL;
  					goto done;
  				}
  				skb = skb_peek(&sk->sk_receive_queue);
  				error = put_user(skb ? skb->len : 0,
f7d57453d   YOSHIFUJI Hideaki   [NET] ATM: Fix wh...
76
  						 (int __user *)argp) ? -EFAULT : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
  				goto done;
  			}
  		case SIOCGSTAMP: /* borrowed from IP */
8865c418c   David Woodhouse   atm: 32-bit ioctl...
80
81
82
83
84
85
  #ifdef CONFIG_COMPAT
  			if (compat)
  				error = compat_sock_get_timestamp(sk, argp);
  			else
  #endif
  				error = sock_get_timestamp(sk, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  			goto done;
ae40eb1ef   Eric Dumazet   [NET]: Introduce ...
87
  		case SIOCGSTAMPNS: /* borrowed from IP */
8865c418c   David Woodhouse   atm: 32-bit ioctl...
88
89
90
91
92
93
  #ifdef CONFIG_COMPAT
  			if (compat)
  				error = compat_sock_get_timestampns(sk, argp);
  			else
  #endif
  				error = sock_get_timestampns(sk, argp);
ae40eb1ef   Eric Dumazet   [NET]: Introduce ...
94
  			goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  		case ATM_SETSC:
8865c418c   David Woodhouse   atm: 32-bit ioctl...
96
97
98
99
  			if (net_ratelimit())
  				printk(KERN_WARNING "ATM_SETSC is obsolete; used by %s:%d
  ",
  				       current->comm, task_pid_nr(current));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
104
105
106
107
108
109
110
111
  			error = 0;
  			goto done;
  		case ATMSIGD_CTRL:
  			if (!capable(CAP_NET_ADMIN)) {
  				error = -EPERM;
  				goto done;
  			}
  			/*
  			 * The user/kernel protocol for exchanging signalling
  			 * info uses kernel pointers as opaque references,
  			 * so the holder of the file descriptor can scribble
  			 * on the kernel... so we should make sure that we
8865c418c   David Woodhouse   atm: 32-bit ioctl...
112
  			 * have the same privileges that /proc/kcore needs
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
116
117
  			 */
  			if (!capable(CAP_SYS_RAWIO)) {
  				error = -EPERM;
  				goto done;
  			}
8865c418c   David Woodhouse   atm: 32-bit ioctl...
118
119
120
121
122
123
124
125
126
127
128
129
  #ifdef CONFIG_COMPAT
  			/* WTF? I don't even want to _think_ about making this
  			   work for 32-bit userspace. TBH I don't really want
  			   to think about it at all. dwmw2. */
  			if (compat) {
  				if (net_ratelimit())
  					printk(KERN_WARNING "32-bit task cannot be atmsigd
  ");
  				error = -EINVAL;
  				goto done;
  			}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
133
  			error = sigd_attach(vcc);
  			if (!error)
  				sock->state = SS_CONNECTED;
  			goto done;
e2c4b7215   Roman Kagan   [ATM]: net/atm/io...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  		case ATM_SETBACKEND:
  		case ATM_NEWBACKENDIF:
  			{
  				atm_backend_t backend;
  				error = get_user(backend, (atm_backend_t __user *) argp);
  				if (error)
  					goto done;
  				switch (backend) {
  					case ATM_BACKEND_PPP:
  						request_module("pppoatm");
  						break;
  					case ATM_BACKEND_BR2684:
  						request_module("br2684");
  						break;
  				}
  			}
  			break;
  		case ATMMPC_CTRL:
  		case ATMMPC_DATA:
  			request_module("mpoa");
  			break;
  		case ATMARPD_CTRL:
  			request_module("clip");
  			break;
  		case ATMLEC_CTRL:
  			request_module("lec");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
  			break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  	error = -ENOIOCTLCMD;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
163
  	mutex_lock(&ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
168
169
170
171
172
  	list_for_each(pos, &ioctl_list) {
  		struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list);
  		if (try_module_get(ic->owner)) {
  			error = ic->ioctl(sock, cmd, arg);
  			module_put(ic->owner);
  			if (error != -ENOIOCTLCMD)
  				break;
  		}
  	}
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
173
  	mutex_unlock(&ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
  
  	if (error != -ENOIOCTLCMD)
  		goto done;
8865c418c   David Woodhouse   atm: 32-bit ioctl...
177
  	error = atm_dev_ioctl(cmd, argp, compat);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
  
  done:
  	return error;
  }
8865c418c   David Woodhouse   atm: 32-bit ioctl...
182
183
184
185
186
187
188
189
190
191
192
193
194
  
  
  int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
  {
  	return do_vcc_ioctl(sock, cmd, arg, 0);
  }
  
  #ifdef CONFIG_COMPAT
  int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
  {
  	return do_vcc_ioctl(sock, cmd, arg, 1);
  }
  #endif