5690 lines · 136.7 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* * INET		An implementation of the TCP/IP protocol suite for the LINUX *		operating system.  INET is implemented using the  BSD Socket *		interface as the means of communication with the user level. * *		Routing netlink socket interface: protocol independent part. * * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> * *	Fixes: *	Vitaly E. Lavrov		RTA_OK arithmetics was wrong. */ #include <linux/bitops.h>#include <linux/errno.h>#include <linux/module.h>#include <linux/types.h>#include <linux/socket.h>#include <linux/kernel.h>#include <linux/timer.h>#include <linux/string.h>#include <linux/sockios.h>#include <linux/net.h>#include <linux/fcntl.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/capability.h>#include <linux/skbuff.h>#include <linux/init.h>#include <linux/security.h>#include <linux/mutex.h>#include <linux/if_addr.h>#include <linux/if_bridge.h>#include <linux/if_vlan.h>#include <linux/pci.h>#include <linux/etherdevice.h>#include <linux/bpf.h> #include <linux/uaccess.h> #include <linux/inet.h>#include <linux/netdevice.h>#include <net/ip.h>#include <net/protocol.h>#include <net/arp.h>#include <net/route.h>#include <net/udp.h>#include <net/tcp.h>#include <net/sock.h>#include <net/pkt_sched.h>#include <net/fib_rules.h>#include <net/rtnetlink.h>#include <net/net_namespace.h> #define RTNL_MAX_TYPE		50#define RTNL_SLAVE_MAX_TYPE	40 struct rtnl_link {	rtnl_doit_func		doit;	rtnl_dumpit_func	dumpit;	struct module		*owner;	unsigned int		flags;	struct rcu_head		rcu;}; static DEFINE_MUTEX(rtnl_mutex); void rtnl_lock(void){	mutex_lock(&rtnl_mutex);}EXPORT_SYMBOL(rtnl_lock); int rtnl_lock_killable(void){	return mutex_lock_killable(&rtnl_mutex);}EXPORT_SYMBOL(rtnl_lock_killable); static struct sk_buff *defer_kfree_skb_list;void rtnl_kfree_skbs(struct sk_buff *head, struct sk_buff *tail){	if (head && tail) {		tail->next = defer_kfree_skb_list;		defer_kfree_skb_list = head;	}}EXPORT_SYMBOL(rtnl_kfree_skbs); void __rtnl_unlock(void){	struct sk_buff *head = defer_kfree_skb_list; 	defer_kfree_skb_list = NULL; 	mutex_unlock(&rtnl_mutex); 	while (head) {		struct sk_buff *next = head->next; 		kfree_skb(head);		cond_resched();		head = next;	}} void rtnl_unlock(void){	/* This fellow will unlock it for us. */	netdev_run_todo();}EXPORT_SYMBOL(rtnl_unlock); int rtnl_trylock(void){	return mutex_trylock(&rtnl_mutex);}EXPORT_SYMBOL(rtnl_trylock); int rtnl_is_locked(void){	return mutex_is_locked(&rtnl_mutex);}EXPORT_SYMBOL(rtnl_is_locked); bool refcount_dec_and_rtnl_lock(refcount_t *r){	return refcount_dec_and_mutex_lock(r, &rtnl_mutex);}EXPORT_SYMBOL(refcount_dec_and_rtnl_lock); #ifdef CONFIG_PROVE_LOCKINGbool lockdep_rtnl_is_held(void){	return lockdep_is_held(&rtnl_mutex);}EXPORT_SYMBOL(lockdep_rtnl_is_held);#endif /* #ifdef CONFIG_PROVE_LOCKING */ static struct rtnl_link __rcu *__rcu *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1]; static inline int rtm_msgindex(int msgtype){	int msgindex = msgtype - RTM_BASE; 	/*	 * msgindex < 0 implies someone tried to register a netlink	 * control code. msgindex >= RTM_NR_MSGTYPES may indicate that	 * the message type has not been added to linux/rtnetlink.h	 */	BUG_ON(msgindex < 0 || msgindex >= RTM_NR_MSGTYPES); 	return msgindex;} static struct rtnl_link *rtnl_get_link(int protocol, int msgtype){	struct rtnl_link __rcu **tab; 	if (protocol >= ARRAY_SIZE(rtnl_msg_handlers))		protocol = PF_UNSPEC; 	tab = rcu_dereference_rtnl(rtnl_msg_handlers[protocol]);	if (!tab)		tab = rcu_dereference_rtnl(rtnl_msg_handlers[PF_UNSPEC]); 	return rcu_dereference_rtnl(tab[msgtype]);} static int rtnl_register_internal(struct module *owner,				  int protocol, int msgtype,				  rtnl_doit_func doit, rtnl_dumpit_func dumpit,				  unsigned int flags){	struct rtnl_link *link, *old;	struct rtnl_link __rcu **tab;	int msgindex;	int ret = -ENOBUFS; 	BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX);	msgindex = rtm_msgindex(msgtype); 	rtnl_lock();	tab = rtnl_dereference(rtnl_msg_handlers[protocol]);	if (tab == NULL) {		tab = kcalloc(RTM_NR_MSGTYPES, sizeof(void *), GFP_KERNEL);		if (!tab)			goto unlock; 		/* ensures we see the 0 stores */		rcu_assign_pointer(rtnl_msg_handlers[protocol], tab);	} 	old = rtnl_dereference(tab[msgindex]);	if (old) {		link = kmemdup(old, sizeof(*old), GFP_KERNEL);		if (!link)			goto unlock;	} else {		link = kzalloc(sizeof(*link), GFP_KERNEL);		if (!link)			goto unlock;	} 	WARN_ON(link->owner && link->owner != owner);	link->owner = owner; 	WARN_ON(doit && link->doit && link->doit != doit);	if (doit)		link->doit = doit;	WARN_ON(dumpit && link->dumpit && link->dumpit != dumpit);	if (dumpit)		link->dumpit = dumpit; 	link->flags |= flags; 	/* publish protocol:msgtype */	rcu_assign_pointer(tab[msgindex], link);	ret = 0;	if (old)		kfree_rcu(old, rcu);unlock:	rtnl_unlock();	return ret;} /** * rtnl_register_module - Register a rtnetlink message type * * @owner: module registering the hook (THIS_MODULE) * @protocol: Protocol family or PF_UNSPEC * @msgtype: rtnetlink message type * @doit: Function pointer called for each request message * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message * @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions * * Like rtnl_register, but for use by removable modules. */int rtnl_register_module(struct module *owner,			 int protocol, int msgtype,			 rtnl_doit_func doit, rtnl_dumpit_func dumpit,			 unsigned int flags){	return rtnl_register_internal(owner, protocol, msgtype,				      doit, dumpit, flags);}EXPORT_SYMBOL_GPL(rtnl_register_module); /** * rtnl_register - Register a rtnetlink message type * @protocol: Protocol family or PF_UNSPEC * @msgtype: rtnetlink message type * @doit: Function pointer called for each request message * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message * @flags: rtnl_link_flags to modifiy behaviour of doit/dumpit functions * * Registers the specified function pointers (at least one of them has * to be non-NULL) to be called whenever a request message for the * specified protocol family and message type is received. * * The special protocol family PF_UNSPEC may be used to define fallback * function pointers for the case when no entry for the specific protocol * family exists. */void rtnl_register(int protocol, int msgtype,		   rtnl_doit_func doit, rtnl_dumpit_func dumpit,		   unsigned int flags){	int err; 	err = rtnl_register_internal(NULL, protocol, msgtype, doit, dumpit,				     flags);	if (err)		pr_err("Unable to register rtnetlink message handler, "		       "protocol = %d, message type = %d\n", protocol, msgtype);} /** * rtnl_unregister - Unregister a rtnetlink message type * @protocol: Protocol family or PF_UNSPEC * @msgtype: rtnetlink message type * * Returns 0 on success or a negative error code. */int rtnl_unregister(int protocol, int msgtype){	struct rtnl_link __rcu **tab;	struct rtnl_link *link;	int msgindex; 	BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX);	msgindex = rtm_msgindex(msgtype); 	rtnl_lock();	tab = rtnl_dereference(rtnl_msg_handlers[protocol]);	if (!tab) {		rtnl_unlock();		return -ENOENT;	} 	link = rtnl_dereference(tab[msgindex]);	rcu_assign_pointer(tab[msgindex], NULL);	rtnl_unlock(); 	kfree_rcu(link, rcu); 	return 0;}EXPORT_SYMBOL_GPL(rtnl_unregister); /** * rtnl_unregister_all - Unregister all rtnetlink message type of a protocol * @protocol : Protocol family or PF_UNSPEC * * Identical to calling rtnl_unregster() for all registered message types * of a certain protocol family. */void rtnl_unregister_all(int protocol){	struct rtnl_link __rcu **tab;	struct rtnl_link *link;	int msgindex; 	BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); 	rtnl_lock();	tab = rtnl_dereference(rtnl_msg_handlers[protocol]);	if (!tab) {		rtnl_unlock();		return;	}	RCU_INIT_POINTER(rtnl_msg_handlers[protocol], NULL);	for (msgindex = 0; msgindex < RTM_NR_MSGTYPES; msgindex++) {		link = rtnl_dereference(tab[msgindex]);		if (!link)			continue; 		rcu_assign_pointer(tab[msgindex], NULL);		kfree_rcu(link, rcu);	}	rtnl_unlock(); 	synchronize_net(); 	kfree(tab);}EXPORT_SYMBOL_GPL(rtnl_unregister_all); static LIST_HEAD(link_ops); static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind){	const struct rtnl_link_ops *ops; 	list_for_each_entry(ops, &link_ops, list) {		if (!strcmp(ops->kind, kind))			return ops;	}	return NULL;} /** * __rtnl_link_register - Register rtnl_link_ops with rtnetlink. * @ops: struct rtnl_link_ops * to register * * The caller must hold the rtnl_mutex. This function should be used * by drivers that create devices during module initialization. It * must be called before registering the devices. * * Returns 0 on success or a negative error code. */int __rtnl_link_register(struct rtnl_link_ops *ops){	if (rtnl_link_ops_get(ops->kind))		return -EEXIST; 	/* The check for setup is here because if ops	 * does not have that filled up, it is not possible	 * to use the ops for creating device. So do not	 * fill up dellink as well. That disables rtnl_dellink.	 */	if (ops->setup && !ops->dellink)		ops->dellink = unregister_netdevice_queue; 	list_add_tail(&ops->list, &link_ops);	return 0;}EXPORT_SYMBOL_GPL(__rtnl_link_register); /** * rtnl_link_register - Register rtnl_link_ops with rtnetlink. * @ops: struct rtnl_link_ops * to register * * Returns 0 on success or a negative error code. */int rtnl_link_register(struct rtnl_link_ops *ops){	int err; 	/* Sanity-check max sizes to avoid stack buffer overflow. */	if (WARN_ON(ops->maxtype > RTNL_MAX_TYPE ||		    ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE))		return -EINVAL; 	rtnl_lock();	err = __rtnl_link_register(ops);	rtnl_unlock();	return err;}EXPORT_SYMBOL_GPL(rtnl_link_register); static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops){	struct net_device *dev;	LIST_HEAD(list_kill); 	for_each_netdev(net, dev) {		if (dev->rtnl_link_ops == ops)			ops->dellink(dev, &list_kill);	}	unregister_netdevice_many(&list_kill);} /** * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. * @ops: struct rtnl_link_ops * to unregister * * The caller must hold the rtnl_mutex and guarantee net_namespace_list * integrity (hold pernet_ops_rwsem for writing to close the race * with setup_net() and cleanup_net()). */void __rtnl_link_unregister(struct rtnl_link_ops *ops){	struct net *net; 	for_each_net(net) {		__rtnl_kill_links(net, ops);	}	list_del(&ops->list);}EXPORT_SYMBOL_GPL(__rtnl_link_unregister); /* Return with the rtnl_lock held when there are no network * devices unregistering in any network namespace. */static void rtnl_lock_unregistering_all(void){	struct net *net;	bool unregistering;	DEFINE_WAIT_FUNC(wait, woken_wake_function); 	add_wait_queue(&netdev_unregistering_wq, &wait);	for (;;) {		unregistering = false;		rtnl_lock();		/* We held write locked pernet_ops_rwsem, and parallel		 * setup_net() and cleanup_net() are not possible.		 */		for_each_net(net) {			if (net->dev_unreg_count > 0) {				unregistering = true;				break;			}		}		if (!unregistering)			break;		__rtnl_unlock(); 		wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);	}	remove_wait_queue(&netdev_unregistering_wq, &wait);} /** * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. * @ops: struct rtnl_link_ops * to unregister */void rtnl_link_unregister(struct rtnl_link_ops *ops){	/* Close the race with setup_net() and cleanup_net() */	down_write(&pernet_ops_rwsem);	rtnl_lock_unregistering_all();	__rtnl_link_unregister(ops);	rtnl_unlock();	up_write(&pernet_ops_rwsem);}EXPORT_SYMBOL_GPL(rtnl_link_unregister); static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev){	struct net_device *master_dev;	const struct rtnl_link_ops *ops;	size_t size = 0; 	rcu_read_lock(); 	master_dev = netdev_master_upper_dev_get_rcu((struct net_device *)dev);	if (!master_dev)

Lines 1–500 of 5690.