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