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