File Index
Files and directories
Sign in
FILE

netconsole.c

File preview with syntax highlighting.

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