aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/atm/resources.c390
1 files changed, 192 insertions, 198 deletions
diff --git a/net/atm/resources.c b/net/atm/resources.c
index 0d4c0ee090db..447ed89205d8 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -71,7 +71,7 @@ struct atm_dev *atm_dev_lookup(int number)
71 mutex_unlock(&atm_dev_mutex); 71 mutex_unlock(&atm_dev_mutex);
72 return dev; 72 return dev;
73} 73}
74 74EXPORT_SYMBOL(atm_dev_lookup);
75 75
76struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, 76struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
77 int number, unsigned long *flags) 77 int number, unsigned long *flags)
@@ -85,7 +85,8 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
85 } 85 }
86 mutex_lock(&atm_dev_mutex); 86 mutex_lock(&atm_dev_mutex);
87 if (number != -1) { 87 if (number != -1) {
88 if ((inuse = __atm_dev_lookup(number))) { 88 inuse = __atm_dev_lookup(number);
89 if (inuse) {
89 atm_dev_put(inuse); 90 atm_dev_put(inuse);
90 mutex_unlock(&atm_dev_mutex); 91 mutex_unlock(&atm_dev_mutex);
91 kfree(dev); 92 kfree(dev);
@@ -130,7 +131,7 @@ out_fail:
130 dev = NULL; 131 dev = NULL;
131 goto out; 132 goto out;
132} 133}
133 134EXPORT_SYMBOL(atm_dev_register);
134 135
135void atm_dev_deregister(struct atm_dev *dev) 136void atm_dev_deregister(struct atm_dev *dev)
136{ 137{
@@ -152,7 +153,7 @@ void atm_dev_deregister(struct atm_dev *dev)
152 153
153 atm_dev_put(dev); 154 atm_dev_put(dev);
154} 155}
155 156EXPORT_SYMBOL(atm_dev_deregister);
156 157
157static void copy_aal_stats(struct k_atm_aal_stats *from, 158static void copy_aal_stats(struct k_atm_aal_stats *from,
158 struct atm_aal_stats *to) 159 struct atm_aal_stats *to)
@@ -162,7 +163,6 @@ static void copy_aal_stats(struct k_atm_aal_stats *from,
162#undef __HANDLE_ITEM 163#undef __HANDLE_ITEM
163} 164}
164 165
165
166static void subtract_aal_stats(struct k_atm_aal_stats *from, 166static void subtract_aal_stats(struct k_atm_aal_stats *from,
167 struct atm_aal_stats *to) 167 struct atm_aal_stats *to)
168{ 168{
@@ -171,8 +171,8 @@ static void subtract_aal_stats(struct k_atm_aal_stats *from,
171#undef __HANDLE_ITEM 171#undef __HANDLE_ITEM
172} 172}
173 173
174 174static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg,
175static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, int zero) 175 int zero)
176{ 176{
177 struct atm_dev_stats tmp; 177 struct atm_dev_stats tmp;
178 int error = 0; 178 int error = 0;
@@ -190,7 +190,6 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, in
190 return error ? -EFAULT : 0; 190 return error ? -EFAULT : 0;
191} 191}
192 192
193
194int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat) 193int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
195{ 194{
196 void __user *buf; 195 void __user *buf;
@@ -206,50 +205,49 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
206#endif 205#endif
207 206
208 switch (cmd) { 207 switch (cmd) {
209 case ATM_GETNAMES: 208 case ATM_GETNAMES:
210 209 if (compat) {
211 if (compat) {
212#ifdef CONFIG_COMPAT 210#ifdef CONFIG_COMPAT
213 struct compat_atm_iobuf __user *ciobuf = arg; 211 struct compat_atm_iobuf __user *ciobuf = arg;
214 compat_uptr_t cbuf; 212 compat_uptr_t cbuf;
215 iobuf_len = &ciobuf->length; 213 iobuf_len = &ciobuf->length;
216 if (get_user(cbuf, &ciobuf->buffer)) 214 if (get_user(cbuf, &ciobuf->buffer))
217 return -EFAULT; 215 return -EFAULT;
218 buf = compat_ptr(cbuf); 216 buf = compat_ptr(cbuf);
219#endif 217#endif
220 } else { 218 } else {
221 struct atm_iobuf __user *iobuf = arg; 219 struct atm_iobuf __user *iobuf = arg;
222 iobuf_len = &iobuf->length; 220 iobuf_len = &iobuf->length;
223 if (get_user(buf, &iobuf->buffer)) 221 if (get_user(buf, &iobuf->buffer))
224 return -EFAULT;
225 }
226 if (get_user(len, iobuf_len))
227 return -EFAULT; 222 return -EFAULT;
228 mutex_lock(&atm_dev_mutex); 223 }
229 list_for_each(p, &atm_devs) 224 if (get_user(len, iobuf_len))
230 size += sizeof(int); 225 return -EFAULT;
231 if (size > len) { 226 mutex_lock(&atm_dev_mutex);
232 mutex_unlock(&atm_dev_mutex); 227 list_for_each(p, &atm_devs)
233 return -E2BIG; 228 size += sizeof(int);
234 } 229 if (size > len) {
235 tmp_buf = kmalloc(size, GFP_ATOMIC);
236 if (!tmp_buf) {
237 mutex_unlock(&atm_dev_mutex);
238 return -ENOMEM;
239 }
240 tmp_p = tmp_buf;
241 list_for_each(p, &atm_devs) {
242 dev = list_entry(p, struct atm_dev, dev_list);
243 *tmp_p++ = dev->number;
244 }
245 mutex_unlock(&atm_dev_mutex); 230 mutex_unlock(&atm_dev_mutex);
246 error = ((copy_to_user(buf, tmp_buf, size)) || 231 return -E2BIG;
247 put_user(size, iobuf_len)) 232 }
248 ? -EFAULT : 0; 233 tmp_buf = kmalloc(size, GFP_ATOMIC);
249 kfree(tmp_buf); 234 if (!tmp_buf) {
250 return error; 235 mutex_unlock(&atm_dev_mutex);
251 default: 236 return -ENOMEM;
252 break; 237 }
238 tmp_p = tmp_buf;
239 list_for_each(p, &atm_devs) {
240 dev = list_entry(p, struct atm_dev, dev_list);
241 *tmp_p++ = dev->number;
242 }
243 mutex_unlock(&atm_dev_mutex);
244 error = ((copy_to_user(buf, tmp_buf, size)) ||
245 put_user(size, iobuf_len))
246 ? -EFAULT : 0;
247 kfree(tmp_buf);
248 return error;
249 default:
250 break;
253 } 251 }
254 252
255 if (compat) { 253 if (compat) {
@@ -278,166 +276,167 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
278 if (get_user(number, &sioc->number)) 276 if (get_user(number, &sioc->number))
279 return -EFAULT; 277 return -EFAULT;
280 } 278 }
281 if (!(dev = try_then_request_module(atm_dev_lookup(number), 279
282 "atm-device-%d", number))) 280 dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d",
281 number);
282 if (!dev)
283 return -ENODEV; 283 return -ENODEV;
284 284
285 switch (cmd) { 285 switch (cmd) {
286 case ATM_GETTYPE: 286 case ATM_GETTYPE:
287 size = strlen(dev->type) + 1; 287 size = strlen(dev->type) + 1;
288 if (copy_to_user(buf, dev->type, size)) { 288 if (copy_to_user(buf, dev->type, size)) {
289 error = -EFAULT; 289 error = -EFAULT;
290 goto done; 290 goto done;
291 } 291 }
292 break; 292 break;
293 case ATM_GETESI: 293 case ATM_GETESI:
294 size = ESI_LEN; 294 size = ESI_LEN;
295 if (copy_to_user(buf, dev->esi, size)) { 295 if (copy_to_user(buf, dev->esi, size)) {
296 error = -EFAULT; 296 error = -EFAULT;
297 goto done; 297 goto done;
298 } 298 }
299 break; 299 break;
300 case ATM_SETESI: 300 case ATM_SETESI:
301 { 301 {
302 int i; 302 int i;
303 303
304 for (i = 0; i < ESI_LEN; i++) 304 for (i = 0; i < ESI_LEN; i++)
305 if (dev->esi[i]) { 305 if (dev->esi[i]) {
306 error = -EEXIST; 306 error = -EEXIST;
307 goto done;
308 }
309 }
310 /* fall through */
311 case ATM_SETESIF:
312 {
313 unsigned char esi[ESI_LEN];
314
315 if (!capable(CAP_NET_ADMIN)) {
316 error = -EPERM;
317 goto done;
318 }
319 if (copy_from_user(esi, buf, ESI_LEN)) {
320 error = -EFAULT;
321 goto done;
322 }
323 memcpy(dev->esi, esi, ESI_LEN);
324 error = ESI_LEN;
325 goto done;
326 }
327 case ATM_GETSTATZ:
328 if (!capable(CAP_NET_ADMIN)) {
329 error = -EPERM;
330 goto done;
331 }
332 /* fall through */
333 case ATM_GETSTAT:
334 size = sizeof(struct atm_dev_stats);
335 error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ);
336 if (error)
337 goto done;
338 break;
339 case ATM_GETCIRANGE:
340 size = sizeof(struct atm_cirange);
341 if (copy_to_user(buf, &dev->ci_range, size)) {
342 error = -EFAULT;
343 goto done;
344 }
345 break;
346 case ATM_GETLINKRATE:
347 size = sizeof(int);
348 if (copy_to_user(buf, &dev->link_rate, size)) {
349 error = -EFAULT;
350 goto done;
351 }
352 break;
353 case ATM_RSTADDR:
354 if (!capable(CAP_NET_ADMIN)) {
355 error = -EPERM;
356 goto done;
357 }
358 atm_reset_addr(dev, ATM_ADDR_LOCAL);
359 break;
360 case ATM_ADDADDR:
361 case ATM_DELADDR:
362 case ATM_ADDLECSADDR:
363 case ATM_DELLECSADDR:
364 if (!capable(CAP_NET_ADMIN)) {
365 error = -EPERM;
366 goto done;
367 }
368 {
369 struct sockaddr_atmsvc addr;
370
371 if (copy_from_user(&addr, buf, sizeof(addr))) {
372 error = -EFAULT;
373 goto done;
374 }
375 if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR)
376 error = atm_add_addr(dev, &addr,
377 (cmd == ATM_ADDADDR ?
378 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
379 else
380 error = atm_del_addr(dev, &addr,
381 (cmd == ATM_DELADDR ?
382 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
383 goto done; 307 goto done;
384 } 308 }
385 case ATM_GETADDR: 309 }
386 case ATM_GETLECSADDR: 310 /* fall through */
387 error = atm_get_addr(dev, buf, len, 311 case ATM_SETESIF:
388 (cmd == ATM_GETADDR ? 312 {
313 unsigned char esi[ESI_LEN];
314
315 if (!capable(CAP_NET_ADMIN)) {
316 error = -EPERM;
317 goto done;
318 }
319 if (copy_from_user(esi, buf, ESI_LEN)) {
320 error = -EFAULT;
321 goto done;
322 }
323 memcpy(dev->esi, esi, ESI_LEN);
324 error = ESI_LEN;
325 goto done;
326 }
327 case ATM_GETSTATZ:
328 if (!capable(CAP_NET_ADMIN)) {
329 error = -EPERM;
330 goto done;
331 }
332 /* fall through */
333 case ATM_GETSTAT:
334 size = sizeof(struct atm_dev_stats);
335 error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ);
336 if (error)
337 goto done;
338 break;
339 case ATM_GETCIRANGE:
340 size = sizeof(struct atm_cirange);
341 if (copy_to_user(buf, &dev->ci_range, size)) {
342 error = -EFAULT;
343 goto done;
344 }
345 break;
346 case ATM_GETLINKRATE:
347 size = sizeof(int);
348 if (copy_to_user(buf, &dev->link_rate, size)) {
349 error = -EFAULT;
350 goto done;
351 }
352 break;
353 case ATM_RSTADDR:
354 if (!capable(CAP_NET_ADMIN)) {
355 error = -EPERM;
356 goto done;
357 }
358 atm_reset_addr(dev, ATM_ADDR_LOCAL);
359 break;
360 case ATM_ADDADDR:
361 case ATM_DELADDR:
362 case ATM_ADDLECSADDR:
363 case ATM_DELLECSADDR:
364 {
365 struct sockaddr_atmsvc addr;
366
367 if (!capable(CAP_NET_ADMIN)) {
368 error = -EPERM;
369 goto done;
370 }
371
372 if (copy_from_user(&addr, buf, sizeof(addr))) {
373 error = -EFAULT;
374 goto done;
375 }
376 if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR)
377 error = atm_add_addr(dev, &addr,
378 (cmd == ATM_ADDADDR ?
389 ATM_ADDR_LOCAL : ATM_ADDR_LECS)); 379 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
390 if (error < 0) 380 else
391 goto done; 381 error = atm_del_addr(dev, &addr,
392 size = error; 382 (cmd == ATM_DELADDR ?
393 /* may return 0, but later on size == 0 means "don't 383 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
394 write the length" */ 384 goto done;
395 error = put_user(size, sioc_len) 385 }
396 ? -EFAULT : 0; 386 case ATM_GETADDR:
387 case ATM_GETLECSADDR:
388 error = atm_get_addr(dev, buf, len,
389 (cmd == ATM_GETADDR ?
390 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
391 if (error < 0)
392 goto done;
393 size = error;
394 /* may return 0, but later on size == 0 means "don't
395 write the length" */
396 error = put_user(size, sioc_len) ? -EFAULT : 0;
397 goto done;
398 case ATM_SETLOOP:
399 if (__ATM_LM_XTRMT((int) (unsigned long) buf) &&
400 __ATM_LM_XTLOC((int) (unsigned long) buf) >
401 __ATM_LM_XTRMT((int) (unsigned long) buf)) {
402 error = -EINVAL;
397 goto done; 403 goto done;
398 case ATM_SETLOOP: 404 }
399 if (__ATM_LM_XTRMT((int) (unsigned long) buf) && 405 /* fall through */
400 __ATM_LM_XTLOC((int) (unsigned long) buf) > 406 case ATM_SETCIRANGE:
401 __ATM_LM_XTRMT((int) (unsigned long) buf)) { 407 case SONET_GETSTATZ:
408 case SONET_SETDIAG:
409 case SONET_CLRDIAG:
410 case SONET_SETFRAMING:
411 if (!capable(CAP_NET_ADMIN)) {
412 error = -EPERM;
413 goto done;
414 }
415 /* fall through */
416 default:
417 if (compat) {
418#ifdef CONFIG_COMPAT
419 if (!dev->ops->compat_ioctl) {
402 error = -EINVAL; 420 error = -EINVAL;
403 goto done; 421 goto done;
404 } 422 }
405 /* fall through */ 423 size = dev->ops->compat_ioctl(dev, cmd, buf);
406 case ATM_SETCIRANGE:
407 case SONET_GETSTATZ:
408 case SONET_SETDIAG:
409 case SONET_CLRDIAG:
410 case SONET_SETFRAMING:
411 if (!capable(CAP_NET_ADMIN)) {
412 error = -EPERM;
413 goto done;
414 }
415 /* fall through */
416 default:
417 if (compat) {
418#ifdef CONFIG_COMPAT
419 if (!dev->ops->compat_ioctl) {
420 error = -EINVAL;
421 goto done;
422 }
423 size = dev->ops->compat_ioctl(dev, cmd, buf);
424#endif 424#endif
425 } else { 425 } else {
426 if (!dev->ops->ioctl) { 426 if (!dev->ops->ioctl) {
427 error = -EINVAL; 427 error = -EINVAL;
428 goto done;
429 }
430 size = dev->ops->ioctl(dev, cmd, buf);
431 }
432 if (size < 0) {
433 error = (size == -ENOIOCTLCMD ? -EINVAL : size);
434 goto done; 428 goto done;
435 } 429 }
430 size = dev->ops->ioctl(dev, cmd, buf);
431 }
432 if (size < 0) {
433 error = (size == -ENOIOCTLCMD ? -EINVAL : size);
434 goto done;
435 }
436 } 436 }
437 437
438 if (size) 438 if (size)
439 error = put_user(size, sioc_len) 439 error = put_user(size, sioc_len) ? -EFAULT : 0;
440 ? -EFAULT : 0;
441 else 440 else
442 error = 0; 441 error = 0;
443done: 442done:
@@ -445,7 +444,7 @@ done:
445 return error; 444 return error;
446} 445}
447 446
448static __inline__ void *dev_get_idx(loff_t left) 447static inline void *dev_get_idx(loff_t left)
449{ 448{
450 struct list_head *p; 449 struct list_head *p;
451 450
@@ -474,8 +473,3 @@ void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
474 ? atm_devs.next : ((struct list_head *)v)->next; 473 ? atm_devs.next : ((struct list_head *)v)->next;
475 return (v == &atm_devs) ? NULL : v; 474 return (v == &atm_devs) ? NULL : v;
476} 475}
477
478
479EXPORT_SYMBOL(atm_dev_register);
480EXPORT_SYMBOL(atm_dev_deregister);
481EXPORT_SYMBOL(atm_dev_lookup);