xref: /linux/drivers/net/netconsole.c (revision d2b007374551ac09db16badde575cdd698f6fc92)
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 
43 MODULE_AUTHOR("Matt Mackall <mpm@selenic.com>");
44 MODULE_DESCRIPTION("Console driver for network interfaces");
45 MODULE_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 
56 static char config[MAX_PARAM_LENGTH];
57 module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
58 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
59 
60 static bool oops_only;
61 module_param(oops_only, bool, 0600);
62 MODULE_PARM_DESC(oops_only, "Only log oops messages");
63 
64 #define NETCONSOLE_PARAM_TARGET_PREFIX "cmdline"
65 
66 #ifndef	MODULE
67 static 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 */
76 static 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  */
81 static LIST_HEAD(target_cleanup_list);
82 
83 /* This needs to be a spinlock because write_msg() cannot sleep */
84 static DEFINE_SPINLOCK(target_list_lock);
85 /* This needs to be a mutex because netpoll_cleanup might sleep */
86 static 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  */
92 static struct console netconsole_ext, netconsole;
93 
94 struct netconsole_target_stats  {
95 	u64_stats_t xmit_drop_count;
96 	u64_stats_t enomem_count;
97 	struct u64_stats_sync syncp;
98 };
99 
100 enum 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  */
109 enum 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  */
150 struct 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 
173 static struct configfs_subsystem netconsole_subsys;
174 static DEFINE_MUTEX(dynamic_netconsole_mutex);
175 
176 static 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 
183 static 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  */
193 static 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 
199 static 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 
207 static int __init dynamic_netconsole_init(void)
208 {
209 	return 0;
210 }
211 
212 static 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  */
220 static void netconsole_target_get(struct netconsole_target *nt)
221 {
222 }
223 
224 static void netconsole_target_put(struct netconsole_target *nt)
225 {
226 }
227 
228 static 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  */
237 static 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(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  */
262 static 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(&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(&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(&nt->list, &target_list);
280 		spin_unlock_irqrestore(&target_list_lock, flags);
281 	}
282 	WARN_ON_ONCE(!list_empty(&target_cleanup_list));
283 	mutex_unlock(&target_cleanup_list_lock);
284 }
285 
286 static 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  */
306 static 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(str, len, (void *)addr, -1, &end) > 0 &&
319 	    (!end || *end == 0 || *end == '\n'))
320 		return 0;
321 
322 	if (IS_ENABLED(CONFIG_IPV6) &&
323 	    in6_pton(str, len, (void *)addr, -1, &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 
356 static 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  */
370 static 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 */
381 static 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 
394 static ssize_t enabled_show(struct config_item *item, char *buf)
395 {
396 	return sysfs_emit(buf, "%d\n", to_target(item)->enabled);
397 }
398 
399 static ssize_t extended_show(struct config_item *item, char *buf)
400 {
401 	return sysfs_emit(buf, "%d\n", to_target(item)->extended);
402 }
403 
404 static ssize_t release_show(struct config_item *item, char *buf)
405 {
406 	return sysfs_emit(buf, "%d\n", to_target(item)->release);
407 }
408 
409 static 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 
414 static 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 
419 static 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 
424 static 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 
434 static 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 
444 static 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 
452 static 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 
457 static 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 */
473 static 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 */
486 static 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 
499 static 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  */
515 static 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 
539 static 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  */
559 static 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();
633 out_unlock:
634 	mutex_unlock(&dynamic_netconsole_mutex);
635 	return ret;
636 }
637 
638 static 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);
660 out_unlock:
661 	mutex_unlock(&dynamic_netconsole_mutex);
662 	return ret;
663 }
664 
665 static 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);
686 out_unlock:
687 	mutex_unlock(&dynamic_netconsole_mutex);
688 	return ret;
689 }
690 
691 static 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 
711 static 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);
728 out_unlock:
729 	mutex_unlock(&dynamic_netconsole_mutex);
730 	return ret;
731 }
732 
733 static 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);
750 out_unlock:
751 	mutex_unlock(&dynamic_netconsole_mutex);
752 	return ret;
753 }
754 
755 static 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);
775 out_unlock:
776 	mutex_unlock(&dynamic_netconsole_mutex);
777 	return ret;
778 }
779 
780 static 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);
800 out_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  */
810 static 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 
829 static 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);
850 out_unlock:
851 	mutex_unlock(&dynamic_netconsole_mutex);
852 	return ret;
853 }
854 
855 struct userdatum {
856 	struct config_item item;
857 	char value[MAX_EXTRADATA_VALUE_LEN];
858 };
859 
860 static struct userdatum *to_userdatum(struct config_item *item)
861 {
862 	return container_of(item, struct userdatum, item);
863 }
864 
865 struct userdata {
866 	struct config_group group;
867 };
868 
869 static struct userdata *to_userdata(struct config_item *item)
870 {
871 	return container_of(to_config_group(item), struct userdata, group);
872 }
873 
874 static 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 
882 static 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 
887 static 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 
923 static 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;
945 out_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  */
954 static 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 
961 static 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 
988 unlock_ok:
989 	ret = strnlen(buf, count);
990 unlock:
991 	mutex_unlock(&dynamic_netconsole_mutex);
992 	return ret;
993 }
994 
995 static 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 
1022 unlock_ok:
1023 	ret = strnlen(buf, count);
1024 unlock:
1025 	mutex_unlock(&dynamic_netconsole_mutex);
1026 	return ret;
1027 }
1028 
1029 static 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 
1056 unlock_ok:
1057 	ret = strnlen(buf, count);
1058 unlock:
1059 	mutex_unlock(&dynamic_netconsole_mutex);
1060 	return ret;
1061 }
1062 
1063 /* configfs helper to sysdata cpu_nr feature */
1064 static 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 
1099 unlock_ok:
1100 	ret = strnlen(buf, count);
1101 unlock:
1102 	mutex_unlock(&dynamic_netconsole_mutex);
1103 	return ret;
1104 }
1105 
1106 CONFIGFS_ATTR(userdatum_, value);
1107 CONFIGFS_ATTR(sysdata_, cpu_nr_enabled);
1108 CONFIGFS_ATTR(sysdata_, taskname_enabled);
1109 CONFIGFS_ATTR(sysdata_, release_enabled);
1110 CONFIGFS_ATTR(sysdata_, msgid_enabled);
1111 
1112 static struct configfs_attribute *userdatum_attrs[] = {
1113 	&userdatum_attr_value,
1114 	NULL,
1115 };
1116 
1117 static void userdatum_release(struct config_item *item)
1118 {
1119 	kfree(to_userdatum(item));
1120 }
1121 
1122 static struct configfs_item_operations userdatum_ops = {
1123 	.release = userdatum_release,
1124 };
1125 
1126 static 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 
1132 static 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 
1155 static 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 
1169 static 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 
1177 static struct configfs_group_operations userdata_ops = {
1178 	.make_item		= userdatum_make_item,
1179 	.drop_item		= userdatum_drop,
1180 };
1181 
1182 static 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 
1189 CONFIGFS_ATTR(, enabled);
1190 CONFIGFS_ATTR(, extended);
1191 CONFIGFS_ATTR(, dev_name);
1192 CONFIGFS_ATTR(, local_port);
1193 CONFIGFS_ATTR(, remote_port);
1194 CONFIGFS_ATTR(, local_ip);
1195 CONFIGFS_ATTR(, remote_ip);
1196 CONFIGFS_ATTR_RO(, local_mac);
1197 CONFIGFS_ATTR(, remote_mac);
1198 CONFIGFS_ATTR(, release);
1199 CONFIGFS_ATTR_RO(, transmit_errors);
1200 
1201 static 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 
1220 static void netconsole_target_release(struct config_item *item)
1221 {
1222 	kfree(to_target(item));
1223 }
1224 
1225 static struct configfs_item_operations netconsole_target_item_ops = {
1226 	.release		= netconsole_target_release,
1227 };
1228 
1229 static 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 
1235 static 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 
1244 static 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 
1265 static 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 
1299 static 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 
1319 static struct configfs_group_operations netconsole_subsys_group_ops = {
1320 	.make_group	= make_netconsole_target,
1321 	.drop_item	= drop_netconsole_target,
1322 };
1323 
1324 static 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 */
1330 static 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 
1339 static 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 
1349 static 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 
1357 static 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 
1364 static 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 
1371 static 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  */
1383 static 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 
1407 out:
1408 	return extradata_len;
1409 }
1410 #else /* CONFIG_NETCONSOLE_DYNAMIC not set */
1411 static int prepare_extradata(struct netconsole_target *nt)
1412 {
1413 	return 0;
1414 }
1415 #endif	/* CONFIG_NETCONSOLE_DYNAMIC */
1416 
1417 /* Handle network interface device notifications */
1418 static 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(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(&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(&nt->list, &target_cleanup_list);
1444 				stopped = true;
1445 			}
1446 		}
1447 		netconsole_target_put(nt);
1448 	}
1449 	spin_unlock_irqrestore(&target_list_lock, flags);
1450 	mutex_unlock(&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 
1475 done:
1476 	return NOTIFY_DONE;
1477 }
1478 
1479 static 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  */
1493 static void send_udp(struct netconsole_target *nt, const char *msg, int len)
1494 {
1495 	int result = netpoll_send_udp(&nt->np, msg, len);
1496 
1497 	if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC)) {
1498 		if (result == NET_XMIT_DROP) {
1499 			u64_stats_update_begin(&nt->stats.syncp);
1500 			u64_stats_inc(&nt->stats.xmit_drop_count);
1501 			u64_stats_update_end(&nt->stats.syncp);
1502 		} else if (result == -ENOMEM) {
1503 			u64_stats_update_begin(&nt->stats.syncp);
1504 			u64_stats_inc(&nt->stats.enomem_count);
1505 			u64_stats_update_end(&nt->stats.syncp);
1506 		}
1507 	}
1508 }
1509 
1510 static 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(nt->buf, MAX_PRINT_CHUNK, "%s,%s", release, msg);
1526 		msg_len += release_len;
1527 	} else {
1528 		memcpy(nt->buf, msg, msg_len);
1529 	}
1530 
1531 	if (extradata)
1532 		msg_len += scnprintf(&nt->buf[msg_len],
1533 				     MAX_PRINT_CHUNK - msg_len,
1534 				     "%s", extradata);
1535 
1536 	send_udp(nt, nt->buf, msg_len);
1537 }
1538 
1539 static void append_release(char *buf)
1540 {
1541 	const char *release;
1542 
1543 	release = init_utsname()->release;
1544 	scnprintf(buf, MAX_PRINT_CHUNK, "%s,", release);
1545 }
1546 
1547 static 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(nt->buf + this_header,
1578 					 MAX_PRINT_CHUNK - this_header,
1579 					 ",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(nt->buf + this_header, msgbody + offset,
1589 			       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(nt->buf + this_header + this_offset,
1624 			       extradata + sent_extradata,
1625 			       this_chunk);
1626 			this_offset += this_chunk;
1627 		}
1628 
1629 		send_udp(nt, nt->buf, this_header + this_offset);
1630 		offset += this_offset;
1631 	}
1632 }
1633 
1634 static 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(nt->buf);
1658 
1659 	/* Copy the header into the buffer */
1660 	memcpy(nt->buf + release_len, msg, 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  */
1680 static 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 
1698 static 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(&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(nt->np.dev))
1710 			send_ext_msg_udp(nt, msg, len);
1711 	spin_unlock_irqrestore(&target_list_lock, flags);
1712 }
1713 
1714 static 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(&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(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, tmp, frag);
1740 				tmp += frag;
1741 				left -= frag;
1742 			}
1743 		}
1744 	}
1745 	spin_unlock_irqrestore(&target_list_lock, flags);
1746 }
1747 
1748 static 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(cur, 10, &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(cur, &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(np->dev_mac);
1790 		if (!strchr(cur, ':'))
1791 			strscpy(np->dev_name, cur, sizeof(np->dev_name));
1792 		else if (!mac_pton(cur, 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(cur, 10, &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(cur, &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(cur, 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 */
1843 static 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(&nt->np, target_config);
1872 	if (err)
1873 		goto fail;
1874 
1875 	err = netpoll_setup(&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 
1891 fail:
1892 	kfree(nt);
1893 	return ERR_PTR(err);
1894 }
1895 
1896 /* Cleanup netpoll for given target (from boot/module param) and free it */
1897 static void free_param_target(struct netconsole_target *nt)
1898 {
1899 	netpoll_cleanup(&nt->np);
1900 	kfree(nt);
1901 }
1902 
1903 static struct console netconsole_ext = {
1904 	.name	= "netcon_ext",
1905 	.flags	= CON_ENABLED | CON_EXTENDED,
1906 	.write	= write_ext_msg,
1907 };
1908 
1909 static struct console netconsole = {
1910 	.name	= "netcon",
1911 	.flags	= CON_ENABLED,
1912 	.write	= write_msg,
1913 };
1914 
1915 static 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, count);
1928 			if (IS_ERR(nt)) {
1929 				if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
1930 					continue;
1931 				err = PTR_ERR(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(&nt->list, &target_list);
1945 			spin_unlock_irqrestore(&target_list_lock, flags);
1946 			count++;
1947 		}
1948 	}
1949 
1950 	err = register_netdevice_notifier(&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 
1966 undonotifier:
1967 	unregister_netdevice_notifier(&netconsole_netdev_notifier);
1968 
1969 fail:
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(&nt->list);
1979 		free_param_target(nt);
1980 	}
1981 
1982 	return err;
1983 }
1984 
1985 static void __exit cleanup_netconsole(void)
1986 {
1987 	struct netconsole_target *nt, *tmp;
1988 
1989 	if (console_is_registered(&netconsole_ext))
1990 		unregister_console(&netconsole_ext);
1991 	if (console_is_registered(&netconsole))
1992 		unregister_console(&netconsole);
1993 	dynamic_netconsole_exit();
1994 	unregister_netdevice_notifier(&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(&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  */
2016 late_initcall(init_netconsole);
2017 module_exit(cleanup_netconsole);
2018