brintos

brintos / linux-shallow public Read only

0
0
Text · 35.4 KiB · de20928 Raw
1406 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  linux/drivers/net/netconsole.c4 *5 *  Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>6 *7 *  This file contains the implementation of an IRQ-safe, crash-safe8 *  kernel console implementation that outputs kernel messages to the9 *  network.10 *11 * Modification history:12 *13 * 2001-09-17    started by Ingo Molnar.14 * 2003-08-11    2.6 port by Matt Mackall15 *               simplified options16 *               generic card hooks17 *               works non-modular18 * 2003-09-07    rewritten with netpoll api19 */20 21/****************************************************************22 *23 ****************************************************************/24 25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt26 27#include <linux/mm.h>28#include <linux/init.h>29#include <linux/module.h>30#include <linux/slab.h>31#include <linux/console.h>32#include <linux/moduleparam.h>33#include <linux/kernel.h>34#include <linux/string.h>35#include <linux/netpoll.h>36#include <linux/inet.h>37#include <linux/configfs.h>38#include <linux/etherdevice.h>39#include <linux/utsname.h>40#include <linux/rtnetlink.h>41 42MODULE_AUTHOR("Matt Mackall <mpm@selenic.com>");43MODULE_DESCRIPTION("Console driver for network interfaces");44MODULE_LICENSE("GPL");45 46#define MAX_PARAM_LENGTH		25647#define MAX_USERDATA_ENTRY_LENGTH	25648#define MAX_USERDATA_VALUE_LENGTH	20049/* The number 3 comes from userdata entry format characters (' ', '=', '\n') */50#define MAX_USERDATA_NAME_LENGTH	(MAX_USERDATA_ENTRY_LENGTH - \51					MAX_USERDATA_VALUE_LENGTH - 3)52#define MAX_USERDATA_ITEMS		1653#define MAX_PRINT_CHUNK			100054 55static char config[MAX_PARAM_LENGTH];56module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);57MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");58 59static bool oops_only;60module_param(oops_only, bool, 0600);61MODULE_PARM_DESC(oops_only, "Only log oops messages");62 63#define NETCONSOLE_PARAM_TARGET_PREFIX "cmdline"64 65#ifndef	MODULE66static int __init option_setup(char *opt)67{68	strscpy(config, opt, MAX_PARAM_LENGTH);69	return 1;70}71__setup("netconsole=", option_setup);72#endif	/* MODULE */73 74/* Linked list of all configured targets */75static LIST_HEAD(target_list);76/* target_cleanup_list is used to track targets that need to be cleaned outside77 * of target_list_lock. It should be cleaned in the same function it is78 * populated.79 */80static LIST_HEAD(target_cleanup_list);81 82/* This needs to be a spinlock because write_msg() cannot sleep */83static DEFINE_SPINLOCK(target_list_lock);84/* This needs to be a mutex because netpoll_cleanup might sleep */85static DEFINE_MUTEX(target_cleanup_list_lock);86 87/*88 * Console driver for extended netconsoles.  Registered on the first use to89 * avoid unnecessarily enabling ext message formatting.90 */91static struct console netconsole_ext;92 93/**94 * struct netconsole_target - Represents a configured netconsole target.95 * @list:	Links this target into the target_list.96 * @group:	Links us into the configfs subsystem hierarchy.97 * @userdata_group:	Links to the userdata configfs hierarchy98 * @userdata_complete:	Cached, formatted string of append99 * @userdata_length:	String length of userdata_complete100 * @enabled:	On / off knob to enable / disable target.101 *		Visible from userspace (read-write).102 *		We maintain a strict 1:1 correspondence between this and103 *		whether the corresponding netpoll is active or inactive.104 *		Also, other parameters of a target may be modified at105 *		runtime only when it is disabled (enabled == 0).106 * @extended:	Denotes whether console is extended or not.107 * @release:	Denotes whether kernel release version should be prepended108 *		to the message. Depends on extended console.109 * @np:		The netpoll structure for this target.110 *		Contains the other userspace visible parameters:111 *		dev_name	(read-write)112 *		local_port	(read-write)113 *		remote_port	(read-write)114 *		local_ip	(read-write)115 *		remote_ip	(read-write)116 *		local_mac	(read-only)117 *		remote_mac	(read-write)118 */119struct netconsole_target {120	struct list_head	list;121#ifdef	CONFIG_NETCONSOLE_DYNAMIC122	struct config_group	group;123	struct config_group	userdata_group;124	char userdata_complete[MAX_USERDATA_ENTRY_LENGTH * MAX_USERDATA_ITEMS];125	size_t			userdata_length;126#endif127	bool			enabled;128	bool			extended;129	bool			release;130	struct netpoll		np;131};132 133#ifdef	CONFIG_NETCONSOLE_DYNAMIC134 135static struct configfs_subsystem netconsole_subsys;136static DEFINE_MUTEX(dynamic_netconsole_mutex);137 138static int __init dynamic_netconsole_init(void)139{140	config_group_init(&netconsole_subsys.su_group);141	mutex_init(&netconsole_subsys.su_mutex);142	return configfs_register_subsystem(&netconsole_subsys);143}144 145static void __exit dynamic_netconsole_exit(void)146{147	configfs_unregister_subsystem(&netconsole_subsys);148}149 150/*151 * Targets that were created by parsing the boot/module option string152 * do not exist in the configfs hierarchy (and have NULL names) and will153 * never go away, so make these a no-op for them.154 */155static void netconsole_target_get(struct netconsole_target *nt)156{157	if (config_item_name(&nt->group.cg_item))158		config_group_get(&nt->group);159}160 161static void netconsole_target_put(struct netconsole_target *nt)162{163	if (config_item_name(&nt->group.cg_item))164		config_group_put(&nt->group);165}166 167#else	/* !CONFIG_NETCONSOLE_DYNAMIC */168 169static int __init dynamic_netconsole_init(void)170{171	return 0;172}173 174static void __exit dynamic_netconsole_exit(void)175{176}177 178/*179 * No danger of targets going away from under us when dynamic180 * reconfigurability is off.181 */182static void netconsole_target_get(struct netconsole_target *nt)183{184}185 186static void netconsole_target_put(struct netconsole_target *nt)187{188}189 190static void populate_configfs_item(struct netconsole_target *nt,191				   int cmdline_count)192{193}194#endif	/* CONFIG_NETCONSOLE_DYNAMIC */195 196/* Allocate and initialize with defaults.197 * Note that these targets get their config_item fields zeroed-out.198 */199static struct netconsole_target *alloc_and_init(void)200{201	struct netconsole_target *nt;202 203	nt = kzalloc(sizeof(*nt), GFP_KERNEL);204	if (!nt)205		return nt;206 207	if (IS_ENABLED(CONFIG_NETCONSOLE_EXTENDED_LOG))208		nt->extended = true;209	if (IS_ENABLED(CONFIG_NETCONSOLE_PREPEND_RELEASE))210		nt->release = true;211 212	nt->np.name = "netconsole";213	strscpy(nt->np.dev_name, "eth0", IFNAMSIZ);214	nt->np.local_port = 6665;215	nt->np.remote_port = 6666;216	eth_broadcast_addr(nt->np.remote_mac);217 218	return nt;219}220 221/* Clean up every target in the cleanup_list and move the clean targets back to222 * the main target_list.223 */224static void netconsole_process_cleanups_core(void)225{226	struct netconsole_target *nt, *tmp;227	unsigned long flags;228 229	/* The cleanup needs RTNL locked */230	ASSERT_RTNL();231 232	mutex_lock(&target_cleanup_list_lock);233	list_for_each_entry_safe(nt, tmp, &target_cleanup_list, list) {234		/* all entries in the cleanup_list needs to be disabled */235		WARN_ON_ONCE(nt->enabled);236		do_netpoll_cleanup(&nt->np);237		/* moved the cleaned target to target_list. Need to hold both238		 * locks239		 */240		spin_lock_irqsave(&target_list_lock, flags);241		list_move(&nt->list, &target_list);242		spin_unlock_irqrestore(&target_list_lock, flags);243	}244	WARN_ON_ONCE(!list_empty(&target_cleanup_list));245	mutex_unlock(&target_cleanup_list_lock);246}247 248#ifdef	CONFIG_NETCONSOLE_DYNAMIC249 250/*251 * Our subsystem hierarchy is:252 *253 * /sys/kernel/config/netconsole/254 *				|255 *				<target>/256 *				|	enabled257 *				|	release258 *				|	dev_name259 *				|	local_port260 *				|	remote_port261 *				|	local_ip262 *				|	remote_ip263 *				|	local_mac264 *				|	remote_mac265 *				|	userdata/266 *				|		<key>/267 *				|			value268 *				|		...269 *				|270 *				<target>/...271 */272 273static struct netconsole_target *to_target(struct config_item *item)274{275	struct config_group *cfg_group;276 277	cfg_group = to_config_group(item);278	if (!cfg_group)279		return NULL;280	return container_of(to_config_group(item),281			    struct netconsole_target, group);282}283 284/* Do the list cleanup with the rtnl lock hold.  rtnl lock is necessary because285 * netdev might be cleaned-up by calling __netpoll_cleanup(),286 */287static void netconsole_process_cleanups(void)288{289	/* rtnl lock is called here, because it has precedence over290	 * target_cleanup_list_lock mutex and target_cleanup_list291	 */292	rtnl_lock();293	netconsole_process_cleanups_core();294	rtnl_unlock();295}296 297/* Get rid of possible trailing newline, returning the new length */298static void trim_newline(char *s, size_t maxlen)299{300	size_t len;301 302	len = strnlen(s, maxlen);303	if (s[len - 1] == '\n')304		s[len - 1] = '\0';305}306 307/*308 * Attribute operations for netconsole_target.309 */310 311static ssize_t enabled_show(struct config_item *item, char *buf)312{313	return sysfs_emit(buf, "%d\n", to_target(item)->enabled);314}315 316static ssize_t extended_show(struct config_item *item, char *buf)317{318	return sysfs_emit(buf, "%d\n", to_target(item)->extended);319}320 321static ssize_t release_show(struct config_item *item, char *buf)322{323	return sysfs_emit(buf, "%d\n", to_target(item)->release);324}325 326static ssize_t dev_name_show(struct config_item *item, char *buf)327{328	return sysfs_emit(buf, "%s\n", to_target(item)->np.dev_name);329}330 331static ssize_t local_port_show(struct config_item *item, char *buf)332{333	return sysfs_emit(buf, "%d\n", to_target(item)->np.local_port);334}335 336static ssize_t remote_port_show(struct config_item *item, char *buf)337{338	return sysfs_emit(buf, "%d\n", to_target(item)->np.remote_port);339}340 341static ssize_t local_ip_show(struct config_item *item, char *buf)342{343	struct netconsole_target *nt = to_target(item);344 345	if (nt->np.ipv6)346		return sysfs_emit(buf, "%pI6c\n", &nt->np.local_ip.in6);347	else348		return sysfs_emit(buf, "%pI4\n", &nt->np.local_ip);349}350 351static ssize_t remote_ip_show(struct config_item *item, char *buf)352{353	struct netconsole_target *nt = to_target(item);354 355	if (nt->np.ipv6)356		return sysfs_emit(buf, "%pI6c\n", &nt->np.remote_ip.in6);357	else358		return sysfs_emit(buf, "%pI4\n", &nt->np.remote_ip);359}360 361static ssize_t local_mac_show(struct config_item *item, char *buf)362{363	struct net_device *dev = to_target(item)->np.dev;364	static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };365 366	return sysfs_emit(buf, "%pM\n", dev ? dev->dev_addr : bcast);367}368 369static ssize_t remote_mac_show(struct config_item *item, char *buf)370{371	return sysfs_emit(buf, "%pM\n", to_target(item)->np.remote_mac);372}373 374/*375 * This one is special -- targets created through the configfs interface376 * are not enabled (and the corresponding netpoll activated) by default.377 * The user is expected to set the desired parameters first (which378 * would enable him to dynamically add new netpoll targets for new379 * network interfaces as and when they come up).380 */381static ssize_t enabled_store(struct config_item *item,382		const char *buf, size_t count)383{384	struct netconsole_target *nt = to_target(item);385	unsigned long flags;386	bool enabled;387	ssize_t ret;388 389	mutex_lock(&dynamic_netconsole_mutex);390	ret = kstrtobool(buf, &enabled);391	if (ret)392		goto out_unlock;393 394	ret = -EINVAL;395	if (enabled == nt->enabled) {396		pr_info("network logging has already %s\n",397			nt->enabled ? "started" : "stopped");398		goto out_unlock;399	}400 401	if (enabled) {	/* true */402		if (nt->release && !nt->extended) {403			pr_err("Not enabling netconsole. Release feature requires extended log message");404			goto out_unlock;405		}406 407		if (nt->extended && !console_is_registered(&netconsole_ext))408			register_console(&netconsole_ext);409 410		/*411		 * Skip netpoll_parse_options() -- all the attributes are412		 * already configured via configfs. Just print them out.413		 */414		netpoll_print_options(&nt->np);415 416		ret = netpoll_setup(&nt->np);417		if (ret)418			goto out_unlock;419 420		nt->enabled = true;421		pr_info("network logging started\n");422	} else {	/* false */423		/* We need to disable the netconsole before cleaning it up424		 * otherwise we might end up in write_msg() with425		 * nt->np.dev == NULL and nt->enabled == true426		 */427		mutex_lock(&target_cleanup_list_lock);428		spin_lock_irqsave(&target_list_lock, flags);429		nt->enabled = false;430		/* Remove the target from the list, while holding431		 * target_list_lock432		 */433		list_move(&nt->list, &target_cleanup_list);434		spin_unlock_irqrestore(&target_list_lock, flags);435		mutex_unlock(&target_cleanup_list_lock);436	}437 438	ret = strnlen(buf, count);439	/* Deferred cleanup */440	netconsole_process_cleanups();441out_unlock:442	mutex_unlock(&dynamic_netconsole_mutex);443	return ret;444}445 446static ssize_t release_store(struct config_item *item, const char *buf,447			     size_t count)448{449	struct netconsole_target *nt = to_target(item);450	bool release;451	ssize_t ret;452 453	mutex_lock(&dynamic_netconsole_mutex);454	if (nt->enabled) {455		pr_err("target (%s) is enabled, disable to update parameters\n",456		       config_item_name(&nt->group.cg_item));457		ret = -EINVAL;458		goto out_unlock;459	}460 461	ret = kstrtobool(buf, &release);462	if (ret)463		goto out_unlock;464 465	nt->release = release;466 467	ret = strnlen(buf, count);468out_unlock:469	mutex_unlock(&dynamic_netconsole_mutex);470	return ret;471}472 473static ssize_t extended_store(struct config_item *item, const char *buf,474		size_t count)475{476	struct netconsole_target *nt = to_target(item);477	bool extended;478	ssize_t ret;479 480	mutex_lock(&dynamic_netconsole_mutex);481	if (nt->enabled) {482		pr_err("target (%s) is enabled, disable to update parameters\n",483		       config_item_name(&nt->group.cg_item));484		ret = -EINVAL;485		goto out_unlock;486	}487 488	ret = kstrtobool(buf, &extended);489	if (ret)490		goto out_unlock;491 492	nt->extended = extended;493	ret = strnlen(buf, count);494out_unlock:495	mutex_unlock(&dynamic_netconsole_mutex);496	return ret;497}498 499static ssize_t dev_name_store(struct config_item *item, const char *buf,500		size_t count)501{502	struct netconsole_target *nt = to_target(item);503 504	mutex_lock(&dynamic_netconsole_mutex);505	if (nt->enabled) {506		pr_err("target (%s) is enabled, disable to update parameters\n",507		       config_item_name(&nt->group.cg_item));508		mutex_unlock(&dynamic_netconsole_mutex);509		return -EINVAL;510	}511 512	strscpy(nt->np.dev_name, buf, IFNAMSIZ);513	trim_newline(nt->np.dev_name, IFNAMSIZ);514 515	mutex_unlock(&dynamic_netconsole_mutex);516	return strnlen(buf, count);517}518 519static ssize_t local_port_store(struct config_item *item, const char *buf,520		size_t count)521{522	struct netconsole_target *nt = to_target(item);523	ssize_t ret = -EINVAL;524 525	mutex_lock(&dynamic_netconsole_mutex);526	if (nt->enabled) {527		pr_err("target (%s) is enabled, disable to update parameters\n",528		       config_item_name(&nt->group.cg_item));529		goto out_unlock;530	}531 532	ret = kstrtou16(buf, 10, &nt->np.local_port);533	if (ret < 0)534		goto out_unlock;535	ret = strnlen(buf, count);536out_unlock:537	mutex_unlock(&dynamic_netconsole_mutex);538	return ret;539}540 541static ssize_t remote_port_store(struct config_item *item,542		const char *buf, size_t count)543{544	struct netconsole_target *nt = to_target(item);545	ssize_t ret = -EINVAL;546 547	mutex_lock(&dynamic_netconsole_mutex);548	if (nt->enabled) {549		pr_err("target (%s) is enabled, disable to update parameters\n",550		       config_item_name(&nt->group.cg_item));551		goto out_unlock;552	}553 554	ret = kstrtou16(buf, 10, &nt->np.remote_port);555	if (ret < 0)556		goto out_unlock;557	ret = strnlen(buf, count);558out_unlock:559	mutex_unlock(&dynamic_netconsole_mutex);560	return ret;561}562 563static ssize_t local_ip_store(struct config_item *item, const char *buf,564		size_t count)565{566	struct netconsole_target *nt = to_target(item);567	ssize_t ret = -EINVAL;568 569	mutex_lock(&dynamic_netconsole_mutex);570	if (nt->enabled) {571		pr_err("target (%s) is enabled, disable to update parameters\n",572		       config_item_name(&nt->group.cg_item));573		goto out_unlock;574	}575 576	if (strnchr(buf, count, ':')) {577		const char *end;578 579		if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) {580			if (*end && *end != '\n') {581				pr_err("invalid IPv6 address at: <%c>\n", *end);582				goto out_unlock;583			}584			nt->np.ipv6 = true;585		} else586			goto out_unlock;587	} else {588		if (!nt->np.ipv6)589			nt->np.local_ip.ip = in_aton(buf);590		else591			goto out_unlock;592	}593 594	ret = strnlen(buf, count);595out_unlock:596	mutex_unlock(&dynamic_netconsole_mutex);597	return ret;598}599 600static ssize_t remote_ip_store(struct config_item *item, const char *buf,601	       size_t count)602{603	struct netconsole_target *nt = to_target(item);604	ssize_t ret = -EINVAL;605 606	mutex_lock(&dynamic_netconsole_mutex);607	if (nt->enabled) {608		pr_err("target (%s) is enabled, disable to update parameters\n",609		       config_item_name(&nt->group.cg_item));610		goto out_unlock;611	}612 613	if (strnchr(buf, count, ':')) {614		const char *end;615 616		if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) {617			if (*end && *end != '\n') {618				pr_err("invalid IPv6 address at: <%c>\n", *end);619				goto out_unlock;620			}621			nt->np.ipv6 = true;622		} else623			goto out_unlock;624	} else {625		if (!nt->np.ipv6)626			nt->np.remote_ip.ip = in_aton(buf);627		else628			goto out_unlock;629	}630 631	ret = strnlen(buf, count);632out_unlock:633	mutex_unlock(&dynamic_netconsole_mutex);634	return ret;635}636 637static ssize_t remote_mac_store(struct config_item *item, const char *buf,638		size_t count)639{640	struct netconsole_target *nt = to_target(item);641	u8 remote_mac[ETH_ALEN];642	ssize_t ret = -EINVAL;643 644	mutex_lock(&dynamic_netconsole_mutex);645	if (nt->enabled) {646		pr_err("target (%s) is enabled, disable to update parameters\n",647		       config_item_name(&nt->group.cg_item));648		goto out_unlock;649	}650 651	if (!mac_pton(buf, remote_mac))652		goto out_unlock;653	if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')654		goto out_unlock;655	memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);656 657	ret = strnlen(buf, count);658out_unlock:659	mutex_unlock(&dynamic_netconsole_mutex);660	return ret;661}662 663struct userdatum {664	struct config_item item;665	char value[MAX_USERDATA_VALUE_LENGTH];666};667 668static struct userdatum *to_userdatum(struct config_item *item)669{670	return container_of(item, struct userdatum, item);671}672 673struct userdata {674	struct config_group group;675};676 677static struct userdata *to_userdata(struct config_item *item)678{679	return container_of(to_config_group(item), struct userdata, group);680}681 682static struct netconsole_target *userdata_to_target(struct userdata *ud)683{684	struct config_group *netconsole_group;685 686	netconsole_group = to_config_group(ud->group.cg_item.ci_parent);687	return to_target(&netconsole_group->cg_item);688}689 690static ssize_t userdatum_value_show(struct config_item *item, char *buf)691{692	return sysfs_emit(buf, "%s\n", &(to_userdatum(item)->value[0]));693}694 695static void update_userdata(struct netconsole_target *nt)696{697	int complete_idx = 0, child_count = 0;698	struct list_head *entry;699 700	/* Clear the current string in case the last userdatum was deleted */701	nt->userdata_length = 0;702	nt->userdata_complete[0] = 0;703 704	list_for_each(entry, &nt->userdata_group.cg_children) {705		struct userdatum *udm_item;706		struct config_item *item;707 708		if (child_count >= MAX_USERDATA_ITEMS)709			break;710		child_count++;711 712		item = container_of(entry, struct config_item, ci_entry);713		udm_item = to_userdatum(item);714 715		/* Skip userdata with no value set */716		if (strnlen(udm_item->value, MAX_USERDATA_VALUE_LENGTH) == 0)717			continue;718 719		/* This doesn't overflow userdata_complete since it will write720		 * one entry length (1/MAX_USERDATA_ITEMS long), entry count is721		 * checked to not exceed MAX items with child_count above722		 */723		complete_idx += scnprintf(&nt->userdata_complete[complete_idx],724					  MAX_USERDATA_ENTRY_LENGTH, " %s=%s\n",725					  item->ci_name, udm_item->value);726	}727	nt->userdata_length = strnlen(nt->userdata_complete,728				      sizeof(nt->userdata_complete));729}730 731static ssize_t userdatum_value_store(struct config_item *item, const char *buf,732				     size_t count)733{734	struct userdatum *udm = to_userdatum(item);735	struct netconsole_target *nt;736	struct userdata *ud;737	ssize_t ret;738 739	if (count > MAX_USERDATA_VALUE_LENGTH)740		return -EMSGSIZE;741 742	mutex_lock(&dynamic_netconsole_mutex);743 744	ret = strscpy(udm->value, buf, sizeof(udm->value));745	if (ret < 0)746		goto out_unlock;747	trim_newline(udm->value, sizeof(udm->value));748 749	ud = to_userdata(item->ci_parent);750	nt = userdata_to_target(ud);751	update_userdata(nt);752	ret = count;753out_unlock:754	mutex_unlock(&dynamic_netconsole_mutex);755	return ret;756}757 758CONFIGFS_ATTR(userdatum_, value);759 760static struct configfs_attribute *userdatum_attrs[] = {761	&userdatum_attr_value,762	NULL,763};764 765static void userdatum_release(struct config_item *item)766{767	kfree(to_userdatum(item));768}769 770static struct configfs_item_operations userdatum_ops = {771	.release = userdatum_release,772};773 774static const struct config_item_type userdatum_type = {775	.ct_item_ops	= &userdatum_ops,776	.ct_attrs	= userdatum_attrs,777	.ct_owner	= THIS_MODULE,778};779 780static struct config_item *userdatum_make_item(struct config_group *group,781					       const char *name)782{783	struct netconsole_target *nt;784	struct userdatum *udm;785	struct userdata *ud;786	size_t child_count;787 788	if (strlen(name) > MAX_USERDATA_NAME_LENGTH)789		return ERR_PTR(-ENAMETOOLONG);790 791	ud = to_userdata(&group->cg_item);792	nt = userdata_to_target(ud);793	child_count = list_count_nodes(&nt->userdata_group.cg_children);794	if (child_count >= MAX_USERDATA_ITEMS)795		return ERR_PTR(-ENOSPC);796 797	udm = kzalloc(sizeof(*udm), GFP_KERNEL);798	if (!udm)799		return ERR_PTR(-ENOMEM);800 801	config_item_init_type_name(&udm->item, name, &userdatum_type);802	return &udm->item;803}804 805static void userdatum_drop(struct config_group *group, struct config_item *item)806{807	struct netconsole_target *nt;808	struct userdata *ud;809 810	ud = to_userdata(&group->cg_item);811	nt = userdata_to_target(ud);812 813	mutex_lock(&dynamic_netconsole_mutex);814	update_userdata(nt);815	config_item_put(item);816	mutex_unlock(&dynamic_netconsole_mutex);817}818 819static struct configfs_attribute *userdata_attrs[] = {820	NULL,821};822 823static struct configfs_group_operations userdata_ops = {824	.make_item		= userdatum_make_item,825	.drop_item		= userdatum_drop,826};827 828static const struct config_item_type userdata_type = {829	.ct_item_ops	= &userdatum_ops,830	.ct_group_ops	= &userdata_ops,831	.ct_attrs	= userdata_attrs,832	.ct_owner	= THIS_MODULE,833};834 835CONFIGFS_ATTR(, enabled);836CONFIGFS_ATTR(, extended);837CONFIGFS_ATTR(, dev_name);838CONFIGFS_ATTR(, local_port);839CONFIGFS_ATTR(, remote_port);840CONFIGFS_ATTR(, local_ip);841CONFIGFS_ATTR(, remote_ip);842CONFIGFS_ATTR_RO(, local_mac);843CONFIGFS_ATTR(, remote_mac);844CONFIGFS_ATTR(, release);845 846static struct configfs_attribute *netconsole_target_attrs[] = {847	&attr_enabled,848	&attr_extended,849	&attr_release,850	&attr_dev_name,851	&attr_local_port,852	&attr_remote_port,853	&attr_local_ip,854	&attr_remote_ip,855	&attr_local_mac,856	&attr_remote_mac,857	NULL,858};859 860/*861 * Item operations and type for netconsole_target.862 */863 864static void netconsole_target_release(struct config_item *item)865{866	kfree(to_target(item));867}868 869static struct configfs_item_operations netconsole_target_item_ops = {870	.release		= netconsole_target_release,871};872 873static const struct config_item_type netconsole_target_type = {874	.ct_attrs		= netconsole_target_attrs,875	.ct_item_ops		= &netconsole_target_item_ops,876	.ct_owner		= THIS_MODULE,877};878 879static void init_target_config_group(struct netconsole_target *nt,880				     const char *name)881{882	config_group_init_type_name(&nt->group, name, &netconsole_target_type);883	config_group_init_type_name(&nt->userdata_group, "userdata",884				    &userdata_type);885	configfs_add_default_group(&nt->userdata_group, &nt->group);886}887 888static struct netconsole_target *find_cmdline_target(const char *name)889{890	struct netconsole_target *nt, *ret = NULL;891	unsigned long flags;892 893	spin_lock_irqsave(&target_list_lock, flags);894	list_for_each_entry(nt, &target_list, list) {895		if (!strcmp(nt->group.cg_item.ci_name, name)) {896			ret = nt;897			break;898		}899	}900	spin_unlock_irqrestore(&target_list_lock, flags);901 902	return ret;903}904 905/*906 * Group operations and type for netconsole_subsys.907 */908 909static struct config_group *make_netconsole_target(struct config_group *group,910						   const char *name)911{912	struct netconsole_target *nt;913	unsigned long flags;914 915	/* Checking if a target by this name was created at boot time.  If so,916	 * attach a configfs entry to that target.  This enables dynamic917	 * control.918	 */919	if (!strncmp(name, NETCONSOLE_PARAM_TARGET_PREFIX,920		     strlen(NETCONSOLE_PARAM_TARGET_PREFIX))) {921		nt = find_cmdline_target(name);922		if (nt) {923			init_target_config_group(nt, name);924			return &nt->group;925		}926	}927 928	nt = alloc_and_init();929	if (!nt)930		return ERR_PTR(-ENOMEM);931 932	/* Initialize the config_group member */933	init_target_config_group(nt, name);934 935	/* Adding, but it is disabled */936	spin_lock_irqsave(&target_list_lock, flags);937	list_add(&nt->list, &target_list);938	spin_unlock_irqrestore(&target_list_lock, flags);939 940	return &nt->group;941}942 943static void drop_netconsole_target(struct config_group *group,944				   struct config_item *item)945{946	unsigned long flags;947	struct netconsole_target *nt = to_target(item);948 949	spin_lock_irqsave(&target_list_lock, flags);950	list_del(&nt->list);951	spin_unlock_irqrestore(&target_list_lock, flags);952 953	/*954	 * The target may have never been enabled, or was manually disabled955	 * before being removed so netpoll may have already been cleaned up.956	 */957	if (nt->enabled)958		netpoll_cleanup(&nt->np);959 960	config_item_put(&nt->group.cg_item);961}962 963static struct configfs_group_operations netconsole_subsys_group_ops = {964	.make_group	= make_netconsole_target,965	.drop_item	= drop_netconsole_target,966};967 968static const struct config_item_type netconsole_subsys_type = {969	.ct_group_ops	= &netconsole_subsys_group_ops,970	.ct_owner	= THIS_MODULE,971};972 973/* The netconsole configfs subsystem */974static struct configfs_subsystem netconsole_subsys = {975	.su_group	= {976		.cg_item	= {977			.ci_namebuf	= "netconsole",978			.ci_type	= &netconsole_subsys_type,979		},980	},981};982 983static void populate_configfs_item(struct netconsole_target *nt,984				   int cmdline_count)985{986	char target_name[16];987 988	snprintf(target_name, sizeof(target_name), "%s%d",989		 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);990	init_target_config_group(nt, target_name);991}992 993#endif	/* CONFIG_NETCONSOLE_DYNAMIC */994 995/* Handle network interface device notifications */996static int netconsole_netdev_event(struct notifier_block *this,997				   unsigned long event, void *ptr)998{999	unsigned long flags;1000	struct netconsole_target *nt, *tmp;1001	struct net_device *dev = netdev_notifier_info_to_dev(ptr);1002	bool stopped = false;1003 1004	if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||1005	      event == NETDEV_RELEASE || event == NETDEV_JOIN))1006		goto done;1007 1008	mutex_lock(&target_cleanup_list_lock);1009	spin_lock_irqsave(&target_list_lock, flags);1010	list_for_each_entry_safe(nt, tmp, &target_list, list) {1011		netconsole_target_get(nt);1012		if (nt->np.dev == dev) {1013			switch (event) {1014			case NETDEV_CHANGENAME:1015				strscpy(nt->np.dev_name, dev->name, IFNAMSIZ);1016				break;1017			case NETDEV_RELEASE:1018			case NETDEV_JOIN:1019			case NETDEV_UNREGISTER:1020				nt->enabled = false;1021				list_move(&nt->list, &target_cleanup_list);1022				stopped = true;1023			}1024		}1025		netconsole_target_put(nt);1026	}1027	spin_unlock_irqrestore(&target_list_lock, flags);1028	mutex_unlock(&target_cleanup_list_lock);1029 1030	if (stopped) {1031		const char *msg = "had an event";1032 1033		switch (event) {1034		case NETDEV_UNREGISTER:1035			msg = "unregistered";1036			break;1037		case NETDEV_RELEASE:1038			msg = "released slaves";1039			break;1040		case NETDEV_JOIN:1041			msg = "is joining a master device";1042			break;1043		}1044		pr_info("network logging stopped on interface %s as it %s\n",1045			dev->name, msg);1046	}1047 1048	/* Process target_cleanup_list entries. By the end, target_cleanup_list1049	 * should be empty1050	 */1051	netconsole_process_cleanups_core();1052 1053done:1054	return NOTIFY_DONE;1055}1056 1057static struct notifier_block netconsole_netdev_notifier = {1058	.notifier_call  = netconsole_netdev_event,1059};1060 1061/**1062 * send_ext_msg_udp - send extended log message to target1063 * @nt: target to send message to1064 * @msg: extended log message to send1065 * @msg_len: length of message1066 *1067 * Transfer extended log @msg to @nt.  If @msg is longer than1068 * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with1069 * ncfrag header field added to identify them.1070 */1071static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,1072			     int msg_len)1073{1074	static char buf[MAX_PRINT_CHUNK]; /* protected by target_list_lock */1075	const char *header, *body;1076	int offset = 0;1077	int header_len, body_len;1078	const char *msg_ready = msg;1079	const char *release;1080	int release_len = 0;1081	int userdata_len = 0;1082	char *userdata = NULL;1083 1084#ifdef CONFIG_NETCONSOLE_DYNAMIC1085	userdata = nt->userdata_complete;1086	userdata_len = nt->userdata_length;1087#endif1088 1089	if (nt->release) {1090		release = init_utsname()->release;1091		release_len = strlen(release) + 1;1092	}1093 1094	if (msg_len + release_len + userdata_len <= MAX_PRINT_CHUNK) {1095		/* No fragmentation needed */1096		if (nt->release) {1097			scnprintf(buf, MAX_PRINT_CHUNK, "%s,%s", release, msg);1098			msg_len += release_len;1099		} else {1100			memcpy(buf, msg, msg_len);1101		}1102 1103		if (userdata)1104			msg_len += scnprintf(&buf[msg_len],1105					     MAX_PRINT_CHUNK - msg_len,1106					     "%s", userdata);1107 1108		msg_ready = buf;1109		netpoll_send_udp(&nt->np, msg_ready, msg_len);1110		return;1111	}1112 1113	/* need to insert extra header fields, detect header and body */1114	header = msg;1115	body = memchr(msg, ';', msg_len);1116	if (WARN_ON_ONCE(!body))1117		return;1118 1119	header_len = body - header;1120	body_len = msg_len - header_len - 1;1121	body++;1122 1123	/*1124	 * Transfer multiple chunks with the following extra header.1125	 * "ncfrag=<byte-offset>/<total-bytes>"1126	 */1127	if (nt->release)1128		scnprintf(buf, MAX_PRINT_CHUNK, "%s,", release);1129	memcpy(buf + release_len, header, header_len);1130	header_len += release_len;1131 1132	while (offset < body_len + userdata_len) {1133		int this_header = header_len;1134		int this_offset = 0;1135		int this_chunk = 0;1136 1137		this_header += scnprintf(buf + this_header,1138					 sizeof(buf) - this_header,1139					 ",ncfrag=%d/%d;", offset,1140					 body_len + userdata_len);1141 1142		/* Not all body data has been written yet */1143		if (offset < body_len) {1144			this_chunk = min(body_len - offset,1145					 MAX_PRINT_CHUNK - this_header);1146			if (WARN_ON_ONCE(this_chunk <= 0))1147				return;1148			memcpy(buf + this_header, body + offset, this_chunk);1149			this_offset += this_chunk;1150		}1151		/* Body is fully written and there is pending userdata to write,1152		 * append userdata in this chunk1153		 */1154		if (offset + this_offset >= body_len &&1155		    offset + this_offset < userdata_len + body_len) {1156			int sent_userdata = (offset + this_offset) - body_len;1157			int preceding_bytes = this_chunk + this_header;1158 1159			if (WARN_ON_ONCE(sent_userdata < 0))1160				return;1161 1162			this_chunk = min(userdata_len - sent_userdata,1163					 MAX_PRINT_CHUNK - preceding_bytes);1164			if (WARN_ON_ONCE(this_chunk < 0))1165				/* this_chunk could be zero if all the previous1166				 * message used all the buffer. This is not a1167				 * problem, userdata will be sent in the next1168				 * iteration1169				 */1170				return;1171 1172			memcpy(buf + this_header + this_offset,1173			       userdata + sent_userdata,1174			       this_chunk);1175			this_offset += this_chunk;1176		}1177 1178		netpoll_send_udp(&nt->np, buf, this_header + this_offset);1179		offset += this_offset;1180	}1181}1182 1183static void write_ext_msg(struct console *con, const char *msg,1184			  unsigned int len)1185{1186	struct netconsole_target *nt;1187	unsigned long flags;1188 1189	if ((oops_only && !oops_in_progress) || list_empty(&target_list))1190		return;1191 1192	spin_lock_irqsave(&target_list_lock, flags);1193	list_for_each_entry(nt, &target_list, list)1194		if (nt->extended && nt->enabled && netif_running(nt->np.dev))1195			send_ext_msg_udp(nt, msg, len);1196	spin_unlock_irqrestore(&target_list_lock, flags);1197}1198 1199static void write_msg(struct console *con, const char *msg, unsigned int len)1200{1201	int frag, left;1202	unsigned long flags;1203	struct netconsole_target *nt;1204	const char *tmp;1205 1206	if (oops_only && !oops_in_progress)1207		return;1208	/* Avoid taking lock and disabling interrupts unnecessarily */1209	if (list_empty(&target_list))1210		return;1211 1212	spin_lock_irqsave(&target_list_lock, flags);1213	list_for_each_entry(nt, &target_list, list) {1214		if (!nt->extended && nt->enabled && netif_running(nt->np.dev)) {1215			/*1216			 * We nest this inside the for-each-target loop above1217			 * so that we're able to get as much logging out to1218			 * at least one target if we die inside here, instead1219			 * of unnecessarily keeping all targets in lock-step.1220			 */1221			tmp = msg;1222			for (left = len; left;) {1223				frag = min(left, MAX_PRINT_CHUNK);1224				netpoll_send_udp(&nt->np, tmp, frag);1225				tmp += frag;1226				left -= frag;1227			}1228		}1229	}1230	spin_unlock_irqrestore(&target_list_lock, flags);1231}1232 1233/* Allocate new target (from boot/module param) and setup netpoll for it */1234static struct netconsole_target *alloc_param_target(char *target_config,1235						    int cmdline_count)1236{1237	struct netconsole_target *nt;1238	int err;1239 1240	nt = alloc_and_init();1241	if (!nt) {1242		err = -ENOMEM;1243		goto fail;1244	}1245 1246	if (*target_config == '+') {1247		nt->extended = true;1248		target_config++;1249	}1250 1251	if (*target_config == 'r') {1252		if (!nt->extended) {1253			pr_err("Netconsole configuration error. Release feature requires extended log message");1254			err = -EINVAL;1255			goto fail;1256		}1257		nt->release = true;1258		target_config++;1259	}1260 1261	/* Parse parameters and setup netpoll */1262	err = netpoll_parse_options(&nt->np, target_config);1263	if (err)1264		goto fail;1265 1266	err = netpoll_setup(&nt->np);1267	if (err) {1268		pr_err("Not enabling netconsole for %s%d. Netpoll setup failed\n",1269		       NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);1270		if (!IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))1271			/* only fail if dynamic reconfiguration is set,1272			 * otherwise, keep the target in the list, but disabled.1273			 */1274			goto fail;1275	} else {1276		nt->enabled = true;1277	}1278	populate_configfs_item(nt, cmdline_count);1279 1280	return nt;1281 1282fail:1283	kfree(nt);1284	return ERR_PTR(err);1285}1286 1287/* Cleanup netpoll for given target (from boot/module param) and free it */1288static void free_param_target(struct netconsole_target *nt)1289{1290	netpoll_cleanup(&nt->np);1291	kfree(nt);1292}1293 1294static struct console netconsole_ext = {1295	.name	= "netcon_ext",1296	.flags	= CON_ENABLED | CON_EXTENDED,1297	.write	= write_ext_msg,1298};1299 1300static struct console netconsole = {1301	.name	= "netcon",1302	.flags	= CON_ENABLED,1303	.write	= write_msg,1304};1305 1306static int __init init_netconsole(void)1307{1308	int err;1309	struct netconsole_target *nt, *tmp;1310	unsigned int count = 0;1311	bool extended = false;1312	unsigned long flags;1313	char *target_config;1314	char *input = config;1315 1316	if (strnlen(input, MAX_PARAM_LENGTH)) {1317		while ((target_config = strsep(&input, ";"))) {1318			nt = alloc_param_target(target_config, count);1319			if (IS_ERR(nt)) {1320				if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))1321					continue;1322				err = PTR_ERR(nt);1323				goto fail;1324			}1325			/* Dump existing printks when we register */1326			if (nt->extended) {1327				extended = true;1328				netconsole_ext.flags |= CON_PRINTBUFFER;1329			} else {1330				netconsole.flags |= CON_PRINTBUFFER;1331			}1332 1333			spin_lock_irqsave(&target_list_lock, flags);1334			list_add(&nt->list, &target_list);1335			spin_unlock_irqrestore(&target_list_lock, flags);1336			count++;1337		}1338	}1339 1340	err = register_netdevice_notifier(&netconsole_netdev_notifier);1341	if (err)1342		goto fail;1343 1344	err = dynamic_netconsole_init();1345	if (err)1346		goto undonotifier;1347 1348	if (extended)1349		register_console(&netconsole_ext);1350	register_console(&netconsole);1351	pr_info("network logging started\n");1352 1353	return err;1354 1355undonotifier:1356	unregister_netdevice_notifier(&netconsole_netdev_notifier);1357 1358fail:1359	pr_err("cleaning up\n");1360 1361	/*1362	 * Remove all targets and destroy them (only targets created1363	 * from the boot/module option exist here). Skipping the list1364	 * lock is safe here, and netpoll_cleanup() will sleep.1365	 */1366	list_for_each_entry_safe(nt, tmp, &target_list, list) {1367		list_del(&nt->list);1368		free_param_target(nt);1369	}1370 1371	return err;1372}1373 1374static void __exit cleanup_netconsole(void)1375{1376	struct netconsole_target *nt, *tmp;1377 1378	if (console_is_registered(&netconsole_ext))1379		unregister_console(&netconsole_ext);1380	unregister_console(&netconsole);1381	dynamic_netconsole_exit();1382	unregister_netdevice_notifier(&netconsole_netdev_notifier);1383 1384	/*1385	 * Targets created via configfs pin references on our module1386	 * and would first be rmdir(2)'ed from userspace. We reach1387	 * here only when they are already destroyed, and only those1388	 * created from the boot/module option are left, so remove and1389	 * destroy them. Skipping the list lock is safe here, and1390	 * netpoll_cleanup() will sleep.1391	 */1392	list_for_each_entry_safe(nt, tmp, &target_list, list) {1393		list_del(&nt->list);1394		free_param_target(nt);1395	}1396}1397 1398/*1399 * Use late_initcall to ensure netconsole is1400 * initialized after network device driver if built-in.1401 *1402 * late_initcall() and module_init() are identical if built as module.1403 */1404late_initcall(init_netconsole);1405module_exit(cleanup_netconsole);1406