aboutsummaryrefslogtreecommitdiffstats
path: root/net/atm/resources.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/atm/resources.c')
-rw-r--r--net/atm/resources.c419
1 files changed, 198 insertions, 221 deletions
diff --git a/net/atm/resources.c b/net/atm/resources.c
index 56b7322ff461..d29e58261511 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -7,6 +7,7 @@
7 * 2002/01 - don't free the whole struct sock on sk->destruct time, 7 * 2002/01 - don't free the whole struct sock on sk->destruct time,
8 * use the default destruct function initialized by sock_init_data */ 8 * use the default destruct function initialized by sock_init_data */
9 9
10#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
10 11
11#include <linux/ctype.h> 12#include <linux/ctype.h>
12#include <linux/string.h> 13#include <linux/string.h>
@@ -18,6 +19,7 @@
18#include <linux/capability.h> 19#include <linux/capability.h>
19#include <linux/delay.h> 20#include <linux/delay.h>
20#include <linux/mutex.h> 21#include <linux/mutex.h>
22#include <linux/slab.h>
21 23
22#include <net/sock.h> /* for struct sock */ 24#include <net/sock.h> /* for struct sock */
23 25
@@ -70,7 +72,7 @@ struct atm_dev *atm_dev_lookup(int number)
70 mutex_unlock(&atm_dev_mutex); 72 mutex_unlock(&atm_dev_mutex);
71 return dev; 73 return dev;
72} 74}
73 75EXPORT_SYMBOL(atm_dev_lookup);
74 76
75struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, 77struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
76 int number, unsigned long *flags) 78 int number, unsigned long *flags)
@@ -79,13 +81,13 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
79 81
80 dev = __alloc_atm_dev(type); 82 dev = __alloc_atm_dev(type);
81 if (!dev) { 83 if (!dev) {
82 printk(KERN_ERR "atm_dev_register: no space for dev %s\n", 84 pr_err("no space for dev %s\n", type);
83 type);
84 return NULL; 85 return NULL;
85 } 86 }
86 mutex_lock(&atm_dev_mutex); 87 mutex_lock(&atm_dev_mutex);
87 if (number != -1) { 88 if (number != -1) {
88 if ((inuse = __atm_dev_lookup(number))) { 89 inuse = __atm_dev_lookup(number);
90 if (inuse) {
89 atm_dev_put(inuse); 91 atm_dev_put(inuse);
90 mutex_unlock(&atm_dev_mutex); 92 mutex_unlock(&atm_dev_mutex);
91 kfree(dev); 93 kfree(dev);
@@ -109,16 +111,12 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
109 atomic_set(&dev->refcnt, 1); 111 atomic_set(&dev->refcnt, 1);
110 112
111 if (atm_proc_dev_register(dev) < 0) { 113 if (atm_proc_dev_register(dev) < 0) {
112 printk(KERN_ERR "atm_dev_register: " 114 pr_err("atm_proc_dev_register failed for dev %s\n", type);
113 "atm_proc_dev_register failed for dev %s\n",
114 type);
115 goto out_fail; 115 goto out_fail;
116 } 116 }
117 117
118 if (atm_register_sysfs(dev) < 0) { 118 if (atm_register_sysfs(dev) < 0) {
119 printk(KERN_ERR "atm_dev_register: " 119 pr_err("atm_register_sysfs failed for dev %s\n", type);
120 "atm_register_sysfs failed for dev %s\n",
121 type);
122 atm_proc_dev_deregister(dev); 120 atm_proc_dev_deregister(dev);
123 goto out_fail; 121 goto out_fail;
124 } 122 }
@@ -134,7 +132,7 @@ out_fail:
134 dev = NULL; 132 dev = NULL;
135 goto out; 133 goto out;
136} 134}
137 135EXPORT_SYMBOL(atm_dev_register);
138 136
139void atm_dev_deregister(struct atm_dev *dev) 137void atm_dev_deregister(struct atm_dev *dev)
140{ 138{
@@ -156,7 +154,7 @@ void atm_dev_deregister(struct atm_dev *dev)
156 154
157 atm_dev_put(dev); 155 atm_dev_put(dev);
158} 156}
159 157EXPORT_SYMBOL(atm_dev_deregister);
160 158
161static void copy_aal_stats(struct k_atm_aal_stats *from, 159static void copy_aal_stats(struct k_atm_aal_stats *from,
162 struct atm_aal_stats *to) 160 struct atm_aal_stats *to)
@@ -166,7 +164,6 @@ static void copy_aal_stats(struct k_atm_aal_stats *from,
166#undef __HANDLE_ITEM 164#undef __HANDLE_ITEM
167} 165}
168 166
169
170static void subtract_aal_stats(struct k_atm_aal_stats *from, 167static void subtract_aal_stats(struct k_atm_aal_stats *from,
171 struct atm_aal_stats *to) 168 struct atm_aal_stats *to)
172{ 169{
@@ -175,8 +172,8 @@ static void subtract_aal_stats(struct k_atm_aal_stats *from,
175#undef __HANDLE_ITEM 172#undef __HANDLE_ITEM
176} 173}
177 174
178 175static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg,
179static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, int zero) 176 int zero)
180{ 177{
181 struct atm_dev_stats tmp; 178 struct atm_dev_stats tmp;
182 int error = 0; 179 int error = 0;
@@ -194,7 +191,6 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, in
194 return error ? -EFAULT : 0; 191 return error ? -EFAULT : 0;
195} 192}
196 193
197
198int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat) 194int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
199{ 195{
200 void __user *buf; 196 void __user *buf;
@@ -210,50 +206,49 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
210#endif 206#endif
211 207
212 switch (cmd) { 208 switch (cmd) {
213 case ATM_GETNAMES: 209 case ATM_GETNAMES:
214 210 if (compat) {
215 if (compat) {
216#ifdef CONFIG_COMPAT 211#ifdef CONFIG_COMPAT
217 struct compat_atm_iobuf __user *ciobuf = arg; 212 struct compat_atm_iobuf __user *ciobuf = arg;
218 compat_uptr_t cbuf; 213 compat_uptr_t cbuf;
219 iobuf_len = &ciobuf->length; 214 iobuf_len = &ciobuf->length;
220 if (get_user(cbuf, &ciobuf->buffer)) 215 if (get_user(cbuf, &ciobuf->buffer))
221 return -EFAULT; 216 return -EFAULT;
222 buf = compat_ptr(cbuf); 217 buf = compat_ptr(cbuf);
223#endif 218#endif
224 } else { 219 } else {
225 struct atm_iobuf __user *iobuf = arg; 220 struct atm_iobuf __user *iobuf = arg;
226 iobuf_len = &iobuf->length; 221 iobuf_len = &iobuf->length;
227 if (get_user(buf, &iobuf->buffer)) 222 if (get_user(buf, &iobuf->buffer))
228 return -EFAULT;
229 }
230 if (get_user(len, iobuf_len))
231 return -EFAULT; 223 return -EFAULT;
232 mutex_lock(&atm_dev_mutex); 224 }
233 list_for_each(p, &atm_devs) 225 if (get_user(len, iobuf_len))
234 size += sizeof(int); 226 return -EFAULT;
235 if (size > len) { 227 mutex_lock(&atm_dev_mutex);
236 mutex_unlock(&atm_dev_mutex); 228 list_for_each(p, &atm_devs)
237 return -E2BIG; 229 size += sizeof(int);
238 } 230 if (size > len) {
239 tmp_buf = kmalloc(size, GFP_ATOMIC); 231 mutex_unlock(&atm_dev_mutex);
240 if (!tmp_buf) { 232 return -E2BIG;
241 mutex_unlock(&atm_dev_mutex); 233 }
242 return -ENOMEM; 234 tmp_buf = kmalloc(size, GFP_ATOMIC);
243 } 235 if (!tmp_buf) {
244 tmp_p = tmp_buf;
245 list_for_each(p, &atm_devs) {
246 dev = list_entry(p, struct atm_dev, dev_list);
247 *tmp_p++ = dev->number;
248 }
249 mutex_unlock(&atm_dev_mutex); 236 mutex_unlock(&atm_dev_mutex);
250 error = ((copy_to_user(buf, tmp_buf, size)) || 237 return -ENOMEM;
251 put_user(size, iobuf_len)) 238 }
252 ? -EFAULT : 0; 239 tmp_p = tmp_buf;
253 kfree(tmp_buf); 240 list_for_each(p, &atm_devs) {
254 return error; 241 dev = list_entry(p, struct atm_dev, dev_list);
255 default: 242 *tmp_p++ = dev->number;
256 break; 243 }
244 mutex_unlock(&atm_dev_mutex);
245 error = ((copy_to_user(buf, tmp_buf, size)) ||
246 put_user(size, iobuf_len))
247 ? -EFAULT : 0;
248 kfree(tmp_buf);
249 return error;
250 default:
251 break;
257 } 252 }
258 253
259 if (compat) { 254 if (compat) {
@@ -282,166 +277,167 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
282 if (get_user(number, &sioc->number)) 277 if (get_user(number, &sioc->number))
283 return -EFAULT; 278 return -EFAULT;
284 } 279 }
285 if (!(dev = try_then_request_module(atm_dev_lookup(number), 280
286 "atm-device-%d", number))) 281 dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d",
282 number);
283 if (!dev)
287 return -ENODEV; 284 return -ENODEV;
288 285
289 switch (cmd) { 286 switch (cmd) {
290 case ATM_GETTYPE: 287 case ATM_GETTYPE:
291 size = strlen(dev->type) + 1; 288 size = strlen(dev->type) + 1;
292 if (copy_to_user(buf, dev->type, size)) { 289 if (copy_to_user(buf, dev->type, size)) {
293 error = -EFAULT; 290 error = -EFAULT;
294 goto done; 291 goto done;
295 } 292 }
296 break; 293 break;
297 case ATM_GETESI: 294 case ATM_GETESI:
298 size = ESI_LEN; 295 size = ESI_LEN;
299 if (copy_to_user(buf, dev->esi, size)) { 296 if (copy_to_user(buf, dev->esi, size)) {
300 error = -EFAULT; 297 error = -EFAULT;
301 goto done; 298 goto done;
302 } 299 }
303 break; 300 break;
304 case ATM_SETESI: 301 case ATM_SETESI:
305 { 302 {
306 int i; 303 int i;
307 304
308 for (i = 0; i < ESI_LEN; i++) 305 for (i = 0; i < ESI_LEN; i++)
309 if (dev->esi[i]) { 306 if (dev->esi[i]) {
310 error = -EEXIST; 307 error = -EEXIST;
311 goto done;
312 }
313 }
314 /* fall through */
315 case ATM_SETESIF:
316 {
317 unsigned char esi[ESI_LEN];
318
319 if (!capable(CAP_NET_ADMIN)) {
320 error = -EPERM;
321 goto done;
322 }
323 if (copy_from_user(esi, buf, ESI_LEN)) {
324 error = -EFAULT;
325 goto done;
326 }
327 memcpy(dev->esi, esi, ESI_LEN);
328 error = ESI_LEN;
329 goto done;
330 }
331 case ATM_GETSTATZ:
332 if (!capable(CAP_NET_ADMIN)) {
333 error = -EPERM;
334 goto done;
335 }
336 /* fall through */
337 case ATM_GETSTAT:
338 size = sizeof(struct atm_dev_stats);
339 error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ);
340 if (error)
341 goto done;
342 break;
343 case ATM_GETCIRANGE:
344 size = sizeof(struct atm_cirange);
345 if (copy_to_user(buf, &dev->ci_range, size)) {
346 error = -EFAULT;
347 goto done;
348 }
349 break;
350 case ATM_GETLINKRATE:
351 size = sizeof(int);
352 if (copy_to_user(buf, &dev->link_rate, size)) {
353 error = -EFAULT;
354 goto done;
355 }
356 break;
357 case ATM_RSTADDR:
358 if (!capable(CAP_NET_ADMIN)) {
359 error = -EPERM;
360 goto done;
361 }
362 atm_reset_addr(dev, ATM_ADDR_LOCAL);
363 break;
364 case ATM_ADDADDR:
365 case ATM_DELADDR:
366 case ATM_ADDLECSADDR:
367 case ATM_DELLECSADDR:
368 if (!capable(CAP_NET_ADMIN)) {
369 error = -EPERM;
370 goto done;
371 }
372 {
373 struct sockaddr_atmsvc addr;
374
375 if (copy_from_user(&addr, buf, sizeof(addr))) {
376 error = -EFAULT;
377 goto done;
378 }
379 if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR)
380 error = atm_add_addr(dev, &addr,
381 (cmd == ATM_ADDADDR ?
382 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
383 else
384 error = atm_del_addr(dev, &addr,
385 (cmd == ATM_DELADDR ?
386 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
387 goto done; 308 goto done;
388 } 309 }
389 case ATM_GETADDR: 310 }
390 case ATM_GETLECSADDR: 311 /* fall through */
391 error = atm_get_addr(dev, buf, len, 312 case ATM_SETESIF:
392 (cmd == ATM_GETADDR ? 313 {
314 unsigned char esi[ESI_LEN];
315
316 if (!capable(CAP_NET_ADMIN)) {
317 error = -EPERM;
318 goto done;
319 }
320 if (copy_from_user(esi, buf, ESI_LEN)) {
321 error = -EFAULT;
322 goto done;
323 }
324 memcpy(dev->esi, esi, ESI_LEN);
325 error = ESI_LEN;
326 goto done;
327 }
328 case ATM_GETSTATZ:
329 if (!capable(CAP_NET_ADMIN)) {
330 error = -EPERM;
331 goto done;
332 }
333 /* fall through */
334 case ATM_GETSTAT:
335 size = sizeof(struct atm_dev_stats);
336 error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ);
337 if (error)
338 goto done;
339 break;
340 case ATM_GETCIRANGE:
341 size = sizeof(struct atm_cirange);
342 if (copy_to_user(buf, &dev->ci_range, size)) {
343 error = -EFAULT;
344 goto done;
345 }
346 break;
347 case ATM_GETLINKRATE:
348 size = sizeof(int);
349 if (copy_to_user(buf, &dev->link_rate, size)) {
350 error = -EFAULT;
351 goto done;
352 }
353 break;
354 case ATM_RSTADDR:
355 if (!capable(CAP_NET_ADMIN)) {
356 error = -EPERM;
357 goto done;
358 }
359 atm_reset_addr(dev, ATM_ADDR_LOCAL);
360 break;
361 case ATM_ADDADDR:
362 case ATM_DELADDR:
363 case ATM_ADDLECSADDR:
364 case ATM_DELLECSADDR:
365 {
366 struct sockaddr_atmsvc addr;
367
368 if (!capable(CAP_NET_ADMIN)) {
369 error = -EPERM;
370 goto done;
371 }
372
373 if (copy_from_user(&addr, buf, sizeof(addr))) {
374 error = -EFAULT;
375 goto done;
376 }
377 if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR)
378 error = atm_add_addr(dev, &addr,
379 (cmd == ATM_ADDADDR ?
393 ATM_ADDR_LOCAL : ATM_ADDR_LECS)); 380 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
394 if (error < 0) 381 else
395 goto done; 382 error = atm_del_addr(dev, &addr,
396 size = error; 383 (cmd == ATM_DELADDR ?
397 /* may return 0, but later on size == 0 means "don't 384 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
398 write the length" */ 385 goto done;
399 error = put_user(size, sioc_len) 386 }
400 ? -EFAULT : 0; 387 case ATM_GETADDR:
388 case ATM_GETLECSADDR:
389 error = atm_get_addr(dev, buf, len,
390 (cmd == ATM_GETADDR ?
391 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
392 if (error < 0)
393 goto done;
394 size = error;
395 /* may return 0, but later on size == 0 means "don't
396 write the length" */
397 error = put_user(size, sioc_len) ? -EFAULT : 0;
398 goto done;
399 case ATM_SETLOOP:
400 if (__ATM_LM_XTRMT((int) (unsigned long) buf) &&
401 __ATM_LM_XTLOC((int) (unsigned long) buf) >
402 __ATM_LM_XTRMT((int) (unsigned long) buf)) {
403 error = -EINVAL;
404 goto done;
405 }
406 /* fall through */
407 case ATM_SETCIRANGE:
408 case SONET_GETSTATZ:
409 case SONET_SETDIAG:
410 case SONET_CLRDIAG:
411 case SONET_SETFRAMING:
412 if (!capable(CAP_NET_ADMIN)) {
413 error = -EPERM;
401 goto done; 414 goto done;
402 case ATM_SETLOOP: 415 }
403 if (__ATM_LM_XTRMT((int) (unsigned long) buf) && 416 /* fall through */
404 __ATM_LM_XTLOC((int) (unsigned long) buf) > 417 default:
405 __ATM_LM_XTRMT((int) (unsigned long) buf)) { 418 if (compat) {
419#ifdef CONFIG_COMPAT
420 if (!dev->ops->compat_ioctl) {
406 error = -EINVAL; 421 error = -EINVAL;
407 goto done; 422 goto done;
408 } 423 }
409 /* fall through */ 424 size = dev->ops->compat_ioctl(dev, cmd, buf);
410 case ATM_SETCIRANGE:
411 case SONET_GETSTATZ:
412 case SONET_SETDIAG:
413 case SONET_CLRDIAG:
414 case SONET_SETFRAMING:
415 if (!capable(CAP_NET_ADMIN)) {
416 error = -EPERM;
417 goto done;
418 }
419 /* fall through */
420 default:
421 if (compat) {
422#ifdef CONFIG_COMPAT
423 if (!dev->ops->compat_ioctl) {
424 error = -EINVAL;
425 goto done;
426 }
427 size = dev->ops->compat_ioctl(dev, cmd, buf);
428#endif 425#endif
429 } else { 426 } else {
430 if (!dev->ops->ioctl) { 427 if (!dev->ops->ioctl) {
431 error = -EINVAL; 428 error = -EINVAL;
432 goto done;
433 }
434 size = dev->ops->ioctl(dev, cmd, buf);
435 }
436 if (size < 0) {
437 error = (size == -ENOIOCTLCMD ? -EINVAL : size);
438 goto done; 429 goto done;
439 } 430 }
431 size = dev->ops->ioctl(dev, cmd, buf);
432 }
433 if (size < 0) {
434 error = (size == -ENOIOCTLCMD ? -EINVAL : size);
435 goto done;
436 }
440 } 437 }
441 438
442 if (size) 439 if (size)
443 error = put_user(size, sioc_len) 440 error = put_user(size, sioc_len) ? -EFAULT : 0;
444 ? -EFAULT : 0;
445 else 441 else
446 error = 0; 442 error = 0;
447done: 443done:
@@ -449,21 +445,10 @@ done:
449 return error; 445 return error;
450} 446}
451 447
452static __inline__ void *dev_get_idx(loff_t left)
453{
454 struct list_head *p;
455
456 list_for_each(p, &atm_devs) {
457 if (!--left)
458 break;
459 }
460 return (p != &atm_devs) ? p : NULL;
461}
462
463void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) 448void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos)
464{ 449{
465 mutex_lock(&atm_dev_mutex); 450 mutex_lock(&atm_dev_mutex);
466 return *pos ? dev_get_idx(*pos) : SEQ_START_TOKEN; 451 return seq_list_start_head(&atm_devs, *pos);
467} 452}
468 453
469void atm_dev_seq_stop(struct seq_file *seq, void *v) 454void atm_dev_seq_stop(struct seq_file *seq, void *v)
@@ -473,13 +458,5 @@ void atm_dev_seq_stop(struct seq_file *seq, void *v)
473 458
474void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) 459void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
475{ 460{
476 ++*pos; 461 return seq_list_next(v, &atm_devs, pos);
477 v = (v == SEQ_START_TOKEN)
478 ? atm_devs.next : ((struct list_head *)v)->next;
479 return (v == &atm_devs) ? NULL : v;
480} 462}
481
482
483EXPORT_SYMBOL(atm_dev_register);
484EXPORT_SYMBOL(atm_dev_deregister);
485EXPORT_SYMBOL(atm_dev_lookup);