3288 lines · 79.4 KB · C
RawDownload
/* * 	NET3	Protocol independent device support routines. * *		This program is free software; you can redistribute it and/or *		modify it under the terms of the GNU General Public License *		as published by the Free Software Foundation; either version *		2 of the License, or (at your option) any later version. * *	Derived from the non IP parts of dev.c 1.0.19 * 		Authors:	Ross Biro *				Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> *				Mark Evans, <evansmp@uhura.aston.ac.uk> * *	Additional Authors: *		Florian la Roche <rzsfl@rz.uni-sb.de> *		Alan Cox <gw4pts@gw4pts.ampr.org> *		David Hinds <dahinds@users.sourceforge.net> *		Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> *		Adam Sulmicki <adam@cfar.umd.edu> *              Pekka Riikonen <priikone@poesidon.pspt.fi> * *	Changes: *              D.J. Barrow     :       Fixed bug where dev->refcnt gets set *              			to 2 if register_netdev gets called *              			before net_dev_init & also removed a *              			few lines of code in the process. *		Alan Cox	:	device private ioctl copies fields back. *		Alan Cox	:	Transmit queue code does relevant *					stunts to keep the queue safe. *		Alan Cox	:	Fixed double lock. *		Alan Cox	:	Fixed promisc NULL pointer trap *		????????	:	Support the full private ioctl range *		Alan Cox	:	Moved ioctl permission check into *					drivers *		Tim Kordas	:	SIOCADDMULTI/SIOCDELMULTI *		Alan Cox	:	100 backlog just doesn't cut it when *					you start doing multicast video 8) *		Alan Cox	:	Rewrote net_bh and list manager. *		Alan Cox	: 	Fix ETH_P_ALL echoback lengths. *		Alan Cox	:	Took out transmit every packet pass *					Saved a few bytes in the ioctl handler *		Alan Cox	:	Network driver sets packet type before *					calling netif_rx. Saves a function *					call a packet. *		Alan Cox	:	Hashed net_bh() *		Richard Kooijman:	Timestamp fixes. *		Alan Cox	:	Wrong field in SIOCGIFDSTADDR *		Alan Cox	:	Device lock protection. *		Alan Cox	: 	Fixed nasty side effect of device close *					changes. *		Rudi Cilibrasi	:	Pass the right thing to *					set_mac_address() *		Dave Miller	:	32bit quantity for the device lock to *					make it work out on a Sparc. *		Bjorn Ekwall	:	Added KERNELD hack. *		Alan Cox	:	Cleaned up the backlog initialise. *		Craig Metz	:	SIOCGIFCONF fix if space for under *					1 device. *	    Thomas Bogendoerfer :	Return ENODEV for dev_open, if there *					is no device open function. *		Andi Kleen	:	Fix error reporting for SIOCGIFCONF *	    Michael Chastain	:	Fix signed/unsigned for SIOCGIFCONF *		Cyrus Durgin	:	Cleaned for KMOD *		Adam Sulmicki   :	Bug Fix : Network Device Unload *					A network device unload needs to purge *					the backlog queue. *	Paul Rusty Russell	:	SIOCSIFNAME *              Pekka Riikonen  :	Netdev boot-time settings code *              Andrew Morton   :       Make unregister_netdevice wait *              			indefinitely on dev->refcnt * 		J Hadi Salim	:	- Backlog queue sampling *				        - netif_rx() feedback */ #include <asm/uaccess.h>#include <asm/system.h>#include <linux/bitops.h>#include <linux/config.h>#include <linux/cpu.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/socket.h>#include <linux/sockios.h>#include <linux/errno.h>#include <linux/interrupt.h>#include <linux/if_ether.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/notifier.h>#include <linux/skbuff.h>#include <net/sock.h>#include <linux/rtnetlink.h>#include <linux/proc_fs.h>#include <linux/seq_file.h>#include <linux/stat.h>#include <linux/if_bridge.h>#include <linux/divert.h>#include <net/dst.h>#include <net/pkt_sched.h>#include <net/checksum.h>#include <linux/highmem.h>#include <linux/init.h>#include <linux/kmod.h>#include <linux/module.h>#include <linux/kallsyms.h>#include <linux/netpoll.h>#include <linux/rcupdate.h>#include <linux/delay.h>#ifdef CONFIG_NET_RADIO#include <linux/wireless.h>		/* Note : will define WIRELESS_EXT */#include <net/iw_handler.h>#endif	/* CONFIG_NET_RADIO */#include <asm/current.h> /* *	The list of packet types we will receive (as opposed to discard) *	and the routines to invoke. * *	Why 16. Because with 16 the only overlap we get on a hash of the *	low nibble of the protocol value is RARP/SNAP/X.25. * *      NOTE:  That is no longer true with the addition of VLAN tags.  Not *             sure which should go first, but I bet it won't make much *             difference if we are running VLANs.  The good news is that *             this protocol won't be in the list unless compiled in, so *             the average user (w/out VLANs) will not be adversly affected. *             --BLG * *		0800	IP *		8100    802.1Q VLAN *		0001	802.3 *		0002	AX.25 *		0004	802.2 *		8035	RARP *		0005	SNAP *		0805	X.25 *		0806	ARP *		8137	IPX *		0009	Localtalk *		86DD	IPv6 */ static DEFINE_SPINLOCK(ptype_lock);static struct list_head ptype_base[16];	/* 16 way hashed list */static struct list_head ptype_all;		/* Taps */ /* * The @dev_base list is protected by @dev_base_lock and the rtln * semaphore. * * Pure readers hold dev_base_lock for reading. * * Writers must hold the rtnl semaphore while they loop through the * dev_base list, and hold dev_base_lock for writing when they do the * actual updates.  This allows pure readers to access the list even * while a writer is preparing to update it. * * To put it another way, dev_base_lock is held for writing only to * protect against pure readers; the rtnl semaphore provides the * protection against other writers. * * See, for example usages, register_netdevice() and * unregister_netdevice(), which must be called with the rtnl * semaphore held. */struct net_device *dev_base;static struct net_device **dev_tail = &dev_base;DEFINE_RWLOCK(dev_base_lock); EXPORT_SYMBOL(dev_base);EXPORT_SYMBOL(dev_base_lock); #define NETDEV_HASHBITS	8static struct hlist_head dev_name_head[1<<NETDEV_HASHBITS];static struct hlist_head dev_index_head[1<<NETDEV_HASHBITS]; static inline struct hlist_head *dev_name_hash(const char *name){	unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ));	return &dev_name_head[hash & ((1<<NETDEV_HASHBITS)-1)];} static inline struct hlist_head *dev_index_hash(int ifindex){	return &dev_index_head[ifindex & ((1<<NETDEV_HASHBITS)-1)];} /* *	Our notifier list */ static struct notifier_block *netdev_chain; /* *	Device drivers call our routines to queue packets here. We empty the *	queue in the local softnet handler. */DEFINE_PER_CPU(struct softnet_data, softnet_data) = { NULL }; #ifdef CONFIG_SYSFSextern int netdev_sysfs_init(void);extern int netdev_register_sysfs(struct net_device *);extern void netdev_unregister_sysfs(struct net_device *);#else#define netdev_sysfs_init()	 	(0)#define netdev_register_sysfs(dev)	(0)#define	netdev_unregister_sysfs(dev)	do { } while(0)#endif  /******************************************************************************* 		Protocol management and registration routines *******************************************************************************/ /* *	For efficiency */ int netdev_nit; /* *	Add a protocol ID to the list. Now that the input handler is *	smarter we can dispense with all the messy stuff that used to be *	here. * *	BEWARE!!! Protocol handlers, mangling input packets, *	MUST BE last in hash buckets and checking protocol handlers *	MUST start from promiscuous ptype_all chain in net_bh. *	It is true now, do not change it. *	Explanation follows: if protocol handler, mangling packet, will *	be the first on list, it is not able to sense, that packet *	is cloned and should be copied-on-write, so that it will *	change it and subsequent readers will get broken packet. *							--ANK (980803) */ /** *	dev_add_pack - add packet handler *	@pt: packet type declaration * *	Add a protocol handler to the networking stack. The passed &packet_type *	is linked into kernel lists and may not be freed until it has been *	removed from the kernel lists. * *	This call does not sleep therefore it can not  *	guarantee all CPU's that are in middle of receiving packets *	will see the new packet type (until the next received packet). */ void dev_add_pack(struct packet_type *pt){	int hash; 	spin_lock_bh(&ptype_lock);	if (pt->type == htons(ETH_P_ALL)) {		netdev_nit++;		list_add_rcu(&pt->list, &ptype_all);	} else {		hash = ntohs(pt->type) & 15;		list_add_rcu(&pt->list, &ptype_base[hash]);	}	spin_unlock_bh(&ptype_lock);} /** *	__dev_remove_pack	 - remove packet handler *	@pt: packet type declaration * *	Remove a protocol handler that was previously added to the kernel *	protocol handlers by dev_add_pack(). The passed &packet_type is removed *	from the kernel lists and can be freed or reused once this function *	returns.  * *      The packet type might still be in use by receivers *	and must not be freed until after all the CPU's have gone *	through a quiescent state. */void __dev_remove_pack(struct packet_type *pt){	struct list_head *head;	struct packet_type *pt1; 	spin_lock_bh(&ptype_lock); 	if (pt->type == htons(ETH_P_ALL)) {		netdev_nit--;		head = &ptype_all;	} else		head = &ptype_base[ntohs(pt->type) & 15]; 	list_for_each_entry(pt1, head, list) {		if (pt == pt1) {			list_del_rcu(&pt->list);			goto out;		}	} 	printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt);out:	spin_unlock_bh(&ptype_lock);}/** *	dev_remove_pack	 - remove packet handler *	@pt: packet type declaration * *	Remove a protocol handler that was previously added to the kernel *	protocol handlers by dev_add_pack(). The passed &packet_type is removed *	from the kernel lists and can be freed or reused once this function *	returns. * *	This call sleeps to guarantee that no CPU is looking at the packet *	type after return. */void dev_remove_pack(struct packet_type *pt){	__dev_remove_pack(pt);		synchronize_net();} /****************************************************************************** 		      Device Boot-time Settings Routines *******************************************************************************/ /* Boot time configuration table */static struct netdev_boot_setup dev_boot_setup[NETDEV_BOOT_SETUP_MAX]; /** *	netdev_boot_setup_add	- add new setup entry *	@name: name of the device *	@map: configured settings for the device * *	Adds new setup entry to the dev_boot_setup list.  The function *	returns 0 on error and 1 on success.  This is a generic routine to *	all netdevices. */static int netdev_boot_setup_add(char *name, struct ifmap *map){	struct netdev_boot_setup *s;	int i; 	s = dev_boot_setup;	for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) {		if (s[i].name[0] == '\0' || s[i].name[0] == ' ') {			memset(s[i].name, 0, sizeof(s[i].name));			strcpy(s[i].name, name);			memcpy(&s[i].map, map, sizeof(s[i].map));			break;		}	} 	return i >= NETDEV_BOOT_SETUP_MAX ? 0 : 1;} /** *	netdev_boot_setup_check	- check boot time settings *	@dev: the netdevice * * 	Check boot time settings for the device. *	The found settings are set for the device to be used *	later in the device probing. *	Returns 0 if no settings found, 1 if they are. */int netdev_boot_setup_check(struct net_device *dev){	struct netdev_boot_setup *s = dev_boot_setup;	int i; 	for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) {		if (s[i].name[0] != '\0' && s[i].name[0] != ' ' &&		    !strncmp(dev->name, s[i].name, strlen(s[i].name))) {			dev->irq 	= s[i].map.irq;			dev->base_addr 	= s[i].map.base_addr;			dev->mem_start 	= s[i].map.mem_start;			dev->mem_end 	= s[i].map.mem_end;			return 1;		}	}	return 0;}  /** *	netdev_boot_base	- get address from boot time settings *	@prefix: prefix for network device *	@unit: id for network device * * 	Check boot time settings for the base address of device. *	The found settings are set for the device to be used *	later in the device probing. *	Returns 0 if no settings found. */unsigned long netdev_boot_base(const char *prefix, int unit){	const struct netdev_boot_setup *s = dev_boot_setup;	char name[IFNAMSIZ];	int i; 	sprintf(name, "%s%d", prefix, unit); 	/*	 * If device already registered then return base of 1	 * to indicate not to probe for this interface	 */	if (__dev_get_by_name(name))		return 1; 	for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++)		if (!strcmp(name, s[i].name))			return s[i].map.base_addr;	return 0;} /* * Saves at boot time configured settings for any netdevice. */int __init netdev_boot_setup(char *str){	int ints[5];	struct ifmap map; 	str = get_options(str, ARRAY_SIZE(ints), ints);	if (!str || !*str)		return 0; 	/* Save settings */	memset(&map, 0, sizeof(map));	if (ints[0] > 0)		map.irq = ints[1];	if (ints[0] > 1)		map.base_addr = ints[2];	if (ints[0] > 2)		map.mem_start = ints[3];	if (ints[0] > 3)		map.mem_end = ints[4]; 	/* Add new entry to the list */	return netdev_boot_setup_add(str, &map);} __setup("netdev=", netdev_boot_setup); /******************************************************************************* 			    Device Interface Subroutines *******************************************************************************/ /** *	__dev_get_by_name	- find a device by its name *	@name: name to find * *	Find an interface by name. Must be called under RTNL semaphore *	or @dev_base_lock. If the name is found a pointer to the device *	is returned. If the name is not found then %NULL is returned. The *	reference counters are not incremented so the caller must be *	careful with locks. */ struct net_device *__dev_get_by_name(const char *name){	struct hlist_node *p; 	hlist_for_each(p, dev_name_hash(name)) {		struct net_device *dev			= hlist_entry(p, struct net_device, name_hlist);		if (!strncmp(dev->name, name, IFNAMSIZ))			return dev;	}	return NULL;} /** *	dev_get_by_name		- find a device by its name *	@name: name to find * *	Find an interface by name. This can be called from any *	context and does its own locking. The returned handle has *	the usage count incremented and the caller must use dev_put() to *	release it when it is no longer needed. %NULL is returned if no *	matching device is found. */ struct net_device *dev_get_by_name(const char *name){	struct net_device *dev; 	read_lock(&dev_base_lock);	dev = __dev_get_by_name(name);	if (dev)		dev_hold(dev);	read_unlock(&dev_base_lock);	return dev;

Lines 1–500 of 3288.