⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dev.c

📁 GNU Hurd 源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		dev_mc_upload(dev);		printk(KERN_INFO "device %s %s promiscuous mode\n",		       dev->name, (dev->flags&IFF_PROMISC) ? "entered" : "left");	}}void dev_set_allmulti(struct device *dev, int inc){	unsigned short old_flags = dev->flags;	dev->flags |= IFF_ALLMULTI;	if ((dev->allmulti += inc) == 0)		dev->flags &= ~IFF_ALLMULTI;	if (dev->flags^old_flags)		dev_mc_upload(dev);}int dev_change_flags(struct device *dev, unsigned flags){	int ret;	int old_flags = dev->flags;	/*	 *	Set the flags on our device.	 */	dev->flags = (flags & (IFF_DEBUG|IFF_NOTRAILERS|IFF_RUNNING|IFF_NOARP|			       IFF_SLAVE|IFF_MASTER|IFF_DYNAMIC|			       IFF_MULTICAST|IFF_PORTSEL|IFF_AUTOMEDIA)) |				       (dev->flags & (IFF_UP|IFF_VOLATILE|IFF_PROMISC|IFF_ALLMULTI));	/*	 *	Load in the correct multicast list now the flags have changed.	 */	dev_mc_upload(dev);	/*	 *	Have we downed the interface. We handle IFF_UP ourselves	 *	according to user attempts to set it, rather than blindly	 *	setting it.	 */	ret = 0;	if ((old_flags^flags)&IFF_UP)	/* Bit is different  ? */	{		ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);		if (ret == 0)			dev_mc_upload(dev);	}	if (dev->flags&IFF_UP &&	    ((old_flags^dev->flags)&~(IFF_UP|IFF_RUNNING|IFF_PROMISC|IFF_ALLMULTI|IFF_VOLATILE)))		notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);	if ((flags^dev->gflags)&IFF_PROMISC) {		int inc = (flags&IFF_PROMISC) ? +1 : -1;		dev->gflags ^= IFF_PROMISC;		dev_set_promiscuity(dev, inc);	}	/* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI	   is important. Some (broken) drivers set IFF_PROMISC, when	   IFF_ALLMULTI is requested not asking us and not reporting.	 */	if ((flags^dev->gflags)&IFF_ALLMULTI) {		int inc = (flags&IFF_ALLMULTI) ? +1 : -1;		dev->gflags ^= IFF_ALLMULTI;		dev_set_allmulti(dev, inc);	}	return ret;}#ifdef _HURD_#define dev_ioctl 0#else/* *	Perform the SIOCxIFxxx calls. */static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd){	struct device *dev;	int err;	if ((dev = dev_get(ifr->ifr_name)) == NULL)		return -ENODEV;	switch(cmd)	{		case SIOCGIFFLAGS:	/* Get interface flags */			ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))				|(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));			return 0;		case SIOCSIFFLAGS:	/* Set interface flags */			return dev_change_flags(dev, ifr->ifr_flags);		case SIOCGIFMETRIC:	/* Get the metric on the interface (currently unused) */			ifr->ifr_metric = 0;			return 0;		case SIOCSIFMETRIC:	/* Set the metric on the interface (currently unused) */			return -EOPNOTSUPP;		case SIOCGIFMTU:	/* Get the MTU of a device */			ifr->ifr_mtu = dev->mtu;			return 0;		case SIOCSIFMTU:	/* Set the MTU of a device */			if (ifr->ifr_mtu == dev->mtu)				return 0;			/*			 *	MTU must be positive.			 */			if (ifr->ifr_mtu<=0)				return -EINVAL;			if (dev->change_mtu)				err = dev->change_mtu(dev, ifr->ifr_mtu);			else {				dev->mtu = ifr->ifr_mtu;				err = 0;			}			if (!err && dev->flags&IFF_UP)				notifier_call_chain(&netdev_chain, NETDEV_CHANGEMTU, dev);			return err;		case SIOCGIFHWADDR:			memcpy(ifr->ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN);			ifr->ifr_hwaddr.sa_family=dev->type;			return 0;		case SIOCSIFHWADDR:			if(dev->set_mac_address==NULL)				return -EOPNOTSUPP;			if(ifr->ifr_hwaddr.sa_family!=dev->type)				return -EINVAL;			err=dev->set_mac_address(dev,&ifr->ifr_hwaddr);			if (!err)				notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);			return err;		case SIOCSIFHWBROADCAST:			if(ifr->ifr_hwaddr.sa_family!=dev->type)				return -EINVAL;			memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, MAX_ADDR_LEN);			notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);			return 0;		case SIOCGIFMAP:			ifr->ifr_map.mem_start=dev->mem_start;			ifr->ifr_map.mem_end=dev->mem_end;			ifr->ifr_map.base_addr=dev->base_addr;			ifr->ifr_map.irq=dev->irq;			ifr->ifr_map.dma=dev->dma;			ifr->ifr_map.port=dev->if_port;			return 0;		case SIOCSIFMAP:			if (dev->set_config)				return dev->set_config(dev,&ifr->ifr_map);			return -EOPNOTSUPP;		case SIOCADDMULTI:			if(dev->set_multicast_list==NULL ||			   ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)				return -EINVAL;			dev_mc_add(dev,ifr->ifr_hwaddr.sa_data, dev->addr_len, 1);			return 0;		case SIOCDELMULTI:			if(dev->set_multicast_list==NULL ||			   ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)				return -EINVAL;			dev_mc_delete(dev,ifr->ifr_hwaddr.sa_data,dev->addr_len, 1);			return 0;		case SIOCGIFINDEX:			ifr->ifr_ifindex = dev->ifindex;			return 0;		case SIOCGIFTXQLEN:			ifr->ifr_qlen = dev->tx_queue_len;			return 0;		case SIOCSIFTXQLEN:			if(ifr->ifr_qlen<0)				return -EINVAL;			dev->tx_queue_len = ifr->ifr_qlen;			return 0;		case SIOCSIFNAME:			if (dev->flags&IFF_UP)				return -EBUSY;			if (dev_get(ifr->ifr_newname))				return -EEXIST;			memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);			dev->name[IFNAMSIZ-1] = 0;			notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);			return 0;		/*		 *	Unknown or private ioctl		 */		default:			if(cmd >= SIOCDEVPRIVATE &&			   cmd <= SIOCDEVPRIVATE + 15) {				if (dev->do_ioctl)					return dev->do_ioctl(dev, ifr, cmd);				return -EOPNOTSUPP;			}#ifdef CONFIG_NET_RADIO			if(cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {				if (dev->do_ioctl)					return dev->do_ioctl(dev, ifr, cmd);				return -EOPNOTSUPP;			}#endif	/* CONFIG_NET_RADIO */	}	return -EINVAL;}/* *	This function handles all "interface"-type I/O control requests. The actual *	'doing' part of this is dev_ifsioc above. */int dev_ioctl(unsigned int cmd, void *arg){	struct ifreq ifr;	int ret;	char *colon;	/* One special case: SIOCGIFCONF takes ifconf argument	   and requires shared lock, because it sleeps writing	   to user space.	 */	if (cmd == SIOCGIFCONF) {		rtnl_shlock();		ret = dev_ifconf((char *) arg);		rtnl_shunlock();		return ret;	}	if (cmd == SIOCGIFNAME) {		return dev_ifname((struct ifreq *)arg);	}	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))		return -EFAULT;	ifr.ifr_name[IFNAMSIZ-1] = 0;	colon = strchr(ifr.ifr_name, ':');	if (colon)		*colon = 0;	/*	 *	See which interface the caller is talking about.	 */	switch(cmd)	{		/*		 *	These ioctl calls:		 *	- can be done by all.		 *	- atomic and do not require locking.		 *	- return a value		 */		case SIOCGIFFLAGS:		case SIOCGIFMETRIC:		case SIOCGIFMTU:		case SIOCGIFHWADDR:		case SIOCGIFSLAVE:		case SIOCGIFMAP:		case SIOCGIFINDEX:		case SIOCGIFTXQLEN:			dev_load(ifr.ifr_name);			ret = dev_ifsioc(&ifr, cmd);			if (!ret) {				if (colon)					*colon = ':';				if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))					return -EFAULT;			}			return ret;		/*		 *	These ioctl calls:		 *	- require superuser power.		 *	- require strict serialization.		 *	- do not return a value		 */		case SIOCSIFFLAGS:		case SIOCSIFMETRIC:		case SIOCSIFMTU:		case SIOCSIFMAP:		case SIOCSIFHWADDR:		case SIOCSIFSLAVE:		case SIOCADDMULTI:		case SIOCDELMULTI:		case SIOCSIFHWBROADCAST:		case SIOCSIFTXQLEN:		case SIOCSIFNAME:			if (!capable(CAP_NET_ADMIN))				return -EPERM;			dev_load(ifr.ifr_name);			rtnl_lock();			ret = dev_ifsioc(&ifr, cmd);			rtnl_unlock();			return ret;		case SIOCGIFMEM:			/* Get the per device memory space. We can add this but currently			   do not support it */		case SIOCSIFMEM:			/* Set the per device memory buffer space. Not applicable in our case */		case SIOCSIFLINK:			return -EINVAL;		/*		 *	Unknown or private ioctl.		 */		default:			if (cmd >= SIOCDEVPRIVATE &&			    cmd <= SIOCDEVPRIVATE + 15) {				dev_load(ifr.ifr_name);				rtnl_lock();				ret = dev_ifsioc(&ifr, cmd);				rtnl_unlock();				if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))					return -EFAULT;				return ret;			}#ifdef CONFIG_NET_RADIO			if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {				dev_load(ifr.ifr_name);				if (IW_IS_SET(cmd)) {					if (!suser())						return -EPERM;					rtnl_lock();				}				ret = dev_ifsioc(&ifr, cmd);				if (IW_IS_SET(cmd))					rtnl_unlock();				if (!ret && IW_IS_GET(cmd) &&				    copy_to_user(arg, &ifr, sizeof(struct ifreq)))					return -EFAULT;				return ret;			}#endif	/* CONFIG_NET_RADIO */			return -EINVAL;	}}#endifint dev_new_index(void){	static int ifindex;	for (;;) {		if (++ifindex <= 0)			ifindex=1;		if (dev_get_by_index(ifindex) == NULL)			return ifindex;	}}static int dev_boot_phase = 1;int register_netdevice(struct device *dev){	struct device *d, **dp;	if (dev_boot_phase) {		/* This is NOT bug, but I am not sure, that all the		   devices, initialized before netdev module is started		   are sane.		   Now they are chained to device boot list		   and probed later. If a module is initialized		   before netdev, but assumes that dev->init		   is really called by register_netdev(), it will fail.		   So that this message should be printed for a while.		 */		printk(KERN_INFO "early initialization of device %s is deferred\n", dev->name);		/* Check for existence, and append to tail of chain */		for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {			if (d == dev || strcmp(d->name, dev->name) == 0)				return -EEXIST;		}		dev->next = NULL;		*dp = dev;		return 0;	}	dev->iflink = -1;	/* Init, if this function is available */	if (dev->init && dev->init(dev) != 0)		return -EIO;	/* Check for existence, and append to tail of chain */	for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {		if (d == dev || strcmp(d->name, dev->name) == 0)			return -EEXIST;	}	dev->next = NULL;	dev_init_scheduler(dev);	dev->ifindex = dev_new_index();	if (dev->iflink == -1)		dev->iflink = dev->ifindex;	*dp = dev;	/* Notify protocols, that a new device appeared. */	notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);	return 0;}int unregister_netdevice(struct device *dev){	struct device *d, **dp;	if (dev_boot_phase == 0) {		/* If device is running, close it.		   It is very bad idea, really we should		   complain loudly here, but random hackery		   in linux/drivers/net likes it.		 */		if (dev->flags & IFF_UP)			dev_close(dev);#ifdef CONFIG_NET_FASTROUTE		dev_clear_fastroute(dev);#endif		/* Shutdown queueing discipline. */		dev_shutdown(dev);		/* Notify protocols, that we are about to destroy		   this device. They should clean all the things.		 */		notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);		/*		 *	Flush the multicast chain		 */		dev_mc_discard(dev);		/* To avoid pointers looking to nowhere,		   we wait for end of critical section */		dev_lock_wait();	}	/* And unlink it from device chain. */	for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) {		if (d == dev) {			*dp = d->next;			synchronize_bh();			d->next = NULL;			if (dev->destructor)				dev->destructor(dev);			return 0;		}	}	return -ENODEV;}/* *	Initialize the DEV module. At boot time this walks the device list and *	unhooks any devices that fail to initialise (normally hardware not *	present) and leaves us with a valid list of present and active devices. * */extern int lance_init(void);extern int bpq_init(void);extern int scc_init(void);extern void sdla_setup(void);extern void sdla_c_setup(void);extern void dlci_setup(void);extern int dmascc_init(void);extern int sm_init(void);extern int baycom_ser_fdx_init(void);extern int baycom_ser_hdx_init(void);extern int baycom_par_init(void);extern int lapbeth_init(void);extern int comx_init(void);extern void arcnet_init(void);extern void ip_auto_config(void);#ifdef CONFIG_8xxextern int cpm_enet_init(void);#endif /* CONFIG_8xx */#ifdef CONFIG_PROC_FSstatic struct proc_dir_entry proc_net_dev = {	PROC_NET_DEV, 3, "dev",	S_IFREG | S_IRUGO, 1, 0, 0,	0, &proc_net_inode_operations,	dev_get_info};#endif#ifdef CONFIG_NET_RADIO#ifdef CONFIG_PROC_FSstatic struct proc_dir_entry proc_net_wireless = {	PROC_NET_WIRELESS, 8, "wireless",	S_IFREG | S_IRUGO, 1, 0, 0,	0, &proc_net_inode_operations,	dev_get_wireless_info};#endif	/* CONFIG_PROC_FS */#endif	/* CONFIG_NET_RADIO */__initfunc(int net_dev_init(void)){	struct device *dev, **dp;#ifdef CONFIG_NET_SCHED	pktsched_init();#endif	/*	 *	Initialise the packet receive queue.	 */	skb_queue_head_init(&backlog);	/*	 *	The bridge has to be up before the devices	 */#ifdef CONFIG_BRIDGE	br_init();#endif	/*	 * This is Very Ugly(tm).	 *	 * Some devices want to be initialized early..	 */#if defined(CONFIG_SCC)	scc_init();#endif#if defined(CONFIG_DMASCC)	dmascc_init();#endif#if defined(CONFIG_BPQETHER)	bpq_init();#endif#if defined(CONFIG_DLCI)	dlci_setup();#endif#if defined(CONFIG_SDLA)	sdla_c_setup();#endif#if defined(CONFIG_BAYCOM_PAR)	baycom_par_init();#endif#if defined(CONFIG_BAYCOM_SER_FDX)	baycom_ser_fdx_init();#endif#if defined(CONFIG_BAYCOM_SER_HDX)	baycom_ser_hdx_init();#endif#if defined(CONFIG_SOUNDMODEM)	sm_init();#endif#if defined(CONFIG_LAPBETHER)	lapbeth_init();#endif#if defined(CONFIG_PLIP)	plip_init();#endif#if defined(CONFIG_ARCNET)	arcnet_init();#endif#if defined(CONFIG_8xx)        cpm_enet_init();#endif#if defined(CONFIG_COMX)	comx_init();#endif	/*	 *	SLHC if present needs attaching so other people see it	 *	even if not opened.	 */#ifdef CONFIG_INET#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \	 || defined(CONFIG_PPP) \    || (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))	slhc_install();#endif#endif#ifdef CONFIG_NET_PROFILE	net_profile_init();	NET_PROFILE_REGISTER(dev_queue_xmit);	NET_PROFILE_REGISTER(net_bh);#if 0	NET_PROFILE_REGISTER(net_bh_skb);#endif#endif	/*	 *	Add the devices.	 *	If the call to dev->init fails, the dev is removed	 *	from the chain disconnecting the device until the	 *	next reboot.	 */	dp = &dev_base;	while ((dev = *dp) != NULL)	{		dev->iflink = -1;		if (dev->init && dev->init(dev))		{			/*			 *	It failed to come up. Unhook it.			 */			*dp = dev->next;			synchronize_bh();		}		else		{			dp = &dev->next;			dev->ifindex = dev_new_index();			if (dev->iflink == -1)				dev->iflink = dev->ifindex;			dev_init_scheduler(dev);		}	}#ifdef CONFIG_PROC_FS	proc_net_register(&proc_net_dev);	{		struct proc_dir_entry *ent = create_proc_entry("net/dev_stat", 0, 0);		ent->read_proc = dev_proc_stats;	}#endif#ifdef CONFIG_NET_RADIO#ifdef CONFIG_PROC_FS	proc_net_register(&proc_net_wireless);#endif	/* CONFIG_PROC_FS */#endif	/* CONFIG_NET_RADIO */	init_bh(NET_BH, net_bh);	dev_boot_phase = 0;	dev_mcast_init();#ifdef CONFIG_BRIDGE	/*	 * Register any statically linked ethernet devices with the bridge	 */	br_spacedevice_register();#endif#ifdef CONFIG_IP_PNP	ip_auto_config();#endif	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -