1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * linux/drivers/net/netconsole.c 4 * 5 * Copyright (C) 2001 Ingo Molnar <mingo@redhat.com> 6 * 7 * This file contains the implementation of an IRQ-safe, crash-safe 8 * kernel console implementation that outputs kernel messages to the 9 * network. 10 * 11 * Modification history: 12 * 13 * 2001-09-17 started by Ingo Molnar. 14 * 2003-08-11 2.6 port by Matt Mackall 15 * simplified options 16 * generic card hooks 17 * works non-modular 18 * 2003-09-07 rewritten with netpoll api 19 */ 20 21 /**************************************************************** 22 * 23 ****************************************************************/ 24 25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 26 27 #include <linux/mm.h> 28 #include <linux/init.h> 29 #include <linux/module.h> 30 #include <linux/slab.h> 31 #include <linux/console.h> 32 #include <linux/moduleparam.h> 33 #include <linux/kernel.h> 34 #include <linux/string.h> 35 #include <linux/netpoll.h> 36 #include <linux/inet.h> 37 #include <linux/configfs.h> 38 #include <linux/etherdevice.h> 39 #include <linux/utsname.h> 40 41 MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@selenic.com>"); 42 MODULE_DESCRIPTION("Console driver for network interfaces"); 43 MODULE_LICENSE("GPL"); 44 45 #define MAX_PARAM_LENGTH 256 46 #define MAX_PRINT_CHUNK 1000 47 48 static char config[MAX_PARAM_LENGTH]; 49 module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0); 50 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]"); 51 52 static bool oops_only = false; 53 module_param(oops_only, bool, 0600); 54 MODULE_PARM_DESC(oops_only, "Only log oops messages"); 55 56 #ifndef MODULE 57 static int __init option_setup(char *opt) 58 { 59 strscpy(config, opt, MAX_PARAM_LENGTH); 60 return 1; 61 } 62 __setup("netconsole=", option_setup); 63 #endif /* MODULE */ 64 65 /* Linked list of all configured targets */ 66 static LIST_HEAD(target_list); 67 68 /* This needs to be a spinlock because write_msg() cannot sleep */ 69 static DEFINE_SPINLOCK(target_list_lock); 70 71 /* 72 * Console driver for extended netconsoles. Registered on the first use to 73 * avoid unnecessarily enabling ext message formatting. 74 */ 75 static struct console netconsole_ext; 76 77 /** 78 * struct netconsole_target - Represents a configured netconsole target. 79 * @list: Links this target into the target_list. 80 * @item: Links us into the configfs subsystem hierarchy. 81 * @enabled: On / off knob to enable / disable target. 82 * Visible from userspace (read-write). 83 * We maintain a strict 1:1 correspondence between this and 84 * whether the corresponding netpoll is active or inactive. 85 * Also, other parameters of a target may be modified at 86 * runtime only when it is disabled (enabled == 0). 87 * @extended: Denotes whether console is extended or not. 88 * @release: Denotes whether kernel release version should be prepended 89 * to the message. Depends on extended console. 90 * @np: The netpoll structure for this target. 91 * Contains the other userspace visible parameters: 92 * dev_name (read-write) 93 * local_port (read-write) 94 * remote_port (read-write) 95 * local_ip (read-write) 96 * remote_ip (read-write) 97 * local_mac (read-only) 98 * remote_mac (read-write) 99 */ 100 struct netconsole_target { 101 struct list_head list; 102 #ifdef CONFIG_NETCONSOLE_DYNAMIC 103 struct config_item item; 104 #endif 105 bool enabled; 106 bool extended; 107 bool release; 108 struct netpoll np; 109 }; 110 111 #ifdef CONFIG_NETCONSOLE_DYNAMIC 112 113 static struct configfs_subsystem netconsole_subsys; 114 static DEFINE_MUTEX(dynamic_netconsole_mutex); 115 116 static int __init dynamic_netconsole_init(void) 117 { 118 config_group_init(&netconsole_subsys.su_group); 119 mutex_init(&netconsole_subsys.su_mutex); 120 return configfs_register_subsystem(&netconsole_subsys); 121 } 122 123 static void __exit dynamic_netconsole_exit(void) 124 { 125 configfs_unregister_subsystem(&netconsole_subsys); 126 } 127 128 /* 129 * Targets that were created by parsing the boot/module option string 130 * do not exist in the configfs hierarchy (and have NULL names) and will 131 * never go away, so make these a no-op for them. 132 */ 133 static void netconsole_target_get(struct netconsole_target *nt) 134 { 135 if (config_item_name(&nt->item)) 136 config_item_get(&nt->item); 137 } 138 139 static void netconsole_target_put(struct netconsole_target *nt) 140 { 141 if (config_item_name(&nt->item)) 142 config_item_put(&nt->item); 143 } 144 145 #else /* !CONFIG_NETCONSOLE_DYNAMIC */ 146 147 static int __init dynamic_netconsole_init(void) 148 { 149 return 0; 150 } 151 152 static void __exit dynamic_netconsole_exit(void) 153 { 154 } 155 156 /* 157 * No danger of targets going away from under us when dynamic 158 * reconfigurability is off. 159 */ 160 static void netconsole_target_get(struct netconsole_target *nt) 161 { 162 } 163 164 static void netconsole_target_put(struct netconsole_target *nt) 165 { 166 } 167 168 #endif /* CONFIG_NETCONSOLE_DYNAMIC */ 169 170 /* Allocate and initialize with defaults. 171 * Note that these targets get their config_item fields zeroed-out. 172 */ 173 static struct netconsole_target *alloc_and_init(void) 174 { 175 struct netconsole_target *nt; 176 177 nt = kzalloc(sizeof(*nt), GFP_KERNEL); 178 if (!nt) 179 return nt; 180 181 if (IS_ENABLED(CONFIG_NETCONSOLE_EXTENDED_LOG)) 182 nt->extended = true; 183 if (IS_ENABLED(CONFIG_NETCONSOLE_PREPEND_RELEASE)) 184 nt->release = true; 185 186 nt->np.name = "netconsole"; 187 strscpy(nt->np.dev_name, "eth0", IFNAMSIZ); 188 nt->np.local_port = 6665; 189 nt->np.remote_port = 6666; 190 eth_broadcast_addr(nt->np.remote_mac); 191 192 return nt; 193 } 194 195 /* Allocate new target (from boot/module param) and setup netpoll for it */ 196 static struct netconsole_target *alloc_param_target(char *target_config) 197 { 198 struct netconsole_target *nt; 199 int err; 200 201 nt = alloc_and_init(); 202 if (!nt) { 203 err = -ENOMEM; 204 goto fail; 205 } 206 207 if (*target_config == '+') { 208 nt->extended = true; 209 target_config++; 210 } 211 212 if (*target_config == 'r') { 213 if (!nt->extended) { 214 pr_err("Netconsole configuration error. Release feature requires extended log message"); 215 err = -EINVAL; 216 goto fail; 217 } 218 nt->release = true; 219 target_config++; 220 } 221 222 /* Parse parameters and setup netpoll */ 223 err = netpoll_parse_options(&nt->np, target_config); 224 if (err) 225 goto fail; 226 227 err = netpoll_setup(&nt->np); 228 if (err) 229 goto fail; 230 231 nt->enabled = true; 232 233 return nt; 234 235 fail: 236 kfree(nt); 237 return ERR_PTR(err); 238 } 239 240 /* Cleanup netpoll for given target (from boot/module param) and free it */ 241 static void free_param_target(struct netconsole_target *nt) 242 { 243 netpoll_cleanup(&nt->np); 244 kfree(nt); 245 } 246 247 #ifdef CONFIG_NETCONSOLE_DYNAMIC 248 249 /* 250 * Our subsystem hierarchy is: 251 * 252 * /sys/kernel/config/netconsole/ 253 * | 254 * <target>/ 255 * | enabled 256 * | release 257 * | dev_name 258 * | local_port 259 * | remote_port 260 * | local_ip 261 * | remote_ip 262 * | local_mac 263 * | remote_mac 264 * | 265 * <target>/... 266 */ 267 268 static struct netconsole_target *to_target(struct config_item *item) 269 { 270 return item ? 271 container_of(item, struct netconsole_target, item) : 272 NULL; 273 } 274 275 /* 276 * Attribute operations for netconsole_target. 277 */ 278 279 static ssize_t enabled_show(struct config_item *item, char *buf) 280 { 281 return sysfs_emit(buf, "%d\n", to_target(item)->enabled); 282 } 283 284 static ssize_t extended_show(struct config_item *item, char *buf) 285 { 286 return sysfs_emit(buf, "%d\n", to_target(item)->extended); 287 } 288 289 static ssize_t release_show(struct config_item *item, char *buf) 290 { 291 return sysfs_emit(buf, "%d\n", to_target(item)->release); 292 } 293 294 static ssize_t dev_name_show(struct config_item *item, char *buf) 295 { 296 return sysfs_emit(buf, "%s\n", to_target(item)->np.dev_name); 297 } 298 299 static ssize_t local_port_show(struct config_item *item, char *buf) 300 { 301 return sysfs_emit(buf, "%d\n", to_target(item)->np.local_port); 302 } 303 304 static ssize_t remote_port_show(struct config_item *item, char *buf) 305 { 306 return sysfs_emit(buf, "%d\n", to_target(item)->np.remote_port); 307 } 308 309 static ssize_t local_ip_show(struct config_item *item, char *buf) 310 { 311 struct netconsole_target *nt = to_target(item); 312 313 if (nt->np.ipv6) 314 return sysfs_emit(buf, "%pI6c\n", &nt->np.local_ip.in6); 315 else 316 return sysfs_emit(buf, "%pI4\n", &nt->np.local_ip); 317 } 318 319 static ssize_t remote_ip_show(struct config_item *item, char *buf) 320 { 321 struct netconsole_target *nt = to_target(item); 322 323 if (nt->np.ipv6) 324 return sysfs_emit(buf, "%pI6c\n", &nt->np.remote_ip.in6); 325 else 326 return sysfs_emit(buf, "%pI4\n", &nt->np.remote_ip); 327 } 328 329 static ssize_t local_mac_show(struct config_item *item, char *buf) 330 { 331 struct net_device *dev = to_target(item)->np.dev; 332 static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 333 334 return sysfs_emit(buf, "%pM\n", dev ? dev->dev_addr : bcast); 335 } 336 337 static ssize_t remote_mac_show(struct config_item *item, char *buf) 338 { 339 return sysfs_emit(buf, "%pM\n", to_target(item)->np.remote_mac); 340 } 341 342 /* 343 * This one is special -- targets created through the configfs interface 344 * are not enabled (and the corresponding netpoll activated) by default. 345 * The user is expected to set the desired parameters first (which 346 * would enable him to dynamically add new netpoll targets for new 347 * network interfaces as and when they come up). 348 */ 349 static ssize_t enabled_store(struct config_item *item, 350 const char *buf, size_t count) 351 { 352 struct netconsole_target *nt = to_target(item); 353 unsigned long flags; 354 bool enabled; 355 int err; 356 357 mutex_lock(&dynamic_netconsole_mutex); 358 err = kstrtobool(buf, &enabled); 359 if (err) 360 goto out_unlock; 361 362 err = -EINVAL; 363 if ((bool)enabled == nt->enabled) { 364 pr_info("network logging has already %s\n", 365 nt->enabled ? "started" : "stopped"); 366 goto out_unlock; 367 } 368 369 if (enabled) { /* true */ 370 if (nt->release && !nt->extended) { 371 pr_err("Not enabling netconsole. Release feature requires extended log message"); 372 goto out_unlock; 373 } 374 375 if (nt->extended && !console_is_registered(&netconsole_ext)) 376 register_console(&netconsole_ext); 377 378 /* 379 * Skip netpoll_parse_options() -- all the attributes are 380 * already configured via configfs. Just print them out. 381 */ 382 netpoll_print_options(&nt->np); 383 384 err = netpoll_setup(&nt->np); 385 if (err) 386 goto out_unlock; 387 388 pr_info("network logging started\n"); 389 } else { /* false */ 390 /* We need to disable the netconsole before cleaning it up 391 * otherwise we might end up in write_msg() with 392 * nt->np.dev == NULL and nt->enabled == true 393 */ 394 spin_lock_irqsave(&target_list_lock, flags); 395 nt->enabled = false; 396 spin_unlock_irqrestore(&target_list_lock, flags); 397 netpoll_cleanup(&nt->np); 398 } 399 400 nt->enabled = enabled; 401 402 mutex_unlock(&dynamic_netconsole_mutex); 403 return strnlen(buf, count); 404 out_unlock: 405 mutex_unlock(&dynamic_netconsole_mutex); 406 return err; 407 } 408 409 static ssize_t release_store(struct config_item *item, const char *buf, 410 size_t count) 411 { 412 struct netconsole_target *nt = to_target(item); 413 bool release; 414 int err; 415 416 mutex_lock(&dynamic_netconsole_mutex); 417 if (nt->enabled) { 418 pr_err("target (%s) is enabled, disable to update parameters\n", 419 config_item_name(&nt->item)); 420 err = -EINVAL; 421 goto out_unlock; 422 } 423 424 err = kstrtobool(buf, &release); 425 if (err) 426 goto out_unlock; 427 428 nt->release = release; 429 430 mutex_unlock(&dynamic_netconsole_mutex); 431 return strnlen(buf, count); 432 out_unlock: 433 mutex_unlock(&dynamic_netconsole_mutex); 434 return err; 435 } 436 437 static ssize_t extended_store(struct config_item *item, const char *buf, 438 size_t count) 439 { 440 struct netconsole_target *nt = to_target(item); 441 bool extended; 442 int err; 443 444 mutex_lock(&dynamic_netconsole_mutex); 445 if (nt->enabled) { 446 pr_err("target (%s) is enabled, disable to update parameters\n", 447 config_item_name(&nt->item)); 448 err = -EINVAL; 449 goto out_unlock; 450 } 451 452 err = kstrtobool(buf, &extended); 453 if (err) 454 goto out_unlock; 455 456 nt->extended = extended; 457 458 mutex_unlock(&dynamic_netconsole_mutex); 459 return strnlen(buf, count); 460 out_unlock: 461 mutex_unlock(&dynamic_netconsole_mutex); 462 return err; 463 } 464 465 static ssize_t dev_name_store(struct config_item *item, const char *buf, 466 size_t count) 467 { 468 struct netconsole_target *nt = to_target(item); 469 size_t len; 470 471 mutex_lock(&dynamic_netconsole_mutex); 472 if (nt->enabled) { 473 pr_err("target (%s) is enabled, disable to update parameters\n", 474 config_item_name(&nt->item)); 475 mutex_unlock(&dynamic_netconsole_mutex); 476 return -EINVAL; 477 } 478 479 strscpy(nt->np.dev_name, buf, IFNAMSIZ); 480 481 /* Get rid of possible trailing newline from echo(1) */ 482 len = strnlen(nt->np.dev_name, IFNAMSIZ); 483 if (nt->np.dev_name[len - 1] == '\n') 484 nt->np.dev_name[len - 1] = '\0'; 485 486 mutex_unlock(&dynamic_netconsole_mutex); 487 return strnlen(buf, count); 488 } 489 490 static ssize_t local_port_store(struct config_item *item, const char *buf, 491 size_t count) 492 { 493 struct netconsole_target *nt = to_target(item); 494 int rv = -EINVAL; 495 496 mutex_lock(&dynamic_netconsole_mutex); 497 if (nt->enabled) { 498 pr_err("target (%s) is enabled, disable to update parameters\n", 499 config_item_name(&nt->item)); 500 goto out_unlock; 501 } 502 503 rv = kstrtou16(buf, 10, &nt->np.local_port); 504 if (rv < 0) 505 goto out_unlock; 506 mutex_unlock(&dynamic_netconsole_mutex); 507 return strnlen(buf, count); 508 out_unlock: 509 mutex_unlock(&dynamic_netconsole_mutex); 510 return rv; 511 } 512 513 static ssize_t remote_port_store(struct config_item *item, 514 const char *buf, size_t count) 515 { 516 struct netconsole_target *nt = to_target(item); 517 int rv = -EINVAL; 518 519 mutex_lock(&dynamic_netconsole_mutex); 520 if (nt->enabled) { 521 pr_err("target (%s) is enabled, disable to update parameters\n", 522 config_item_name(&nt->item)); 523 goto out_unlock; 524 } 525 526 rv = kstrtou16(buf, 10, &nt->np.remote_port); 527 if (rv < 0) 528 goto out_unlock; 529 mutex_unlock(&dynamic_netconsole_mutex); 530 return strnlen(buf, count); 531 out_unlock: 532 mutex_unlock(&dynamic_netconsole_mutex); 533 return rv; 534 } 535 536 static ssize_t local_ip_store(struct config_item *item, const char *buf, 537 size_t count) 538 { 539 struct netconsole_target *nt = to_target(item); 540 541 mutex_lock(&dynamic_netconsole_mutex); 542 if (nt->enabled) { 543 pr_err("target (%s) is enabled, disable to update parameters\n", 544 config_item_name(&nt->item)); 545 goto out_unlock; 546 } 547 548 if (strnchr(buf, count, ':')) { 549 const char *end; 550 if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) { 551 if (*end && *end != '\n') { 552 pr_err("invalid IPv6 address at: <%c>\n", *end); 553 goto out_unlock; 554 } 555 nt->np.ipv6 = true; 556 } else 557 goto out_unlock; 558 } else { 559 if (!nt->np.ipv6) { 560 nt->np.local_ip.ip = in_aton(buf); 561 } else 562 goto out_unlock; 563 } 564 565 mutex_unlock(&dynamic_netconsole_mutex); 566 return strnlen(buf, count); 567 out_unlock: 568 mutex_unlock(&dynamic_netconsole_mutex); 569 return -EINVAL; 570 } 571 572 static ssize_t remote_ip_store(struct config_item *item, const char *buf, 573 size_t count) 574 { 575 struct netconsole_target *nt = to_target(item); 576 577 mutex_lock(&dynamic_netconsole_mutex); 578 if (nt->enabled) { 579 pr_err("target (%s) is enabled, disable to update parameters\n", 580 config_item_name(&nt->item)); 581 goto out_unlock; 582 } 583 584 if (strnchr(buf, count, ':')) { 585 const char *end; 586 if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) { 587 if (*end && *end != '\n') { 588 pr_err("invalid IPv6 address at: <%c>\n", *end); 589 goto out_unlock; 590 } 591 nt->np.ipv6 = true; 592 } else 593 goto out_unlock; 594 } else { 595 if (!nt->np.ipv6) { 596 nt->np.remote_ip.ip = in_aton(buf); 597 } else 598 goto out_unlock; 599 } 600 601 mutex_unlock(&dynamic_netconsole_mutex); 602 return strnlen(buf, count); 603 out_unlock: 604 mutex_unlock(&dynamic_netconsole_mutex); 605 return -EINVAL; 606 } 607 608 static ssize_t remote_mac_store(struct config_item *item, const char *buf, 609 size_t count) 610 { 611 struct netconsole_target *nt = to_target(item); 612 u8 remote_mac[ETH_ALEN]; 613 614 mutex_lock(&dynamic_netconsole_mutex); 615 if (nt->enabled) { 616 pr_err("target (%s) is enabled, disable to update parameters\n", 617 config_item_name(&nt->item)); 618 goto out_unlock; 619 } 620 621 if (!mac_pton(buf, remote_mac)) 622 goto out_unlock; 623 if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n') 624 goto out_unlock; 625 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN); 626 627 mutex_unlock(&dynamic_netconsole_mutex); 628 return strnlen(buf, count); 629 out_unlock: 630 mutex_unlock(&dynamic_netconsole_mutex); 631 return -EINVAL; 632 } 633 634 CONFIGFS_ATTR(, enabled); 635 CONFIGFS_ATTR(, extended); 636 CONFIGFS_ATTR(, dev_name); 637 CONFIGFS_ATTR(, local_port); 638 CONFIGFS_ATTR(, remote_port); 639 CONFIGFS_ATTR(, local_ip); 640 CONFIGFS_ATTR(, remote_ip); 641 CONFIGFS_ATTR_RO(, local_mac); 642 CONFIGFS_ATTR(, remote_mac); 643 CONFIGFS_ATTR(, release); 644 645 static struct configfs_attribute *netconsole_target_attrs[] = { 646 &attr_enabled, 647 &attr_extended, 648 &attr_release, 649 &attr_dev_name, 650 &attr_local_port, 651 &attr_remote_port, 652 &attr_local_ip, 653 &attr_remote_ip, 654 &attr_local_mac, 655 &attr_remote_mac, 656 NULL, 657 }; 658 659 /* 660 * Item operations and type for netconsole_target. 661 */ 662 663 static void netconsole_target_release(struct config_item *item) 664 { 665 kfree(to_target(item)); 666 } 667 668 static struct configfs_item_operations netconsole_target_item_ops = { 669 .release = netconsole_target_release, 670 }; 671 672 static const struct config_item_type netconsole_target_type = { 673 .ct_attrs = netconsole_target_attrs, 674 .ct_item_ops = &netconsole_target_item_ops, 675 .ct_owner = THIS_MODULE, 676 }; 677 678 /* 679 * Group operations and type for netconsole_subsys. 680 */ 681 682 static struct config_item *make_netconsole_target(struct config_group *group, 683 const char *name) 684 { 685 struct netconsole_target *nt; 686 unsigned long flags; 687 688 nt = alloc_and_init(); 689 if (!nt) 690 return ERR_PTR(-ENOMEM); 691 692 /* Initialize the config_item member */ 693 config_item_init_type_name(&nt->item, name, &netconsole_target_type); 694 695 /* Adding, but it is disabled */ 696 spin_lock_irqsave(&target_list_lock, flags); 697 list_add(&nt->list, &target_list); 698 spin_unlock_irqrestore(&target_list_lock, flags); 699 700 return &nt->item; 701 } 702 703 static void drop_netconsole_target(struct config_group *group, 704 struct config_item *item) 705 { 706 unsigned long flags; 707 struct netconsole_target *nt = to_target(item); 708 709 spin_lock_irqsave(&target_list_lock, flags); 710 list_del(&nt->list); 711 spin_unlock_irqrestore(&target_list_lock, flags); 712 713 /* 714 * The target may have never been enabled, or was manually disabled 715 * before being removed so netpoll may have already been cleaned up. 716 */ 717 if (nt->enabled) 718 netpoll_cleanup(&nt->np); 719 720 config_item_put(&nt->item); 721 } 722 723 static struct configfs_group_operations netconsole_subsys_group_ops = { 724 .make_item = make_netconsole_target, 725 .drop_item = drop_netconsole_target, 726 }; 727 728 static const struct config_item_type netconsole_subsys_type = { 729 .ct_group_ops = &netconsole_subsys_group_ops, 730 .ct_owner = THIS_MODULE, 731 }; 732 733 /* The netconsole configfs subsystem */ 734 static struct configfs_subsystem netconsole_subsys = { 735 .su_group = { 736 .cg_item = { 737 .ci_namebuf = "netconsole", 738 .ci_type = &netconsole_subsys_type, 739 }, 740 }, 741 }; 742 743 #endif /* CONFIG_NETCONSOLE_DYNAMIC */ 744 745 /* Handle network interface device notifications */ 746 static int netconsole_netdev_event(struct notifier_block *this, 747 unsigned long event, void *ptr) 748 { 749 unsigned long flags; 750 struct netconsole_target *nt; 751 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 752 bool stopped = false; 753 754 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER || 755 event == NETDEV_RELEASE || event == NETDEV_JOIN)) 756 goto done; 757 758 spin_lock_irqsave(&target_list_lock, flags); 759 restart: 760 list_for_each_entry(nt, &target_list, list) { 761 netconsole_target_get(nt); 762 if (nt->np.dev == dev) { 763 switch (event) { 764 case NETDEV_CHANGENAME: 765 strscpy(nt->np.dev_name, dev->name, IFNAMSIZ); 766 break; 767 case NETDEV_RELEASE: 768 case NETDEV_JOIN: 769 case NETDEV_UNREGISTER: 770 /* rtnl_lock already held 771 * we might sleep in __netpoll_cleanup() 772 */ 773 nt->enabled = false; 774 spin_unlock_irqrestore(&target_list_lock, flags); 775 776 __netpoll_cleanup(&nt->np); 777 778 spin_lock_irqsave(&target_list_lock, flags); 779 netdev_put(nt->np.dev, &nt->np.dev_tracker); 780 nt->np.dev = NULL; 781 stopped = true; 782 netconsole_target_put(nt); 783 goto restart; 784 } 785 } 786 netconsole_target_put(nt); 787 } 788 spin_unlock_irqrestore(&target_list_lock, flags); 789 if (stopped) { 790 const char *msg = "had an event"; 791 switch (event) { 792 case NETDEV_UNREGISTER: 793 msg = "unregistered"; 794 break; 795 case NETDEV_RELEASE: 796 msg = "released slaves"; 797 break; 798 case NETDEV_JOIN: 799 msg = "is joining a master device"; 800 break; 801 } 802 pr_info("network logging stopped on interface %s as it %s\n", 803 dev->name, msg); 804 } 805 806 done: 807 return NOTIFY_DONE; 808 } 809 810 static struct notifier_block netconsole_netdev_notifier = { 811 .notifier_call = netconsole_netdev_event, 812 }; 813 814 /** 815 * send_ext_msg_udp - send extended log message to target 816 * @nt: target to send message to 817 * @msg: extended log message to send 818 * @msg_len: length of message 819 * 820 * Transfer extended log @msg to @nt. If @msg is longer than 821 * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with 822 * ncfrag header field added to identify them. 823 */ 824 static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg, 825 int msg_len) 826 { 827 static char buf[MAX_PRINT_CHUNK]; /* protected by target_list_lock */ 828 const char *header, *body; 829 int offset = 0; 830 int header_len, body_len; 831 const char *msg_ready = msg; 832 const char *release; 833 int release_len = 0; 834 835 if (nt->release) { 836 release = init_utsname()->release; 837 release_len = strlen(release) + 1; 838 } 839 840 if (msg_len + release_len <= MAX_PRINT_CHUNK) { 841 /* No fragmentation needed */ 842 if (nt->release) { 843 scnprintf(buf, MAX_PRINT_CHUNK, "%s,%s", release, msg); 844 msg_len += release_len; 845 msg_ready = buf; 846 } 847 netpoll_send_udp(&nt->np, msg_ready, msg_len); 848 return; 849 } 850 851 /* need to insert extra header fields, detect header and body */ 852 header = msg; 853 body = memchr(msg, ';', msg_len); 854 if (WARN_ON_ONCE(!body)) 855 return; 856 857 header_len = body - header; 858 body_len = msg_len - header_len - 1; 859 body++; 860 861 /* 862 * Transfer multiple chunks with the following extra header. 863 * "ncfrag=<byte-offset>/<total-bytes>" 864 */ 865 if (nt->release) 866 scnprintf(buf, MAX_PRINT_CHUNK, "%s,", release); 867 memcpy(buf + release_len, header, header_len); 868 header_len += release_len; 869 870 while (offset < body_len) { 871 int this_header = header_len; 872 int this_chunk; 873 874 this_header += scnprintf(buf + this_header, 875 sizeof(buf) - this_header, 876 ",ncfrag=%d/%d;", offset, body_len); 877 878 this_chunk = min(body_len - offset, 879 MAX_PRINT_CHUNK - this_header); 880 if (WARN_ON_ONCE(this_chunk <= 0)) 881 return; 882 883 memcpy(buf + this_header, body + offset, this_chunk); 884 885 netpoll_send_udp(&nt->np, buf, this_header + this_chunk); 886 887 offset += this_chunk; 888 } 889 } 890 891 static void write_ext_msg(struct console *con, const char *msg, 892 unsigned int len) 893 { 894 struct netconsole_target *nt; 895 unsigned long flags; 896 897 if ((oops_only && !oops_in_progress) || list_empty(&target_list)) 898 return; 899 900 spin_lock_irqsave(&target_list_lock, flags); 901 list_for_each_entry(nt, &target_list, list) 902 if (nt->extended && nt->enabled && netif_running(nt->np.dev)) 903 send_ext_msg_udp(nt, msg, len); 904 spin_unlock_irqrestore(&target_list_lock, flags); 905 } 906 907 static void write_msg(struct console *con, const char *msg, unsigned int len) 908 { 909 int frag, left; 910 unsigned long flags; 911 struct netconsole_target *nt; 912 const char *tmp; 913 914 if (oops_only && !oops_in_progress) 915 return; 916 /* Avoid taking lock and disabling interrupts unnecessarily */ 917 if (list_empty(&target_list)) 918 return; 919 920 spin_lock_irqsave(&target_list_lock, flags); 921 list_for_each_entry(nt, &target_list, list) { 922 if (!nt->extended && nt->enabled && netif_running(nt->np.dev)) { 923 /* 924 * We nest this inside the for-each-target loop above 925 * so that we're able to get as much logging out to 926 * at least one target if we die inside here, instead 927 * of unnecessarily keeping all targets in lock-step. 928 */ 929 tmp = msg; 930 for (left = len; left;) { 931 frag = min(left, MAX_PRINT_CHUNK); 932 netpoll_send_udp(&nt->np, tmp, frag); 933 tmp += frag; 934 left -= frag; 935 } 936 } 937 } 938 spin_unlock_irqrestore(&target_list_lock, flags); 939 } 940 941 static struct console netconsole_ext = { 942 .name = "netcon_ext", 943 .flags = CON_ENABLED | CON_EXTENDED, 944 .write = write_ext_msg, 945 }; 946 947 static struct console netconsole = { 948 .name = "netcon", 949 .flags = CON_ENABLED, 950 .write = write_msg, 951 }; 952 953 static int __init init_netconsole(void) 954 { 955 int err; 956 struct netconsole_target *nt, *tmp; 957 bool extended = false; 958 unsigned long flags; 959 char *target_config; 960 char *input = config; 961 962 if (strnlen(input, MAX_PARAM_LENGTH)) { 963 while ((target_config = strsep(&input, ";"))) { 964 nt = alloc_param_target(target_config); 965 if (IS_ERR(nt)) { 966 err = PTR_ERR(nt); 967 goto fail; 968 } 969 /* Dump existing printks when we register */ 970 if (nt->extended) { 971 extended = true; 972 netconsole_ext.flags |= CON_PRINTBUFFER; 973 } else { 974 netconsole.flags |= CON_PRINTBUFFER; 975 } 976 977 spin_lock_irqsave(&target_list_lock, flags); 978 list_add(&nt->list, &target_list); 979 spin_unlock_irqrestore(&target_list_lock, flags); 980 } 981 } 982 983 err = register_netdevice_notifier(&netconsole_netdev_notifier); 984 if (err) 985 goto fail; 986 987 err = dynamic_netconsole_init(); 988 if (err) 989 goto undonotifier; 990 991 if (extended) 992 register_console(&netconsole_ext); 993 register_console(&netconsole); 994 pr_info("network logging started\n"); 995 996 return err; 997 998 undonotifier: 999 unregister_netdevice_notifier(&netconsole_netdev_notifier); 1000 1001 fail: 1002 pr_err("cleaning up\n"); 1003 1004 /* 1005 * Remove all targets and destroy them (only targets created 1006 * from the boot/module option exist here). Skipping the list 1007 * lock is safe here, and netpoll_cleanup() will sleep. 1008 */ 1009 list_for_each_entry_safe(nt, tmp, &target_list, list) { 1010 list_del(&nt->list); 1011 free_param_target(nt); 1012 } 1013 1014 return err; 1015 } 1016 1017 static void __exit cleanup_netconsole(void) 1018 { 1019 struct netconsole_target *nt, *tmp; 1020 1021 if (console_is_registered(&netconsole_ext)) 1022 unregister_console(&netconsole_ext); 1023 unregister_console(&netconsole); 1024 dynamic_netconsole_exit(); 1025 unregister_netdevice_notifier(&netconsole_netdev_notifier); 1026 1027 /* 1028 * Targets created via configfs pin references on our module 1029 * and would first be rmdir(2)'ed from userspace. We reach 1030 * here only when they are already destroyed, and only those 1031 * created from the boot/module option are left, so remove and 1032 * destroy them. Skipping the list lock is safe here, and 1033 * netpoll_cleanup() will sleep. 1034 */ 1035 list_for_each_entry_safe(nt, tmp, &target_list, list) { 1036 list_del(&nt->list); 1037 free_param_target(nt); 1038 } 1039 } 1040 1041 /* 1042 * Use late_initcall to ensure netconsole is 1043 * initialized after network device driver if built-in. 1044 * 1045 * late_initcall() and module_init() are identical if built as module. 1046 */ 1047 late_initcall(init_netconsole); 1048 module_exit(cleanup_netconsole); 1049