aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netconsole.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/netconsole.c')
-rw-r--r--drivers/net/netconsole.c108
1 files changed, 35 insertions, 73 deletions
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index eb41e44921e..dfc82720065 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -242,34 +242,6 @@ static struct netconsole_target *to_target(struct config_item *item)
242} 242}
243 243
244/* 244/*
245 * Wrapper over simple_strtol (base 10) with sanity and range checking.
246 * We return (signed) long only because we may want to return errors.
247 * Do not use this to convert numbers that are allowed to be negative.
248 */
249static long strtol10_check_range(const char *cp, long min, long max)
250{
251 long ret;
252 char *p = (char *) cp;
253
254 WARN_ON(min < 0);
255 WARN_ON(max < min);
256
257 ret = simple_strtol(p, &p, 10);
258
259 if (*p && (*p != '\n')) {
260 printk(KERN_ERR "netconsole: invalid input\n");
261 return -EINVAL;
262 }
263 if ((ret < min) || (ret > max)) {
264 printk(KERN_ERR "netconsole: input %ld must be between "
265 "%ld and %ld\n", ret, min, max);
266 return -EINVAL;
267 }
268
269 return ret;
270}
271
272/*
273 * Attribute operations for netconsole_target. 245 * Attribute operations for netconsole_target.
274 */ 246 */
275 247
@@ -327,12 +299,14 @@ static ssize_t store_enabled(struct netconsole_target *nt,
327 const char *buf, 299 const char *buf,
328 size_t count) 300 size_t count)
329{ 301{
302 int enabled;
330 int err; 303 int err;
331 long enabled;
332 304
333 enabled = strtol10_check_range(buf, 0, 1); 305 err = kstrtoint(buf, 10, &enabled);
334 if (enabled < 0) 306 if (err < 0)
335 return enabled; 307 return err;
308 if (enabled < 0 || enabled > 1)
309 return -EINVAL;
336 310
337 if (enabled) { /* 1 */ 311 if (enabled) { /* 1 */
338 312
@@ -384,8 +358,7 @@ static ssize_t store_local_port(struct netconsole_target *nt,
384 const char *buf, 358 const char *buf,
385 size_t count) 359 size_t count)
386{ 360{
387 long local_port; 361 int rv;
388#define __U16_MAX ((__u16) ~0U)
389 362
390 if (nt->enabled) { 363 if (nt->enabled) {
391 printk(KERN_ERR "netconsole: target (%s) is enabled, " 364 printk(KERN_ERR "netconsole: target (%s) is enabled, "
@@ -394,12 +367,9 @@ static ssize_t store_local_port(struct netconsole_target *nt,
394 return -EINVAL; 367 return -EINVAL;
395 } 368 }
396 369
397 local_port = strtol10_check_range(buf, 0, __U16_MAX); 370 rv = kstrtou16(buf, 10, &nt->np.local_port);
398 if (local_port < 0) 371 if (rv < 0)
399 return local_port; 372 return rv;
400
401 nt->np.local_port = local_port;
402
403 return strnlen(buf, count); 373 return strnlen(buf, count);
404} 374}
405 375
@@ -407,8 +377,7 @@ static ssize_t store_remote_port(struct netconsole_target *nt,
407 const char *buf, 377 const char *buf,
408 size_t count) 378 size_t count)
409{ 379{
410 long remote_port; 380 int rv;
411#define __U16_MAX ((__u16) ~0U)
412 381
413 if (nt->enabled) { 382 if (nt->enabled) {
414 printk(KERN_ERR "netconsole: target (%s) is enabled, " 383 printk(KERN_ERR "netconsole: target (%s) is enabled, "
@@ -417,12 +386,9 @@ static ssize_t store_remote_port(struct netconsole_target *nt,
417 return -EINVAL; 386 return -EINVAL;
418 } 387 }
419 388
420 remote_port = strtol10_check_range(buf, 0, __U16_MAX); 389 rv = kstrtou16(buf, 10, &nt->np.remote_port);
421 if (remote_port < 0) 390 if (rv < 0)
422 return remote_port; 391 return rv;
423
424 nt->np.remote_port = remote_port;
425
426 return strnlen(buf, count); 392 return strnlen(buf, count);
427} 393}
428 394
@@ -463,8 +429,6 @@ static ssize_t store_remote_mac(struct netconsole_target *nt,
463 size_t count) 429 size_t count)
464{ 430{
465 u8 remote_mac[ETH_ALEN]; 431 u8 remote_mac[ETH_ALEN];
466 char *p = (char *) buf;
467 int i;
468 432
469 if (nt->enabled) { 433 if (nt->enabled) {
470 printk(KERN_ERR "netconsole: target (%s) is enabled, " 434 printk(KERN_ERR "netconsole: target (%s) is enabled, "
@@ -473,23 +437,13 @@ static ssize_t store_remote_mac(struct netconsole_target *nt,
473 return -EINVAL; 437 return -EINVAL;
474 } 438 }
475 439
476 for (i = 0; i < ETH_ALEN - 1; i++) { 440 if (!mac_pton(buf, remote_mac))
477 remote_mac[i] = simple_strtoul(p, &p, 16); 441 return -EINVAL;
478 if (*p != ':') 442 if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
479 goto invalid; 443 return -EINVAL;
480 p++;
481 }
482 remote_mac[ETH_ALEN - 1] = simple_strtoul(p, &p, 16);
483 if (*p && (*p != '\n'))
484 goto invalid;
485
486 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN); 444 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
487 445
488 return strnlen(buf, count); 446 return strnlen(buf, count);
489
490invalid:
491 printk(KERN_ERR "netconsole: invalid input\n");
492 return -EINVAL;
493} 447}
494 448
495/* 449/*
@@ -667,11 +621,10 @@ static int netconsole_netdev_event(struct notifier_block *this,
667 bool stopped = false; 621 bool stopped = false;
668 622
669 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER || 623 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
670 event == NETDEV_BONDING_DESLAVE || event == NETDEV_GOING_DOWN)) 624 event == NETDEV_RELEASE || event == NETDEV_JOIN))
671 goto done; 625 goto done;
672 626
673 spin_lock_irqsave(&target_list_lock, flags); 627 spin_lock_irqsave(&target_list_lock, flags);
674restart:
675 list_for_each_entry(nt, &target_list, list) { 628 list_for_each_entry(nt, &target_list, list) {
676 netconsole_target_get(nt); 629 netconsole_target_get(nt);
677 if (nt->np.dev == dev) { 630 if (nt->np.dev == dev) {
@@ -679,6 +632,8 @@ restart:
679 case NETDEV_CHANGENAME: 632 case NETDEV_CHANGENAME:
680 strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ); 633 strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
681 break; 634 break;
635 case NETDEV_RELEASE:
636 case NETDEV_JOIN:
682 case NETDEV_UNREGISTER: 637 case NETDEV_UNREGISTER:
683 /* 638 /*
684 * rtnl_lock already held 639 * rtnl_lock already held
@@ -693,11 +648,7 @@ restart:
693 dev_put(nt->np.dev); 648 dev_put(nt->np.dev);
694 nt->np.dev = NULL; 649 nt->np.dev = NULL;
695 netconsole_target_put(nt); 650 netconsole_target_put(nt);
696 goto restart;
697 } 651 }
698 /* Fall through */
699 case NETDEV_GOING_DOWN:
700 case NETDEV_BONDING_DESLAVE:
701 nt->enabled = 0; 652 nt->enabled = 0;
702 stopped = true; 653 stopped = true;
703 break; 654 break;
@@ -706,10 +657,21 @@ restart:
706 netconsole_target_put(nt); 657 netconsole_target_put(nt);
707 } 658 }
708 spin_unlock_irqrestore(&target_list_lock, flags); 659 spin_unlock_irqrestore(&target_list_lock, flags);
709 if (stopped && (event == NETDEV_UNREGISTER || event == NETDEV_BONDING_DESLAVE)) 660 if (stopped) {
710 printk(KERN_INFO "netconsole: network logging stopped on " 661 printk(KERN_INFO "netconsole: network logging stopped on "
711 "interface %s as it %s\n", dev->name, 662 "interface %s as it ", dev->name);
712 event == NETDEV_UNREGISTER ? "unregistered" : "released slaves"); 663 switch (event) {
664 case NETDEV_UNREGISTER:
665 printk(KERN_CONT "unregistered\n");
666 break;
667 case NETDEV_RELEASE:
668 printk(KERN_CONT "released slaves\n");
669 break;
670 case NETDEV_JOIN:
671 printk(KERN_CONT "is joining a master device\n");
672 break;
673 }
674 }
713 675
714done: 676done:
715 return NOTIFY_DONE; 677 return NOTIFY_DONE;