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

📄 net_kern.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	if(*str != '='){		printk(KERN_ERR 		       "eth_setup: expected '=' after device number\n");		return(1);	}	str++;	if(find_device(n)){		printk(KERN_ERR "eth_setup: Device %d already configured\n",		       n);		return(1);	}	if(index_out) *index_out = n;	*str_out = str;	return(0);}struct eth_init {	struct list_head list;	char *init;	int index;};/* Filled in at boot time.  Will need locking if the transports become * modular. */struct list_head transports = LIST_HEAD_INIT(transports);/* Filled in during early boot */struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);static int check_transport(struct transport *transport, char *eth, int n,			   void **init_out, char **mac_out){	int len;	len = strlen(transport->name);	if(strncmp(eth, transport->name, len))		return(0);	eth += len;	if(*eth == ',')		eth++;	else if(*eth != '\0')		return(0);	*init_out = kmalloc(transport->setup_size, GFP_KERNEL);	if(*init_out == NULL)		return(1);	if(!transport->setup(eth, mac_out, *init_out)){		kfree(*init_out);		*init_out = NULL;	}	return(1);}void register_transport(struct transport *new){	struct list_head *ele, *next;	struct eth_init *eth;	void *init;	char *mac = NULL;	int match;	list_add(&new->list, &transports);	list_for_each_safe(ele, next, &eth_cmd_line){		eth = list_entry(ele, struct eth_init, list);		match = check_transport(new, eth->init, eth->index, &init,					&mac);		if(!match)			continue;		else if(init != NULL){			eth_configure(eth->index, init, mac, new);			kfree(init);		}		list_del(&eth->list);	}}static int eth_setup_common(char *str, int index){	struct list_head *ele;	struct transport *transport;	void *init;	char *mac = NULL;	list_for_each(ele, &transports){		transport = list_entry(ele, struct transport, list);	        if(!check_transport(transport, str, index, &init, &mac))			continue;		if(init != NULL){			eth_configure(index, init, mac, transport);			kfree(init);		}		return(1);	}	return(0);}static int eth_setup(char *str){	struct eth_init *new;	int n, err;	err = eth_parse(str, &n, &str);	if(err) return(1);	new = alloc_bootmem(sizeof(new));	if (new == NULL){		printk("eth_init : alloc_bootmem failed\n");		return(1);	}	INIT_LIST_HEAD(&new->list);	new->index = n;	new->init = str;	list_add_tail(&new->list, &eth_cmd_line);	return(1);}__setup("eth", eth_setup);__uml_help(eth_setup,"eth[0-9]+=<transport>,<options>\n""    Configure a network device.\n\n");#if 0static int eth_init(void){	struct list_head *ele, *next;	struct eth_init *eth;	list_for_each_safe(ele, next, &eth_cmd_line){		eth = list_entry(ele, struct eth_init, list);		if(eth_setup_common(eth->init, eth->index))			list_del(&eth->list);	}		return(1);}__initcall(eth_init);#endifstatic int net_config(char *str){	int n, err;	err = eth_parse(str, &n, &str);	if(err) return(err);	str = uml_strdup(str);	if(str == NULL){		printk(KERN_ERR "net_config failed to strdup string\n");		return(-1);	}	err = !eth_setup_common(str, n);	if(err) 		kfree(str);	return(err);}static int net_id(char **str, int *start_out, int *end_out){        char *end;        int n;	n = simple_strtoul(*str, &end, 0);	if((*end != '\0') || (end == *str))		return -1;        *start_out = n;        *end_out = n;        *str = end;        return n;}static int net_remove(int n){	struct uml_net *device;	struct net_device *dev;	struct uml_net_private *lp;	device = find_device(n);	if(device == NULL)		return -ENODEV;	dev = device->dev;	lp = dev->priv;	if(lp->fd > 0)                return -EBUSY;	if(lp->remove != NULL) (*lp->remove)(&lp->user);	unregister_netdev(dev);	platform_device_unregister(&device->pdev);	list_del(&device->list);	kfree(device);	free_netdev(dev);	return 0;}static struct mc_device net_mc = {	.name		= "eth",	.config		= net_config,	.get_config	= NULL,        .id		= net_id,	.remove		= net_remove,};static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,			      void *ptr){	struct in_ifaddr *ifa = ptr;	struct net_device *dev = ifa->ifa_dev->dev;	struct uml_net_private *lp;	void (*proc)(unsigned char *, unsigned char *, void *);	unsigned char addr_buf[4], netmask_buf[4];	if(dev->open != uml_net_open) return(NOTIFY_DONE);	lp = dev->priv;	proc = NULL;	switch (event){	case NETDEV_UP:		proc = lp->add_address;		break;	case NETDEV_DOWN:		proc = lp->delete_address;		break;	}	if(proc != NULL){		memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf));		memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf));		(*proc)(addr_buf, netmask_buf, &lp->user);	}	return(NOTIFY_DONE);}struct notifier_block uml_inetaddr_notifier = {	.notifier_call		= uml_inetaddr_event,};static int uml_net_init(void){	struct list_head *ele;	struct uml_net_private *lp;		struct in_device *ip;	struct in_ifaddr *in;	mconsole_register_dev(&net_mc);	register_inetaddr_notifier(&uml_inetaddr_notifier);	/* Devices may have been opened already, so the uml_inetaddr_notifier	 * didn't get a chance to run for them.  This fakes it so that	 * addresses which have already been set up get handled properly.	 */	list_for_each(ele, &opened){		lp = list_entry(ele, struct uml_net_private, list);		ip = lp->dev->ip_ptr;		if(ip == NULL) continue;		in = ip->ifa_list;		while(in != NULL){			uml_inetaddr_event(NULL, NETDEV_UP, in);			in = in->ifa_next;		}	}		return(0);}__initcall(uml_net_init);static void close_devices(void){	struct list_head *ele;	struct uml_net_private *lp;	list_for_each(ele, &opened){		lp = list_entry(ele, struct uml_net_private, list);		if((lp->close != NULL) && (lp->fd >= 0))			(*lp->close)(lp->fd, &lp->user);		if(lp->remove != NULL) (*lp->remove)(&lp->user);	}}__uml_exitcall(close_devices);int setup_etheraddr(char *str, unsigned char *addr){	char *end;	int i;	if(str == NULL)		return(0);	for(i=0;i<6;i++){		addr[i] = simple_strtoul(str, &end, 16);		if((end == str) ||		   ((*end != ':') && (*end != ',') && (*end != '\0'))){			printk(KERN_ERR 			       "setup_etheraddr: failed to parse '%s' "			       "as an ethernet address\n", str);			return(0);		}		str = end + 1;	}	if(addr[0] & 1){		printk(KERN_ERR 		       "Attempt to assign a broadcast ethernet address to a "		       "device disallowed\n");		return(0);	}	return(1);}void dev_ip_addr(void *d, unsigned char *bin_buf){	struct net_device *dev = d;	struct in_device *ip = dev->ip_ptr;	struct in_ifaddr *in;	if((ip == NULL) || ((in = ip->ifa_list) == NULL)){		printk(KERN_WARNING "dev_ip_addr - device not assigned an "		       "IP address\n");		return;	}	memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address));}void set_ether_mac(void *d, unsigned char *addr){	struct net_device *dev = d;	memcpy(dev->dev_addr, addr, ETH_ALEN);	}struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra){	if((skb != NULL) && (skb_tailroom(skb) < extra)){	  	struct sk_buff *skb2;		skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC);		dev_kfree_skb(skb);		skb = skb2;	}	if(skb != NULL) skb_put(skb, extra);	return(skb);}void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, 					void *), 		    void *arg){	struct net_device *dev = d;	struct in_device *ip = dev->ip_ptr;	struct in_ifaddr *in;	unsigned char address[4], netmask[4];	if(ip == NULL) return;	in = ip->ifa_list;	while(in != NULL){		memcpy(address, &in->ifa_address, sizeof(address));		memcpy(netmask, &in->ifa_mask, sizeof(netmask));		(*cb)(address, netmask, arg);		in = in->ifa_next;	}}int dev_netmask(void *d, void *m){	struct net_device *dev = d;	struct in_device *ip = dev->ip_ptr;	struct in_ifaddr *in;	__u32 *mask_out = m;	if(ip == NULL) 		return(1);	in = ip->ifa_list;	if(in == NULL) 		return(1);	*mask_out = in->ifa_mask;	return(0);}void *get_output_buffer(int *len_out){	void *ret;	ret = (void *) __get_free_pages(GFP_KERNEL, 0);	if(ret) *len_out = PAGE_SIZE;	else *len_out = 0;	return(ret);}void free_output_buffer(void *buffer){	free_pages((unsigned long) buffer, 0);}int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, 		     char **gate_addr){	char *remain;	remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL);	if(remain != NULL){		printk("tap_setup_common - Extra garbage on specification : "		       "'%s'\n", remain);		return(1);	}	return(0);}unsigned short eth_protocol(struct sk_buff *skb){	return(eth_type_trans(skb, skb->dev));}/* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only.  This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-file-style: "linux" * End: */

⌨️ 快捷键说明

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