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/u64_stats_sync.h>
40#include <linux/utsname.h>
41#include <linux/rtnetlink.h>
42
43MODULE_AUTHOR("Matt Mackall <mpm@selenic.com>");
44MODULE_DESCRIPTION("Console driver for network interfaces");
45MODULE_LICENSE("GPL");
46
47#define MAX_PARAM_LENGTH 256
48#define MAX_EXTRADATA_ENTRY_LEN 256
49#define MAX_EXTRADATA_VALUE_LEN 200
50/* The number 3 comes from userdata entry format characters (' ', '=', '\n') */
51#define MAX_EXTRADATA_NAME_LEN (MAX_EXTRADATA_ENTRY_LEN - \
52 MAX_EXTRADATA_VALUE_LEN - 3)
53#define MAX_EXTRADATA_ITEMS 16
54#define MAX_PRINT_CHUNK 1000
55
56static char config[MAX_PARAM_LENGTH];
57module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
58MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
59
60static bool oops_only;
61module_param(oops_only, bool, 0600);
62MODULE_PARM_DESC(oops_only, "Only log oops messages");
63
64#define NETCONSOLE_PARAM_TARGET_PREFIX "cmdline"
65
66#ifndef MODULE
67static int __init option_setup(char *opt)
68{
69 strscpy(config, opt, MAX_PARAM_LENGTH);
70 return 1;
71}
72__setup("netconsole=", option_setup);
73#endif /* MODULE */
74
75/* Linked list of all configured targets */
76static LIST_HEAD(target_list);
77/* target_cleanup_list is used to track targets that need to be cleaned outside
78 * of target_list_lock. It should be cleaned in the same function it is
79 * populated.
80 */
81static LIST_HEAD(target_cleanup_list);
82
83/* This needs to be a spinlock because write_msg() cannot sleep */
84static DEFINE_SPINLOCK(target_list_lock);
85/* This needs to be a mutex because netpoll_cleanup might sleep */
86static DEFINE_MUTEX(target_cleanup_list_lock);
87
88/*
89 * Console driver for netconsoles. Register only consoles that have
90 * an associated target of the same type.
91 */
92static struct console netconsole_ext, netconsole;
93
94struct netconsole_target_stats {
95 u64_stats_t xmit_drop_count;
96 u64_stats_t enomem_count;
97 struct u64_stats_sync syncp;
98};
99
100enum console_type {
101 CONS_BASIC = BIT(0),
102 CONS_EXTENDED = BIT(1),
103};
104
105/* Features enabled in sysdata. Contrary to userdata, this data is populated by
106 * the kernel. The fields are designed as bitwise flags, allowing multiple
107 * features to be set in sysdata_fields.
108 */
109enum sysdata_feature {
110 /* Populate the CPU that sends the message */
111 SYSDATA_CPU_NR = BIT(0),
112 /* Populate the task name (as in current->comm) in sysdata */
113 SYSDATA_TASKNAME = BIT(1),
114 /* Kernel release/version as part of sysdata */
115 SYSDATA_RELEASE = BIT(2),
116 /* Include a per-target message ID as part of sysdata */
117 SYSDATA_MSGID = BIT(3),
118};
119
120/**
121 * struct netconsole_target - Represents a configured netconsole target.
122 * @list: Links this target into the target_list.
123 * @group: Links us into the configfs subsystem hierarchy.
124 * @userdata_group: Links to the userdata configfs hierarchy
125 * @extradata_complete: Cached, formatted string of append
126 * @userdata_length: String length of usedata in extradata_complete.
127 * @sysdata_fields: Sysdata features enabled.
128 * @msgcounter: Message sent counter.
129 * @stats: Packet send stats for the target. Used for debugging.
130 * @enabled: On / off knob to enable / disable target.
131 * Visible from userspace (read-write).
132 * We maintain a strict 1:1 correspondence between this and
133 * whether the corresponding netpoll is active or inactive.
134 * Also, other parameters of a target may be modified at
135 * runtime only when it is disabled (enabled == 0).
136 * @extended: Denotes whether console is extended or not.
137 * @release: Denotes whether kernel release version should be prepended
138 * to the message. Depends on extended console.
139 * @np: The netpoll structure for this target.
140 * Contains the other userspace visible parameters:
141 * dev_name (read-write)
142 * local_port (read-write)
143 * remote_port (read-write)
144 * local_ip (read-write)
145 * remote_ip (read-write)
146 * local_mac (read-only)
147 * remote_mac (read-write)
148 * @buf: The buffer used to send the full msg to the network stack
149 */
150struct netconsole_target {
151 struct list_head list;
152#ifdef CONFIG_NETCONSOLE_DYNAMIC
153 struct config_group group;
154 struct config_group userdata_group;
155 char extradata_complete[MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS];
156 size_t userdata_length;
157 /* bit-wise with sysdata_feature bits */
158 u32 sysdata_fields;
159 /* protected by target_list_lock */
160 u32 msgcounter;
161#endif
162 struct netconsole_target_stats stats;
163 bool enabled;
164 bool extended;
165 bool release;
166 struct netpoll np;
167 /* protected by target_list_lock */
168 char buf[MAX_PRINT_CHUNK];
169};
170
171#ifdef CONFIG_NETCONSOLE_DYNAMIC
172
173static struct configfs_subsystem netconsole_subsys;
174static DEFINE_MUTEX(dynamic_netconsole_mutex);
175
176static int __init dynamic_netconsole_init(void)
177{
178 config_group_init(&netconsole_subsys.su_group);
179 mutex_init(&netconsole_subsys.su_mutex);
180 return configfs_register_subsystem(&netconsole_subsys);
181}
182
183static void __exit dynamic_netconsole_exit(void)
184{
185 configfs_unregister_subsystem(&netconsole_subsys);
186}
187
188/*
189 * Targets that were created by parsing the boot/module option string
190 * do not exist in the configfs hierarchy (and have NULL names) and will
191 * never go away, so make these a no-op for them.
192 */
193static void netconsole_target_get(struct netconsole_target *nt)
194{
195 if (config_item_name(&nt->group.cg_item))
196 config_group_get(&nt->group);
197}
198
199static void netconsole_target_put(struct netconsole_target *nt)
200{
201 if (config_item_name(&nt->group.cg_item))
202 config_group_put(&nt->group);
203}
204
205#else /* !CONFIG_NETCONSOLE_DYNAMIC */
206
207static int __init dynamic_netconsole_init(void)
208{
209 return 0;
210}
211
212static void __exit dynamic_netconsole_exit(void)
213{
214}
215
216/*
217 * No danger of targets going away from under us when dynamic
218 * reconfigurability is off.
219 */
220static void netconsole_target_get(struct netconsole_target *nt)
221{
222}
223
224static void netconsole_target_put(struct netconsole_target *nt)
225{
226}
227
228static void populate_configfs_item(struct netconsole_target *nt,
229 int cmdline_count)
230{
231}
232#endif /* CONFIG_NETCONSOLE_DYNAMIC */
233
234/* Allocate and initialize with defaults.
235 * Note that these targets get their config_item fields zeroed-out.
236 */
237static struct netconsole_target *alloc_and_init(void)
238{
239 struct netconsole_target *nt;
240
241 nt = kzalloc(sizeof(*nt), GFP_KERNEL);
242 if (!nt)
243 return nt;
244
245 if (IS_ENABLED(CONFIG_NETCONSOLE_EXTENDED_LOG))
246 nt->extended = true;
247 if (IS_ENABLED(CONFIG_NETCONSOLE_PREPEND_RELEASE))
248 nt->release = true;
249
250 nt->np.name = "netconsole";
251 strscpy(nt->np.dev_name, "eth0", IFNAMSIZ);
252 nt->np.local_port = 6665;
253 nt->np.remote_port = 6666;
254 eth_broadcast_addr(addr: nt->np.remote_mac);
255
256 return nt;
257}
258
259/* Clean up every target in the cleanup_list and move the clean targets back to
260 * the main target_list.
261 */
262static void netconsole_process_cleanups_core(void)
263{
264 struct netconsole_target *nt, *tmp;
265 unsigned long flags;
266
267 /* The cleanup needs RTNL locked */
268 ASSERT_RTNL();
269
270 mutex_lock(lock: &target_cleanup_list_lock);
271 list_for_each_entry_safe(nt, tmp, &target_cleanup_list, list) {
272 /* all entries in the cleanup_list needs to be disabled */
273 WARN_ON_ONCE(nt->enabled);
274 do_netpoll_cleanup(np: &nt->np);
275 /* moved the cleaned target to target_list. Need to hold both
276 * locks
277 */
278 spin_lock_irqsave(&target_list_lock, flags);
279 list_move(list: &nt->list, head: &target_list);
280 spin_unlock_irqrestore(lock: &target_list_lock, flags);
281 }
282 WARN_ON_ONCE(!list_empty(&target_cleanup_list));
283 mutex_unlock(lock: &target_cleanup_list_lock);
284}
285
286static void netconsole_print_banner(struct netpoll *np)
287{
288 np_info(np, "local port %d\n", np->local_port);
289 if (np->ipv6)
290 np_info(np, "local IPv6 address %pI6c\n", &np->local_ip.in6);
291 else
292 np_info(np, "local IPv4 address %pI4\n", &np->local_ip.ip);
293 np_info(np, "interface name '%s'\n", np->dev_name);
294 np_info(np, "local ethernet address '%pM'\n", np->dev_mac);
295 np_info(np, "remote port %d\n", np->remote_port);
296 if (np->ipv6)
297 np_info(np, "remote IPv6 address %pI6c\n", &np->remote_ip.in6);
298 else
299 np_info(np, "remote IPv4 address %pI4\n", &np->remote_ip.ip);
300 np_info(np, "remote ethernet address %pM\n", np->remote_mac);
301}
302
303/* Parse the string and populate the `inet_addr` union. Return 0 if IPv4 is
304 * populated, 1 if IPv6 is populated, and -1 upon failure.
305 */
306static int netpoll_parse_ip_addr(const char *str, union inet_addr *addr)
307{
308 const char *end = NULL;
309 int len;
310
311 len = strlen(str);
312 if (!len)
313 return -1;
314
315 if (str[len - 1] == '\n')
316 len -= 1;
317
318 if (in4_pton(src: str, srclen: len, dst: (void *)addr, delim: -1, end: &end) > 0 &&
319 (!end || *end == 0 || *end == '\n'))
320 return 0;
321
322 if (IS_ENABLED(CONFIG_IPV6) &&
323 in6_pton(src: str, srclen: len, dst: (void *)addr, delim: -1, end: &end) > 0 &&
324 (!end || *end == 0 || *end == '\n'))
325 return 1;
326
327 return -1;
328}
329
330#ifdef CONFIG_NETCONSOLE_DYNAMIC
331
332/*
333 * Our subsystem hierarchy is:
334 *
335 * /sys/kernel/config/netconsole/
336 * |
337 * <target>/
338 * | enabled
339 * | release
340 * | dev_name
341 * | local_port
342 * | remote_port
343 * | local_ip
344 * | remote_ip
345 * | local_mac
346 * | remote_mac
347 * | transmit_errors
348 * | userdata/
349 * | <key>/
350 * | value
351 * | ...
352 * |
353 * <target>/...
354 */
355
356static struct netconsole_target *to_target(struct config_item *item)
357{
358 struct config_group *cfg_group;
359
360 cfg_group = to_config_group(item);
361 if (!cfg_group)
362 return NULL;
363 return container_of(to_config_group(item),
364 struct netconsole_target, group);
365}
366
367/* Do the list cleanup with the rtnl lock hold. rtnl lock is necessary because
368 * netdev might be cleaned-up by calling __netpoll_cleanup(),
369 */
370static void netconsole_process_cleanups(void)
371{
372 /* rtnl lock is called here, because it has precedence over
373 * target_cleanup_list_lock mutex and target_cleanup_list
374 */
375 rtnl_lock();
376 netconsole_process_cleanups_core();
377 rtnl_unlock();
378}
379
380/* Get rid of possible trailing newline, returning the new length */
381static void trim_newline(char *s, size_t maxlen)
382{
383 size_t len;
384
385 len = strnlen(s, maxlen);
386 if (s[len - 1] == '\n')
387 s[len - 1] = '\0';
388}
389
390/*
391 * Attribute operations for netconsole_target.
392 */
393
394static ssize_t enabled_show(struct config_item *item, char *buf)
395{
396 return sysfs_emit(buf, "%d\n", to_target(item)->enabled);
397}
398
399static ssize_t extended_show(struct config_item *item, char *buf)
400{
401 return sysfs_emit(buf, "%d\n", to_target(item)->extended);
402}
403
404static ssize_t release_show(struct config_item *item, char *buf)
405{
406 return sysfs_emit(buf, "%d\n", to_target(item)->release);
407}
408
409static ssize_t dev_name_show(struct config_item *item, char *buf)
410{
411 return sysfs_emit(buf, "%s\n", to_target(item)->np.dev_name);
412}
413
414static ssize_t local_port_show(struct config_item *item, char *buf)
415{
416 return sysfs_emit(buf, "%d\n", to_target(item)->np.local_port);
417}
418
419static ssize_t remote_port_show(struct config_item *item, char *buf)
420{
421 return sysfs_emit(buf, "%d\n", to_target(item)->np.remote_port);
422}
423
424static ssize_t local_ip_show(struct config_item *item, char *buf)
425{
426 struct netconsole_target *nt = to_target(item);
427
428 if (nt->np.ipv6)
429 return sysfs_emit(buf, "%pI6c\n", &nt->np.local_ip.in6);
430 else
431 return sysfs_emit(buf, "%pI4\n", &nt->np.local_ip);
432}
433
434static ssize_t remote_ip_show(struct config_item *item, char *buf)
435{
436 struct netconsole_target *nt = to_target(item);
437
438 if (nt->np.ipv6)
439 return sysfs_emit(buf, "%pI6c\n", &nt->np.remote_ip.in6);
440 else
441 return sysfs_emit(buf, "%pI4\n", &nt->np.remote_ip);
442}
443
444static ssize_t local_mac_show(struct config_item *item, char *buf)
445{
446 struct net_device *dev = to_target(item)->np.dev;
447 static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
448
449 return sysfs_emit(buf, "%pM\n", dev ? dev->dev_addr : bcast);
450}
451
452static ssize_t remote_mac_show(struct config_item *item, char *buf)
453{
454 return sysfs_emit(buf, "%pM\n", to_target(item)->np.remote_mac);
455}
456
457static ssize_t transmit_errors_show(struct config_item *item, char *buf)
458{
459 struct netconsole_target *nt = to_target(item);
460 u64 xmit_drop_count, enomem_count;
461 unsigned int start;
462
463 do {
464 start = u64_stats_fetch_begin(&nt->stats.syncp);
465 xmit_drop_count = u64_stats_read(&nt->stats.xmit_drop_count);
466 enomem_count = u64_stats_read(&nt->stats.enomem_count);
467 } while (u64_stats_fetch_retry(&nt->stats.syncp, start));
468
469 return sysfs_emit(buf, "%llu\n", xmit_drop_count + enomem_count);
470}
471
472/* configfs helper to display if cpu_nr sysdata feature is enabled */
473static ssize_t sysdata_cpu_nr_enabled_show(struct config_item *item, char *buf)
474{
475 struct netconsole_target *nt = to_target(item->ci_parent);
476 bool cpu_nr_enabled;
477
478 mutex_lock(&dynamic_netconsole_mutex);
479 cpu_nr_enabled = !!(nt->sysdata_fields & SYSDATA_CPU_NR);
480 mutex_unlock(&dynamic_netconsole_mutex);
481
482 return sysfs_emit(buf, "%d\n", cpu_nr_enabled);
483}
484
485/* configfs helper to display if taskname sysdata feature is enabled */
486static ssize_t sysdata_taskname_enabled_show(struct config_item *item,
487 char *buf)
488{
489 struct netconsole_target *nt = to_target(item->ci_parent);
490 bool taskname_enabled;
491
492 mutex_lock(&dynamic_netconsole_mutex);
493 taskname_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
494 mutex_unlock(&dynamic_netconsole_mutex);
495
496 return sysfs_emit(buf, "%d\n", taskname_enabled);
497}
498
499static ssize_t sysdata_release_enabled_show(struct config_item *item,
500 char *buf)
501{
502 struct netconsole_target *nt = to_target(item->ci_parent);
503 bool release_enabled;
504
505 mutex_lock(&dynamic_netconsole_mutex);
506 release_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
507 mutex_unlock(&dynamic_netconsole_mutex);
508
509 return sysfs_emit(buf, "%d\n", release_enabled);
510}
511
512/* Iterate in the list of target, and make sure we don't have any console
513 * register without targets of the same type
514 */
515static void unregister_netcons_consoles(void)
516{
517 struct netconsole_target *nt;
518 u32 console_type_needed = 0;
519 unsigned long flags;
520
521 spin_lock_irqsave(&target_list_lock, flags);
522 list_for_each_entry(nt, &target_list, list) {
523 if (nt->extended)
524 console_type_needed |= CONS_EXTENDED;
525 else
526 console_type_needed |= CONS_BASIC;
527 }
528 spin_unlock_irqrestore(&target_list_lock, flags);
529
530 if (!(console_type_needed & CONS_EXTENDED) &&
531 console_is_registered(&netconsole_ext))
532 unregister_console(&netconsole_ext);
533
534 if (!(console_type_needed & CONS_BASIC) &&
535 console_is_registered(&netconsole))
536 unregister_console(&netconsole);
537}
538
539static ssize_t sysdata_msgid_enabled_show(struct config_item *item,
540 char *buf)
541{
542 struct netconsole_target *nt = to_target(item->ci_parent);
543 bool msgid_enabled;
544
545 mutex_lock(&dynamic_netconsole_mutex);
546 msgid_enabled = !!(nt->sysdata_fields & SYSDATA_MSGID);
547 mutex_unlock(&dynamic_netconsole_mutex);
548
549 return sysfs_emit(buf, "%d\n", msgid_enabled);
550}
551
552/*
553 * This one is special -- targets created through the configfs interface
554 * are not enabled (and the corresponding netpoll activated) by default.
555 * The user is expected to set the desired parameters first (which
556 * would enable him to dynamically add new netpoll targets for new
557 * network interfaces as and when they come up).
558 */
559static ssize_t enabled_store(struct config_item *item,
560 const char *buf, size_t count)
561{
562 struct netconsole_target *nt = to_target(item);
563 unsigned long flags;
564 bool enabled;
565 ssize_t ret;
566
567 mutex_lock(&dynamic_netconsole_mutex);
568 ret = kstrtobool(buf, &enabled);
569 if (ret)
570 goto out_unlock;
571
572 ret = -EINVAL;
573 if (enabled == nt->enabled) {
574 pr_info("network logging has already %s\n",
575 nt->enabled ? "started" : "stopped");
576 goto out_unlock;
577 }
578
579 if (enabled) { /* true */
580 if (nt->release && !nt->extended) {
581 pr_err("Not enabling netconsole. Release feature requires extended log message");
582 goto out_unlock;
583 }
584
585 if (nt->extended && !console_is_registered(&netconsole_ext)) {
586 netconsole_ext.flags |= CON_ENABLED;
587 register_console(&netconsole_ext);
588 }
589
590 /* User might be enabling the basic format target for the very
591 * first time, make sure the console is registered.
592 */
593 if (!nt->extended && !console_is_registered(&netconsole)) {
594 netconsole.flags |= CON_ENABLED;
595 register_console(&netconsole);
596 }
597
598 /*
599 * Skip netconsole_parser_cmdline() -- all the attributes are
600 * already configured via configfs. Just print them out.
601 */
602 netconsole_print_banner(&nt->np);
603
604 ret = netpoll_setup(&nt->np);
605 if (ret)
606 goto out_unlock;
607
608 nt->enabled = true;
609 pr_info("network logging started\n");
610 } else { /* false */
611 /* We need to disable the netconsole before cleaning it up
612 * otherwise we might end up in write_msg() with
613 * nt->np.dev == NULL and nt->enabled == true
614 */
615 mutex_lock(&target_cleanup_list_lock);
616 spin_lock_irqsave(&target_list_lock, flags);
617 nt->enabled = false;
618 /* Remove the target from the list, while holding
619 * target_list_lock
620 */
621 list_move(&nt->list, &target_cleanup_list);
622 spin_unlock_irqrestore(&target_list_lock, flags);
623 mutex_unlock(&target_cleanup_list_lock);
624 /* Unregister consoles, whose the last target of that type got
625 * disabled.
626 */
627 unregister_netcons_consoles();
628 }
629
630 ret = strnlen(buf, count);
631 /* Deferred cleanup */
632 netconsole_process_cleanups();
633out_unlock:
634 mutex_unlock(&dynamic_netconsole_mutex);
635 return ret;
636}
637
638static ssize_t release_store(struct config_item *item, const char *buf,
639 size_t count)
640{
641 struct netconsole_target *nt = to_target(item);
642 bool release;
643 ssize_t ret;
644
645 mutex_lock(&dynamic_netconsole_mutex);
646 if (nt->enabled) {
647 pr_err("target (%s) is enabled, disable to update parameters\n",
648 config_item_name(&nt->group.cg_item));
649 ret = -EINVAL;
650 goto out_unlock;
651 }
652
653 ret = kstrtobool(buf, &release);
654 if (ret)
655 goto out_unlock;
656
657 nt->release = release;
658
659 ret = strnlen(buf, count);
660out_unlock:
661 mutex_unlock(&dynamic_netconsole_mutex);
662 return ret;
663}
664
665static ssize_t extended_store(struct config_item *item, const char *buf,
666 size_t count)
667{
668 struct netconsole_target *nt = to_target(item);
669 bool extended;
670 ssize_t ret;
671
672 mutex_lock(&dynamic_netconsole_mutex);
673 if (nt->enabled) {
674 pr_err("target (%s) is enabled, disable to update parameters\n",
675 config_item_name(&nt->group.cg_item));
676 ret = -EINVAL;
677 goto out_unlock;
678 }
679
680 ret = kstrtobool(buf, &extended);
681 if (ret)
682 goto out_unlock;
683
684 nt->extended = extended;
685 ret = strnlen(buf, count);
686out_unlock:
687 mutex_unlock(&dynamic_netconsole_mutex);
688 return ret;
689}
690
691static ssize_t dev_name_store(struct config_item *item, const char *buf,
692 size_t count)
693{
694 struct netconsole_target *nt = to_target(item);
695
696 mutex_lock(&dynamic_netconsole_mutex);
697 if (nt->enabled) {
698 pr_err("target (%s) is enabled, disable to update parameters\n",
699 config_item_name(&nt->group.cg_item));
700 mutex_unlock(&dynamic_netconsole_mutex);
701 return -EINVAL;
702 }
703
704 strscpy(nt->np.dev_name, buf, IFNAMSIZ);
705 trim_newline(nt->np.dev_name, IFNAMSIZ);
706
707 mutex_unlock(&dynamic_netconsole_mutex);
708 return strnlen(buf, count);
709}
710
711static ssize_t local_port_store(struct config_item *item, const char *buf,
712 size_t count)
713{
714 struct netconsole_target *nt = to_target(item);
715 ssize_t ret = -EINVAL;
716
717 mutex_lock(&dynamic_netconsole_mutex);
718 if (nt->enabled) {
719 pr_err("target (%s) is enabled, disable to update parameters\n",
720 config_item_name(&nt->group.cg_item));
721 goto out_unlock;
722 }
723
724 ret = kstrtou16(buf, 10, &nt->np.local_port);
725 if (ret < 0)
726 goto out_unlock;
727 ret = strnlen(buf, count);
728out_unlock:
729 mutex_unlock(&dynamic_netconsole_mutex);
730 return ret;
731}
732
733static ssize_t remote_port_store(struct config_item *item,
734 const char *buf, size_t count)
735{
736 struct netconsole_target *nt = to_target(item);
737 ssize_t ret = -EINVAL;
738
739 mutex_lock(&dynamic_netconsole_mutex);
740 if (nt->enabled) {
741 pr_err("target (%s) is enabled, disable to update parameters\n",
742 config_item_name(&nt->group.cg_item));
743 goto out_unlock;
744 }
745
746 ret = kstrtou16(buf, 10, &nt->np.remote_port);
747 if (ret < 0)
748 goto out_unlock;
749 ret = strnlen(buf, count);
750out_unlock:
751 mutex_unlock(&dynamic_netconsole_mutex);
752 return ret;
753}
754
755static ssize_t local_ip_store(struct config_item *item, const char *buf,
756 size_t count)
757{
758 struct netconsole_target *nt = to_target(item);
759 ssize_t ret = -EINVAL;
760 int ipv6;
761
762 mutex_lock(&dynamic_netconsole_mutex);
763 if (nt->enabled) {
764 pr_err("target (%s) is enabled, disable to update parameters\n",
765 config_item_name(&nt->group.cg_item));
766 goto out_unlock;
767 }
768
769 ipv6 = netpoll_parse_ip_addr(buf, &nt->np.local_ip);
770 if (ipv6 == -1)
771 goto out_unlock;
772 nt->np.ipv6 = !!ipv6;
773
774 ret = strnlen(buf, count);
775out_unlock:
776 mutex_unlock(&dynamic_netconsole_mutex);
777 return ret;
778}
779
780static ssize_t remote_ip_store(struct config_item *item, const char *buf,
781 size_t count)
782{
783 struct netconsole_target *nt = to_target(item);
784 ssize_t ret = -EINVAL;
785 int ipv6;
786
787 mutex_lock(&dynamic_netconsole_mutex);
788 if (nt->enabled) {
789 pr_err("target (%s) is enabled, disable to update parameters\n",
790 config_item_name(&nt->group.cg_item));
791 goto out_unlock;
792 }
793
794 ipv6 = netpoll_parse_ip_addr(buf, &nt->np.remote_ip);
795 if (ipv6 == -1)
796 goto out_unlock;
797 nt->np.ipv6 = !!ipv6;
798
799 ret = strnlen(buf, count);
800out_unlock:
801 mutex_unlock(&dynamic_netconsole_mutex);
802 return ret;
803}
804
805/* Count number of entries we have in extradata.
806 * This is important because the extradata_complete only supports
807 * MAX_EXTRADATA_ITEMS entries. Before enabling any new {user,sys}data
808 * feature, number of entries needs to checked for available space.
809 */
810static size_t count_extradata_entries(struct netconsole_target *nt)
811{
812 size_t entries;
813
814 /* Userdata entries */
815 entries = list_count_nodes(&nt->userdata_group.cg_children);
816 /* Plus sysdata entries */
817 if (nt->sysdata_fields & SYSDATA_CPU_NR)
818 entries += 1;
819 if (nt->sysdata_fields & SYSDATA_TASKNAME)
820 entries += 1;
821 if (nt->sysdata_fields & SYSDATA_RELEASE)
822 entries += 1;
823 if (nt->sysdata_fields & SYSDATA_MSGID)
824 entries += 1;
825
826 return entries;
827}
828
829static ssize_t remote_mac_store(struct config_item *item, const char *buf,
830 size_t count)
831{
832 struct netconsole_target *nt = to_target(item);
833 u8 remote_mac[ETH_ALEN];
834 ssize_t ret = -EINVAL;
835
836 mutex_lock(&dynamic_netconsole_mutex);
837 if (nt->enabled) {
838 pr_err("target (%s) is enabled, disable to update parameters\n",
839 config_item_name(&nt->group.cg_item));
840 goto out_unlock;
841 }
842
843 if (!mac_pton(buf, remote_mac))
844 goto out_unlock;
845 if (buf[MAC_ADDR_STR_LEN] && buf[MAC_ADDR_STR_LEN] != '\n')
846 goto out_unlock;
847 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
848
849 ret = strnlen(buf, count);
850out_unlock:
851 mutex_unlock(&dynamic_netconsole_mutex);
852 return ret;
853}
854
855struct userdatum {
856 struct config_item item;
857 char value[MAX_EXTRADATA_VALUE_LEN];
858};
859
860static struct userdatum *to_userdatum(struct config_item *item)
861{
862 return container_of(item, struct userdatum, item);
863}
864
865struct userdata {
866 struct config_group group;
867};
868
869static struct userdata *to_userdata(struct config_item *item)
870{
871 return container_of(to_config_group(item), struct userdata, group);
872}
873
874static struct netconsole_target *userdata_to_target(struct userdata *ud)
875{
876 struct config_group *netconsole_group;
877
878 netconsole_group = to_config_group(ud->group.cg_item.ci_parent);
879 return to_target(&netconsole_group->cg_item);
880}
881
882static ssize_t userdatum_value_show(struct config_item *item, char *buf)
883{
884 return sysfs_emit(buf, "%s\n", &(to_userdatum(item)->value[0]));
885}
886
887static void update_userdata(struct netconsole_target *nt)
888{
889 int complete_idx = 0, child_count = 0;
890 struct list_head *entry;
891
892 /* Clear the current string in case the last userdatum was deleted */
893 nt->userdata_length = 0;
894 nt->extradata_complete[0] = 0;
895
896 list_for_each(entry, &nt->userdata_group.cg_children) {
897 struct userdatum *udm_item;
898 struct config_item *item;
899
900 if (WARN_ON_ONCE(child_count >= MAX_EXTRADATA_ITEMS))
901 break;
902 child_count++;
903
904 item = container_of(entry, struct config_item, ci_entry);
905 udm_item = to_userdatum(item);
906
907 /* Skip userdata with no value set */
908 if (strnlen(udm_item->value, MAX_EXTRADATA_VALUE_LEN) == 0)
909 continue;
910
911 /* This doesn't overflow extradata_complete since it will write
912 * one entry length (1/MAX_EXTRADATA_ITEMS long), entry count is
913 * checked to not exceed MAX items with child_count above
914 */
915 complete_idx += scnprintf(&nt->extradata_complete[complete_idx],
916 MAX_EXTRADATA_ENTRY_LEN, " %s=%s\n",
917 item->ci_name, udm_item->value);
918 }
919 nt->userdata_length = strnlen(nt->extradata_complete,
920 sizeof(nt->extradata_complete));
921}
922
923static ssize_t userdatum_value_store(struct config_item *item, const char *buf,
924 size_t count)
925{
926 struct userdatum *udm = to_userdatum(item);
927 struct netconsole_target *nt;
928 struct userdata *ud;
929 ssize_t ret;
930
931 if (count > MAX_EXTRADATA_VALUE_LEN)
932 return -EMSGSIZE;
933
934 mutex_lock(&dynamic_netconsole_mutex);
935
936 ret = strscpy(udm->value, buf, sizeof(udm->value));
937 if (ret < 0)
938 goto out_unlock;
939 trim_newline(udm->value, sizeof(udm->value));
940
941 ud = to_userdata(item->ci_parent);
942 nt = userdata_to_target(ud);
943 update_userdata(nt);
944 ret = count;
945out_unlock:
946 mutex_unlock(&dynamic_netconsole_mutex);
947 return ret;
948}
949
950/* disable_sysdata_feature - Disable sysdata feature and clean sysdata
951 * @nt: target that is disabling the feature
952 * @feature: feature being disabled
953 */
954static void disable_sysdata_feature(struct netconsole_target *nt,
955 enum sysdata_feature feature)
956{
957 nt->sysdata_fields &= ~feature;
958 nt->extradata_complete[nt->userdata_length] = 0;
959}
960
961static ssize_t sysdata_msgid_enabled_store(struct config_item *item,
962 const char *buf, size_t count)
963{
964 struct netconsole_target *nt = to_target(item->ci_parent);
965 bool msgid_enabled, curr;
966 ssize_t ret;
967
968 ret = kstrtobool(buf, &msgid_enabled);
969 if (ret)
970 return ret;
971
972 mutex_lock(&dynamic_netconsole_mutex);
973 curr = !!(nt->sysdata_fields & SYSDATA_MSGID);
974 if (msgid_enabled == curr)
975 goto unlock_ok;
976
977 if (msgid_enabled &&
978 count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) {
979 ret = -ENOSPC;
980 goto unlock;
981 }
982
983 if (msgid_enabled)
984 nt->sysdata_fields |= SYSDATA_MSGID;
985 else
986 disable_sysdata_feature(nt, SYSDATA_MSGID);
987
988unlock_ok:
989 ret = strnlen(buf, count);
990unlock:
991 mutex_unlock(&dynamic_netconsole_mutex);
992 return ret;
993}
994
995static ssize_t sysdata_release_enabled_store(struct config_item *item,
996 const char *buf, size_t count)
997{
998 struct netconsole_target *nt = to_target(item->ci_parent);
999 bool release_enabled, curr;
1000 ssize_t ret;
1001
1002 ret = kstrtobool(buf, &release_enabled);
1003 if (ret)
1004 return ret;
1005
1006 mutex_lock(&dynamic_netconsole_mutex);
1007 curr = !!(nt->sysdata_fields & SYSDATA_RELEASE);
1008 if (release_enabled == curr)
1009 goto unlock_ok;
1010
1011 if (release_enabled &&
1012 count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) {
1013 ret = -ENOSPC;
1014 goto unlock;
1015 }
1016
1017 if (release_enabled)
1018 nt->sysdata_fields |= SYSDATA_RELEASE;
1019 else
1020 disable_sysdata_feature(nt, SYSDATA_RELEASE);
1021
1022unlock_ok:
1023 ret = strnlen(buf, count);
1024unlock:
1025 mutex_unlock(&dynamic_netconsole_mutex);
1026 return ret;
1027}
1028
1029static ssize_t sysdata_taskname_enabled_store(struct config_item *item,
1030 const char *buf, size_t count)
1031{
1032 struct netconsole_target *nt = to_target(item->ci_parent);
1033 bool taskname_enabled, curr;
1034 ssize_t ret;
1035
1036 ret = kstrtobool(buf, &taskname_enabled);
1037 if (ret)
1038 return ret;
1039
1040 mutex_lock(&dynamic_netconsole_mutex);
1041 curr = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
1042 if (taskname_enabled == curr)
1043 goto unlock_ok;
1044
1045 if (taskname_enabled &&
1046 count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) {
1047 ret = -ENOSPC;
1048 goto unlock;
1049 }
1050
1051 if (taskname_enabled)
1052 nt->sysdata_fields |= SYSDATA_TASKNAME;
1053 else
1054 disable_sysdata_feature(nt, SYSDATA_TASKNAME);
1055
1056unlock_ok:
1057 ret = strnlen(buf, count);
1058unlock:
1059 mutex_unlock(&dynamic_netconsole_mutex);
1060 return ret;
1061}
1062
1063/* configfs helper to sysdata cpu_nr feature */
1064static ssize_t sysdata_cpu_nr_enabled_store(struct config_item *item,
1065 const char *buf, size_t count)
1066{
1067 struct netconsole_target *nt = to_target(item->ci_parent);
1068 bool cpu_nr_enabled, curr;
1069 ssize_t ret;
1070
1071 ret = kstrtobool(buf, &cpu_nr_enabled);
1072 if (ret)
1073 return ret;
1074
1075 mutex_lock(&dynamic_netconsole_mutex);
1076 curr = !!(nt->sysdata_fields & SYSDATA_CPU_NR);
1077 if (cpu_nr_enabled == curr)
1078 /* no change requested */
1079 goto unlock_ok;
1080
1081 if (cpu_nr_enabled &&
1082 count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) {
1083 /* user wants the new feature, but there is no space in the
1084 * buffer.
1085 */
1086 ret = -ENOSPC;
1087 goto unlock;
1088 }
1089
1090 if (cpu_nr_enabled)
1091 nt->sysdata_fields |= SYSDATA_CPU_NR;
1092 else
1093 /* This is special because extradata_complete might have
1094 * remaining data from previous sysdata, and it needs to be
1095 * cleaned.
1096 */
1097 disable_sysdata_feature(nt, SYSDATA_CPU_NR);
1098
1099unlock_ok:
1100 ret = strnlen(buf, count);
1101unlock:
1102 mutex_unlock(&dynamic_netconsole_mutex);
1103 return ret;
1104}
1105
1106CONFIGFS_ATTR(userdatum_, value);
1107CONFIGFS_ATTR(sysdata_, cpu_nr_enabled);
1108CONFIGFS_ATTR(sysdata_, taskname_enabled);
1109CONFIGFS_ATTR(sysdata_, release_enabled);
1110CONFIGFS_ATTR(sysdata_, msgid_enabled);
1111
1112static struct configfs_attribute *userdatum_attrs[] = {
1113 &userdatum_attr_value,
1114 NULL,
1115};
1116
1117static void userdatum_release(struct config_item *item)
1118{
1119 kfree(to_userdatum(item));
1120}
1121
1122static struct configfs_item_operations userdatum_ops = {
1123 .release = userdatum_release,
1124};
1125
1126static const struct config_item_type userdatum_type = {
1127 .ct_item_ops = &userdatum_ops,
1128 .ct_attrs = userdatum_attrs,
1129 .ct_owner = THIS_MODULE,
1130};
1131
1132static struct config_item *userdatum_make_item(struct config_group *group,
1133 const char *name)
1134{
1135 struct netconsole_target *nt;
1136 struct userdatum *udm;
1137 struct userdata *ud;
1138
1139 if (strlen(name) > MAX_EXTRADATA_NAME_LEN)
1140 return ERR_PTR(-ENAMETOOLONG);
1141
1142 ud = to_userdata(&group->cg_item);
1143 nt = userdata_to_target(ud);
1144 if (count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS)
1145 return ERR_PTR(-ENOSPC);
1146
1147 udm = kzalloc(sizeof(*udm), GFP_KERNEL);
1148 if (!udm)
1149 return ERR_PTR(-ENOMEM);
1150
1151 config_item_init_type_name(&udm->item, name, &userdatum_type);
1152 return &udm->item;
1153}
1154
1155static void userdatum_drop(struct config_group *group, struct config_item *item)
1156{
1157 struct netconsole_target *nt;
1158 struct userdata *ud;
1159
1160 ud = to_userdata(&group->cg_item);
1161 nt = userdata_to_target(ud);
1162
1163 mutex_lock(&dynamic_netconsole_mutex);
1164 update_userdata(nt);
1165 config_item_put(item);
1166 mutex_unlock(&dynamic_netconsole_mutex);
1167}
1168
1169static struct configfs_attribute *userdata_attrs[] = {
1170 &sysdata_attr_cpu_nr_enabled,
1171 &sysdata_attr_taskname_enabled,
1172 &sysdata_attr_release_enabled,
1173 &sysdata_attr_msgid_enabled,
1174 NULL,
1175};
1176
1177static struct configfs_group_operations userdata_ops = {
1178 .make_item = userdatum_make_item,
1179 .drop_item = userdatum_drop,
1180};
1181
1182static const struct config_item_type userdata_type = {
1183 .ct_item_ops = &userdatum_ops,
1184 .ct_group_ops = &userdata_ops,
1185 .ct_attrs = userdata_attrs,
1186 .ct_owner = THIS_MODULE,
1187};
1188
1189CONFIGFS_ATTR(, enabled);
1190CONFIGFS_ATTR(, extended);
1191CONFIGFS_ATTR(, dev_name);
1192CONFIGFS_ATTR(, local_port);
1193CONFIGFS_ATTR(, remote_port);
1194CONFIGFS_ATTR(, local_ip);
1195CONFIGFS_ATTR(, remote_ip);
1196CONFIGFS_ATTR_RO(, local_mac);
1197CONFIGFS_ATTR(, remote_mac);
1198CONFIGFS_ATTR(, release);
1199CONFIGFS_ATTR_RO(, transmit_errors);
1200
1201static struct configfs_attribute *netconsole_target_attrs[] = {
1202 &attr_enabled,
1203 &attr_extended,
1204 &attr_release,
1205 &attr_dev_name,
1206 &attr_local_port,
1207 &attr_remote_port,
1208 &attr_local_ip,
1209 &attr_remote_ip,
1210 &attr_local_mac,
1211 &attr_remote_mac,
1212 &attr_transmit_errors,
1213 NULL,
1214};
1215
1216/*
1217 * Item operations and type for netconsole_target.
1218 */
1219
1220static void netconsole_target_release(struct config_item *item)
1221{
1222 kfree(to_target(item));
1223}
1224
1225static struct configfs_item_operations netconsole_target_item_ops = {
1226 .release = netconsole_target_release,
1227};
1228
1229static const struct config_item_type netconsole_target_type = {
1230 .ct_attrs = netconsole_target_attrs,
1231 .ct_item_ops = &netconsole_target_item_ops,
1232 .ct_owner = THIS_MODULE,
1233};
1234
1235static void init_target_config_group(struct netconsole_target *nt,
1236 const char *name)
1237{
1238 config_group_init_type_name(&nt->group, name, &netconsole_target_type);
1239 config_group_init_type_name(&nt->userdata_group, "userdata",
1240 &userdata_type);
1241 configfs_add_default_group(&nt->userdata_group, &nt->group);
1242}
1243
1244static struct netconsole_target *find_cmdline_target(const char *name)
1245{
1246 struct netconsole_target *nt, *ret = NULL;
1247 unsigned long flags;
1248
1249 spin_lock_irqsave(&target_list_lock, flags);
1250 list_for_each_entry(nt, &target_list, list) {
1251 if (!strcmp(nt->group.cg_item.ci_name, name)) {
1252 ret = nt;
1253 break;
1254 }
1255 }
1256 spin_unlock_irqrestore(&target_list_lock, flags);
1257
1258 return ret;
1259}
1260
1261/*
1262 * Group operations and type for netconsole_subsys.
1263 */
1264
1265static struct config_group *make_netconsole_target(struct config_group *group,
1266 const char *name)
1267{
1268 struct netconsole_target *nt;
1269 unsigned long flags;
1270
1271 /* Checking if a target by this name was created at boot time. If so,
1272 * attach a configfs entry to that target. This enables dynamic
1273 * control.
1274 */
1275 if (!strncmp(name, NETCONSOLE_PARAM_TARGET_PREFIX,
1276 strlen(NETCONSOLE_PARAM_TARGET_PREFIX))) {
1277 nt = find_cmdline_target(name);
1278 if (nt) {
1279 init_target_config_group(nt, name);
1280 return &nt->group;
1281 }
1282 }
1283
1284 nt = alloc_and_init();
1285 if (!nt)
1286 return ERR_PTR(-ENOMEM);
1287
1288 /* Initialize the config_group member */
1289 init_target_config_group(nt, name);
1290
1291 /* Adding, but it is disabled */
1292 spin_lock_irqsave(&target_list_lock, flags);
1293 list_add(&nt->list, &target_list);
1294 spin_unlock_irqrestore(&target_list_lock, flags);
1295
1296 return &nt->group;
1297}
1298
1299static void drop_netconsole_target(struct config_group *group,
1300 struct config_item *item)
1301{
1302 unsigned long flags;
1303 struct netconsole_target *nt = to_target(item);
1304
1305 spin_lock_irqsave(&target_list_lock, flags);
1306 list_del(&nt->list);
1307 spin_unlock_irqrestore(&target_list_lock, flags);
1308
1309 /*
1310 * The target may have never been enabled, or was manually disabled
1311 * before being removed so netpoll may have already been cleaned up.
1312 */
1313 if (nt->enabled)
1314 netpoll_cleanup(&nt->np);
1315
1316 config_item_put(&nt->group.cg_item);
1317}
1318
1319static struct configfs_group_operations netconsole_subsys_group_ops = {
1320 .make_group = make_netconsole_target,
1321 .drop_item = drop_netconsole_target,
1322};
1323
1324static const struct config_item_type netconsole_subsys_type = {
1325 .ct_group_ops = &netconsole_subsys_group_ops,
1326 .ct_owner = THIS_MODULE,
1327};
1328
1329/* The netconsole configfs subsystem */
1330static struct configfs_subsystem netconsole_subsys = {
1331 .su_group = {
1332 .cg_item = {
1333 .ci_namebuf = "netconsole",
1334 .ci_type = &netconsole_subsys_type,
1335 },
1336 },
1337};
1338
1339static void populate_configfs_item(struct netconsole_target *nt,
1340 int cmdline_count)
1341{
1342 char target_name[16];
1343
1344 snprintf(target_name, sizeof(target_name), "%s%d",
1345 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
1346 init_target_config_group(nt, target_name);
1347}
1348
1349static int sysdata_append_cpu_nr(struct netconsole_target *nt, int offset)
1350{
1351 /* Append cpu=%d at extradata_complete after userdata str */
1352 return scnprintf(&nt->extradata_complete[offset],
1353 MAX_EXTRADATA_ENTRY_LEN, " cpu=%u\n",
1354 raw_smp_processor_id());
1355}
1356
1357static int sysdata_append_taskname(struct netconsole_target *nt, int offset)
1358{
1359 return scnprintf(&nt->extradata_complete[offset],
1360 MAX_EXTRADATA_ENTRY_LEN, " taskname=%s\n",
1361 current->comm);
1362}
1363
1364static int sysdata_append_release(struct netconsole_target *nt, int offset)
1365{
1366 return scnprintf(&nt->extradata_complete[offset],
1367 MAX_EXTRADATA_ENTRY_LEN, " release=%s\n",
1368 init_utsname()->release);
1369}
1370
1371static int sysdata_append_msgid(struct netconsole_target *nt, int offset)
1372{
1373 wrapping_assign_add(nt->msgcounter, 1);
1374 return scnprintf(&nt->extradata_complete[offset],
1375 MAX_EXTRADATA_ENTRY_LEN, " msgid=%u\n",
1376 nt->msgcounter);
1377}
1378
1379/*
1380 * prepare_extradata - append sysdata at extradata_complete in runtime
1381 * @nt: target to send message to
1382 */
1383static int prepare_extradata(struct netconsole_target *nt)
1384{
1385 int extradata_len;
1386
1387 /* userdata was appended when configfs write helper was called
1388 * by update_userdata().
1389 */
1390 extradata_len = nt->userdata_length;
1391
1392 if (!nt->sysdata_fields)
1393 goto out;
1394
1395 if (nt->sysdata_fields & SYSDATA_CPU_NR)
1396 extradata_len += sysdata_append_cpu_nr(nt, extradata_len);
1397 if (nt->sysdata_fields & SYSDATA_TASKNAME)
1398 extradata_len += sysdata_append_taskname(nt, extradata_len);
1399 if (nt->sysdata_fields & SYSDATA_RELEASE)
1400 extradata_len += sysdata_append_release(nt, extradata_len);
1401 if (nt->sysdata_fields & SYSDATA_MSGID)
1402 extradata_len += sysdata_append_msgid(nt, extradata_len);
1403
1404 WARN_ON_ONCE(extradata_len >
1405 MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS);
1406
1407out:
1408 return extradata_len;
1409}
1410#else /* CONFIG_NETCONSOLE_DYNAMIC not set */
1411static int prepare_extradata(struct netconsole_target *nt)
1412{
1413 return 0;
1414}
1415#endif /* CONFIG_NETCONSOLE_DYNAMIC */
1416
1417/* Handle network interface device notifications */
1418static int netconsole_netdev_event(struct notifier_block *this,
1419 unsigned long event, void *ptr)
1420{
1421 unsigned long flags;
1422 struct netconsole_target *nt, *tmp;
1423 struct net_device *dev = netdev_notifier_info_to_dev(info: ptr);
1424 bool stopped = false;
1425
1426 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
1427 event == NETDEV_RELEASE || event == NETDEV_JOIN))
1428 goto done;
1429
1430 mutex_lock(lock: &target_cleanup_list_lock);
1431 spin_lock_irqsave(&target_list_lock, flags);
1432 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1433 netconsole_target_get(nt);
1434 if (nt->np.dev == dev) {
1435 switch (event) {
1436 case NETDEV_CHANGENAME:
1437 strscpy(nt->np.dev_name, dev->name, IFNAMSIZ);
1438 break;
1439 case NETDEV_RELEASE:
1440 case NETDEV_JOIN:
1441 case NETDEV_UNREGISTER:
1442 nt->enabled = false;
1443 list_move(list: &nt->list, head: &target_cleanup_list);
1444 stopped = true;
1445 }
1446 }
1447 netconsole_target_put(nt);
1448 }
1449 spin_unlock_irqrestore(lock: &target_list_lock, flags);
1450 mutex_unlock(lock: &target_cleanup_list_lock);
1451
1452 if (stopped) {
1453 const char *msg = "had an event";
1454
1455 switch (event) {
1456 case NETDEV_UNREGISTER:
1457 msg = "unregistered";
1458 break;
1459 case NETDEV_RELEASE:
1460 msg = "released slaves";
1461 break;
1462 case NETDEV_JOIN:
1463 msg = "is joining a master device";
1464 break;
1465 }
1466 pr_info("network logging stopped on interface %s as it %s\n",
1467 dev->name, msg);
1468 }
1469
1470 /* Process target_cleanup_list entries. By the end, target_cleanup_list
1471 * should be empty
1472 */
1473 netconsole_process_cleanups_core();
1474
1475done:
1476 return NOTIFY_DONE;
1477}
1478
1479static struct notifier_block netconsole_netdev_notifier = {
1480 .notifier_call = netconsole_netdev_event,
1481};
1482
1483/**
1484 * send_udp - Wrapper for netpoll_send_udp that counts errors
1485 * @nt: target to send message to
1486 * @msg: message to send
1487 * @len: length of message
1488 *
1489 * Calls netpoll_send_udp and classifies the return value. If an error
1490 * occurred it increments statistics in nt->stats accordingly.
1491 * Only calls netpoll_send_udp if CONFIG_NETCONSOLE_DYNAMIC is disabled.
1492 */
1493static void send_udp(struct netconsole_target *nt, const char *msg, int len)
1494{
1495 int result = netpoll_send_udp(np: &nt->np, msg, len);
1496
1497 if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC)) {
1498 if (result == NET_XMIT_DROP) {
1499 u64_stats_update_begin(syncp: &nt->stats.syncp);
1500 u64_stats_inc(p: &nt->stats.xmit_drop_count);
1501 u64_stats_update_end(syncp: &nt->stats.syncp);
1502 } else if (result == -ENOMEM) {
1503 u64_stats_update_begin(syncp: &nt->stats.syncp);
1504 u64_stats_inc(p: &nt->stats.enomem_count);
1505 u64_stats_update_end(syncp: &nt->stats.syncp);
1506 }
1507 }
1508}
1509
1510static void send_msg_no_fragmentation(struct netconsole_target *nt,
1511 const char *msg,
1512 int msg_len,
1513 int release_len)
1514{
1515 const char *extradata = NULL;
1516 const char *release;
1517
1518#ifdef CONFIG_NETCONSOLE_DYNAMIC
1519 extradata = nt->extradata_complete;
1520#endif
1521
1522 if (release_len) {
1523 release = init_utsname()->release;
1524
1525 scnprintf(buf: nt->buf, MAX_PRINT_CHUNK, fmt: "%s,%s", release, msg);
1526 msg_len += release_len;
1527 } else {
1528 memcpy(to: nt->buf, from: msg, len: msg_len);
1529 }
1530
1531 if (extradata)
1532 msg_len += scnprintf(buf: &nt->buf[msg_len],
1533 MAX_PRINT_CHUNK - msg_len,
1534 fmt: "%s", extradata);
1535
1536 send_udp(nt, msg: nt->buf, len: msg_len);
1537}
1538
1539static void append_release(char *buf)
1540{
1541 const char *release;
1542
1543 release = init_utsname()->release;
1544 scnprintf(buf, MAX_PRINT_CHUNK, fmt: "%s,", release);
1545}
1546
1547static void send_fragmented_body(struct netconsole_target *nt,
1548 const char *msgbody, int header_len,
1549 int msgbody_len, int extradata_len)
1550{
1551 int sent_extradata, preceding_bytes;
1552 const char *extradata = NULL;
1553 int body_len, offset = 0;
1554
1555#ifdef CONFIG_NETCONSOLE_DYNAMIC
1556 extradata = nt->extradata_complete;
1557#endif
1558
1559 /* body_len represents the number of bytes that will be sent. This is
1560 * bigger than MAX_PRINT_CHUNK, thus, it will be split in multiple
1561 * packets
1562 */
1563 body_len = msgbody_len + extradata_len;
1564
1565 /* In each iteration of the while loop below, we send a packet
1566 * containing the header and a portion of the body. The body is
1567 * composed of two parts: msgbody and extradata. We keep track of how
1568 * many bytes have been sent so far using the offset variable, which
1569 * ranges from 0 to the total length of the body.
1570 */
1571 while (offset < body_len) {
1572 int this_header = header_len;
1573 bool msgbody_written = false;
1574 int this_offset = 0;
1575 int this_chunk = 0;
1576
1577 this_header += scnprintf(buf: nt->buf + this_header,
1578 MAX_PRINT_CHUNK - this_header,
1579 fmt: ",ncfrag=%d/%d;", offset,
1580 body_len);
1581
1582 /* Not all msgbody data has been written yet */
1583 if (offset < msgbody_len) {
1584 this_chunk = min(msgbody_len - offset,
1585 MAX_PRINT_CHUNK - this_header);
1586 if (WARN_ON_ONCE(this_chunk <= 0))
1587 return;
1588 memcpy(to: nt->buf + this_header, from: msgbody + offset,
1589 len: this_chunk);
1590 this_offset += this_chunk;
1591 }
1592
1593 /* msgbody was finally written, either in the previous
1594 * messages and/or in the current buf. Time to write
1595 * the extradata.
1596 */
1597 msgbody_written |= offset + this_offset >= msgbody_len;
1598
1599 /* Msg body is fully written and there is pending extradata to
1600 * write, append extradata in this chunk
1601 */
1602 if (msgbody_written && offset + this_offset < body_len) {
1603 /* Track how much user data was already sent. First
1604 * time here, sent_userdata is zero
1605 */
1606 sent_extradata = (offset + this_offset) - msgbody_len;
1607 /* offset of bytes used in current buf */
1608 preceding_bytes = this_chunk + this_header;
1609
1610 if (WARN_ON_ONCE(sent_extradata < 0))
1611 return;
1612
1613 this_chunk = min(extradata_len - sent_extradata,
1614 MAX_PRINT_CHUNK - preceding_bytes);
1615 if (WARN_ON_ONCE(this_chunk < 0))
1616 /* this_chunk could be zero if all the previous
1617 * message used all the buffer. This is not a
1618 * problem, extradata will be sent in the next
1619 * iteration
1620 */
1621 return;
1622
1623 memcpy(to: nt->buf + this_header + this_offset,
1624 from: extradata + sent_extradata,
1625 len: this_chunk);
1626 this_offset += this_chunk;
1627 }
1628
1629 send_udp(nt, msg: nt->buf, len: this_header + this_offset);
1630 offset += this_offset;
1631 }
1632}
1633
1634static void send_msg_fragmented(struct netconsole_target *nt,
1635 const char *msg,
1636 int msg_len,
1637 int release_len,
1638 int extradata_len)
1639{
1640 int header_len, msgbody_len;
1641 const char *msgbody;
1642
1643 /* need to insert extra header fields, detect header and msgbody */
1644 msgbody = memchr(msg, ';', msg_len);
1645 if (WARN_ON_ONCE(!msgbody))
1646 return;
1647
1648 header_len = msgbody - msg;
1649 msgbody_len = msg_len - header_len - 1;
1650 msgbody++;
1651
1652 /*
1653 * Transfer multiple chunks with the following extra header.
1654 * "ncfrag=<byte-offset>/<total-bytes>"
1655 */
1656 if (release_len)
1657 append_release(buf: nt->buf);
1658
1659 /* Copy the header into the buffer */
1660 memcpy(to: nt->buf + release_len, from: msg, len: header_len);
1661 header_len += release_len;
1662
1663 /* for now on, the header will be persisted, and the msgbody
1664 * will be replaced
1665 */
1666 send_fragmented_body(nt, msgbody, header_len, msgbody_len,
1667 extradata_len);
1668}
1669
1670/**
1671 * send_ext_msg_udp - send extended log message to target
1672 * @nt: target to send message to
1673 * @msg: extended log message to send
1674 * @msg_len: length of message
1675 *
1676 * Transfer extended log @msg to @nt. If @msg is longer than
1677 * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with
1678 * ncfrag header field added to identify them.
1679 */
1680static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
1681 int msg_len)
1682{
1683 int release_len = 0;
1684 int extradata_len;
1685
1686 extradata_len = prepare_extradata(nt);
1687
1688 if (nt->release)
1689 release_len = strlen(init_utsname()->release) + 1;
1690
1691 if (msg_len + release_len + extradata_len <= MAX_PRINT_CHUNK)
1692 return send_msg_no_fragmentation(nt, msg, msg_len, release_len);
1693
1694 return send_msg_fragmented(nt, msg, msg_len, release_len,
1695 extradata_len);
1696}
1697
1698static void write_ext_msg(struct console *con, const char *msg,
1699 unsigned int len)
1700{
1701 struct netconsole_target *nt;
1702 unsigned long flags;
1703
1704 if ((oops_only && !oops_in_progress) || list_empty(head: &target_list))
1705 return;
1706
1707 spin_lock_irqsave(&target_list_lock, flags);
1708 list_for_each_entry(nt, &target_list, list)
1709 if (nt->extended && nt->enabled && netif_running(dev: nt->np.dev))
1710 send_ext_msg_udp(nt, msg, msg_len: len);
1711 spin_unlock_irqrestore(lock: &target_list_lock, flags);
1712}
1713
1714static void write_msg(struct console *con, const char *msg, unsigned int len)
1715{
1716 int frag, left;
1717 unsigned long flags;
1718 struct netconsole_target *nt;
1719 const char *tmp;
1720
1721 if (oops_only && !oops_in_progress)
1722 return;
1723 /* Avoid taking lock and disabling interrupts unnecessarily */
1724 if (list_empty(head: &target_list))
1725 return;
1726
1727 spin_lock_irqsave(&target_list_lock, flags);
1728 list_for_each_entry(nt, &target_list, list) {
1729 if (!nt->extended && nt->enabled && netif_running(dev: nt->np.dev)) {
1730 /*
1731 * We nest this inside the for-each-target loop above
1732 * so that we're able to get as much logging out to
1733 * at least one target if we die inside here, instead
1734 * of unnecessarily keeping all targets in lock-step.
1735 */
1736 tmp = msg;
1737 for (left = len; left;) {
1738 frag = min(left, MAX_PRINT_CHUNK);
1739 send_udp(nt, msg: tmp, len: frag);
1740 tmp += frag;
1741 left -= frag;
1742 }
1743 }
1744 }
1745 spin_unlock_irqrestore(lock: &target_list_lock, flags);
1746}
1747
1748static int netconsole_parser_cmdline(struct netpoll *np, char *opt)
1749{
1750 bool ipversion_set = false;
1751 char *cur = opt;
1752 char *delim;
1753 int ipv6;
1754
1755 if (*cur != '@') {
1756 delim = strchr(cur, '@');
1757 if (!delim)
1758 goto parse_failed;
1759 *delim = 0;
1760 if (kstrtou16(s: cur, base: 10, res: &np->local_port))
1761 goto parse_failed;
1762 cur = delim;
1763 }
1764 cur++;
1765
1766 if (*cur != '/') {
1767 ipversion_set = true;
1768 delim = strchr(cur, '/');
1769 if (!delim)
1770 goto parse_failed;
1771 *delim = 0;
1772 ipv6 = netpoll_parse_ip_addr(str: cur, addr: &np->local_ip);
1773 if (ipv6 < 0)
1774 goto parse_failed;
1775 else
1776 np->ipv6 = (bool)ipv6;
1777 cur = delim;
1778 }
1779 cur++;
1780
1781 if (*cur != ',') {
1782 /* parse out dev_name or dev_mac */
1783 delim = strchr(cur, ',');
1784 if (!delim)
1785 goto parse_failed;
1786 *delim = 0;
1787
1788 np->dev_name[0] = '\0';
1789 eth_broadcast_addr(addr: np->dev_mac);
1790 if (!strchr(cur, ':'))
1791 strscpy(np->dev_name, cur, sizeof(np->dev_name));
1792 else if (!mac_pton(s: cur, mac: np->dev_mac))
1793 goto parse_failed;
1794
1795 cur = delim;
1796 }
1797 cur++;
1798
1799 if (*cur != '@') {
1800 /* dst port */
1801 delim = strchr(cur, '@');
1802 if (!delim)
1803 goto parse_failed;
1804 *delim = 0;
1805 if (*cur == ' ' || *cur == '\t')
1806 np_info(np, "warning: whitespace is not allowed\n");
1807 if (kstrtou16(s: cur, base: 10, res: &np->remote_port))
1808 goto parse_failed;
1809 cur = delim;
1810 }
1811 cur++;
1812
1813 /* dst ip */
1814 delim = strchr(cur, '/');
1815 if (!delim)
1816 goto parse_failed;
1817 *delim = 0;
1818 ipv6 = netpoll_parse_ip_addr(str: cur, addr: &np->remote_ip);
1819 if (ipv6 < 0)
1820 goto parse_failed;
1821 else if (ipversion_set && np->ipv6 != (bool)ipv6)
1822 goto parse_failed;
1823 else
1824 np->ipv6 = (bool)ipv6;
1825 cur = delim + 1;
1826
1827 if (*cur != 0) {
1828 /* MAC address */
1829 if (!mac_pton(s: cur, mac: np->remote_mac))
1830 goto parse_failed;
1831 }
1832
1833 netconsole_print_banner(np);
1834
1835 return 0;
1836
1837 parse_failed:
1838 np_info(np, "couldn't parse config at '%s'!\n", cur);
1839 return -1;
1840}
1841
1842/* Allocate new target (from boot/module param) and setup netpoll for it */
1843static struct netconsole_target *alloc_param_target(char *target_config,
1844 int cmdline_count)
1845{
1846 struct netconsole_target *nt;
1847 int err;
1848
1849 nt = alloc_and_init();
1850 if (!nt) {
1851 err = -ENOMEM;
1852 goto fail;
1853 }
1854
1855 if (*target_config == '+') {
1856 nt->extended = true;
1857 target_config++;
1858 }
1859
1860 if (*target_config == 'r') {
1861 if (!nt->extended) {
1862 pr_err("Netconsole configuration error. Release feature requires extended log message");
1863 err = -EINVAL;
1864 goto fail;
1865 }
1866 nt->release = true;
1867 target_config++;
1868 }
1869
1870 /* Parse parameters and setup netpoll */
1871 err = netconsole_parser_cmdline(np: &nt->np, opt: target_config);
1872 if (err)
1873 goto fail;
1874
1875 err = netpoll_setup(np: &nt->np);
1876 if (err) {
1877 pr_err("Not enabling netconsole for %s%d. Netpoll setup failed\n",
1878 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
1879 if (!IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
1880 /* only fail if dynamic reconfiguration is set,
1881 * otherwise, keep the target in the list, but disabled.
1882 */
1883 goto fail;
1884 } else {
1885 nt->enabled = true;
1886 }
1887 populate_configfs_item(nt, cmdline_count);
1888
1889 return nt;
1890
1891fail:
1892 kfree(objp: nt);
1893 return ERR_PTR(error: err);
1894}
1895
1896/* Cleanup netpoll for given target (from boot/module param) and free it */
1897static void free_param_target(struct netconsole_target *nt)
1898{
1899 netpoll_cleanup(np: &nt->np);
1900 kfree(objp: nt);
1901}
1902
1903static struct console netconsole_ext = {
1904 .name = "netcon_ext",
1905 .flags = CON_ENABLED | CON_EXTENDED,
1906 .write = write_ext_msg,
1907};
1908
1909static struct console netconsole = {
1910 .name = "netcon",
1911 .flags = CON_ENABLED,
1912 .write = write_msg,
1913};
1914
1915static int __init init_netconsole(void)
1916{
1917 int err;
1918 struct netconsole_target *nt, *tmp;
1919 u32 console_type_needed = 0;
1920 unsigned int count = 0;
1921 unsigned long flags;
1922 char *target_config;
1923 char *input = config;
1924
1925 if (strnlen(input, MAX_PARAM_LENGTH)) {
1926 while ((target_config = strsep(&input, ";"))) {
1927 nt = alloc_param_target(target_config, cmdline_count: count);
1928 if (IS_ERR(ptr: nt)) {
1929 if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
1930 continue;
1931 err = PTR_ERR(ptr: nt);
1932 goto fail;
1933 }
1934 /* Dump existing printks when we register */
1935 if (nt->extended) {
1936 console_type_needed |= CONS_EXTENDED;
1937 netconsole_ext.flags |= CON_PRINTBUFFER;
1938 } else {
1939 console_type_needed |= CONS_BASIC;
1940 netconsole.flags |= CON_PRINTBUFFER;
1941 }
1942
1943 spin_lock_irqsave(&target_list_lock, flags);
1944 list_add(new: &nt->list, head: &target_list);
1945 spin_unlock_irqrestore(lock: &target_list_lock, flags);
1946 count++;
1947 }
1948 }
1949
1950 err = register_netdevice_notifier(nb: &netconsole_netdev_notifier);
1951 if (err)
1952 goto fail;
1953
1954 err = dynamic_netconsole_init();
1955 if (err)
1956 goto undonotifier;
1957
1958 if (console_type_needed & CONS_EXTENDED)
1959 register_console(&netconsole_ext);
1960 if (console_type_needed & CONS_BASIC)
1961 register_console(&netconsole);
1962 pr_info("network logging started\n");
1963
1964 return err;
1965
1966undonotifier:
1967 unregister_netdevice_notifier(nb: &netconsole_netdev_notifier);
1968
1969fail:
1970 pr_err("cleaning up\n");
1971
1972 /*
1973 * Remove all targets and destroy them (only targets created
1974 * from the boot/module option exist here). Skipping the list
1975 * lock is safe here, and netpoll_cleanup() will sleep.
1976 */
1977 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1978 list_del(entry: &nt->list);
1979 free_param_target(nt);
1980 }
1981
1982 return err;
1983}
1984
1985static void __exit cleanup_netconsole(void)
1986{
1987 struct netconsole_target *nt, *tmp;
1988
1989 if (console_is_registered(con: &netconsole_ext))
1990 unregister_console(&netconsole_ext);
1991 if (console_is_registered(con: &netconsole))
1992 unregister_console(&netconsole);
1993 dynamic_netconsole_exit();
1994 unregister_netdevice_notifier(nb: &netconsole_netdev_notifier);
1995
1996 /*
1997 * Targets created via configfs pin references on our module
1998 * and would first be rmdir(2)'ed from userspace. We reach
1999 * here only when they are already destroyed, and only those
2000 * created from the boot/module option are left, so remove and
2001 * destroy them. Skipping the list lock is safe here, and
2002 * netpoll_cleanup() will sleep.
2003 */
2004 list_for_each_entry_safe(nt, tmp, &target_list, list) {
2005 list_del(entry: &nt->list);
2006 free_param_target(nt);
2007 }
2008}
2009
2010/*
2011 * Use late_initcall to ensure netconsole is
2012 * initialized after network device driver if built-in.
2013 *
2014 * late_initcall() and module_init() are identical if built as module.
2015 */
2016late_initcall(init_netconsole);
2017module_exit(cleanup_netconsole);
2018