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

📄 dn_dev.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (dn_db->parms.forwarding == 0)		dev_mc_add(dev, dn_rt_all_end_mcast, ETH_ALEN, 0);	else		dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0);	dev_mc_upload(dev);	dn_db->use_long = 1;	return 0;}static void dn_eth_down(struct net_device *dev){	struct dn_dev *dn_db = dev->dn_ptr;	if (dn_db->parms.forwarding == 0)		dev_mc_delete(dev, dn_rt_all_end_mcast, ETH_ALEN, 0);	else		dev_mc_delete(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0);}static void dn_dev_set_timer(struct net_device *dev);static void dn_dev_timer_func(unsigned long arg){	struct net_device *dev = (struct net_device *)arg;	struct dn_dev *dn_db = dev->dn_ptr;	struct dn_ifaddr *ifa;	if (dn_db->t3 <= dn_db->parms.t2) {		if (dn_db->parms.timer3) {			for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next) {				if (!(ifa->ifa_flags & IFA_F_SECONDARY))					dn_db->parms.timer3(dev, ifa);			}		}		dn_db->t3 = dn_db->parms.t3;	} else {		dn_db->t3 -= dn_db->parms.t2;	}	dn_dev_set_timer(dev);}static void dn_dev_set_timer(struct net_device *dev){	struct dn_dev *dn_db = dev->dn_ptr;	if (dn_db->parms.t2 > dn_db->parms.t3)		dn_db->parms.t2 = dn_db->parms.t3;	dn_db->timer.data = (unsigned long)dev;	dn_db->timer.function = dn_dev_timer_func;	dn_db->timer.expires = jiffies + (dn_db->parms.t2 * HZ);	add_timer(&dn_db->timer);}struct dn_dev *dn_dev_create(struct net_device *dev, int *err){	int i;	struct dn_dev_parms *p = dn_dev_list;	struct dn_dev *dn_db;	for(i = 0; i < DN_DEV_LIST_SIZE; i++, p++) {		if (p->type == dev->type)			break;	}	*err = -ENODEV;	if (i == DN_DEV_LIST_SIZE)		return NULL;	*err = -ENOBUFS;	if ((dn_db = kmalloc(sizeof(struct dn_dev), GFP_ATOMIC)) == NULL)		return NULL;	memset(dn_db, 0, sizeof(struct dn_dev));	memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));	smp_wmb();	dev->dn_ptr = dn_db;	dn_db->dev = dev;	init_timer(&dn_db->timer);	dn_db->uptime = jiffies;	if (dn_db->parms.up) {		if (dn_db->parms.up(dev) < 0) {			dev->dn_ptr = NULL;			kfree(dn_db);			return NULL;		}	}	dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);	dn_dev_sysctl_register(dev, &dn_db->parms);	dn_dev_set_timer(dev);	*err = 0;	return dn_db;}/* * This processes a device up event. We only start up * the loopback device & ethernet devices with correct * MAC addreses automatically. Others must be started * specifically. * * FIXME: How should we configure the loopback address ? If we could dispense * with using decnet_address here and for autobind, it will be one less thing * for users to worry about setting up. */void dn_dev_up(struct net_device *dev){	struct dn_ifaddr *ifa;	dn_address addr = decnet_address;	int maybe_default = 0;	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;	if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))		return;	/*	 * Need to ensure that loopback device has a dn_db attached to it	 * to allow creation of neighbours against it, even though it might	 * not have a local address of its own. Might as well do the same for	 * all autoconfigured interfaces.	 */	if (dn_db == NULL) {		int err;		dn_db = dn_dev_create(dev, &err);		if (dn_db == NULL)			return;	}	if (dev->type == ARPHRD_ETHER) {		if (memcmp(dev->dev_addr, dn_hiord, 4) != 0)			return;		addr = dn_htons(dn_eth2dn(dev->dev_addr));		maybe_default = 1;	}	if (addr == 0)		return;	if ((ifa = dn_dev_alloc_ifa()) == NULL)		return;	ifa->ifa_local = ifa->ifa_address = addr;	ifa->ifa_flags = 0;	ifa->ifa_scope = RT_SCOPE_UNIVERSE;	strcpy(ifa->ifa_label, dev->name);	dn_dev_set_ifa(dev, ifa);	/*	 * Automagically set the default device to the first automatically	 * configured ethernet card in the system.	 */	if (maybe_default) {		dev_hold(dev);		if (dn_dev_set_default(dev, 0))			dev_put(dev);	}}static void dn_dev_delete(struct net_device *dev){	struct dn_dev *dn_db = dev->dn_ptr;	if (dn_db == NULL)		return;	del_timer_sync(&dn_db->timer);	dn_dev_sysctl_unregister(&dn_db->parms);	dn_dev_check_default(dev);	neigh_ifdown(&dn_neigh_table, dev);	if (dn_db->parms.down)		dn_db->parms.down(dev);	dev->dn_ptr = NULL;	neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);	neigh_ifdown(&dn_neigh_table, dev);	if (dn_db->router)		neigh_release(dn_db->router);	if (dn_db->peer)		neigh_release(dn_db->peer);	kfree(dn_db);}void dn_dev_down(struct net_device *dev){	struct dn_dev *dn_db = dev->dn_ptr;	struct dn_ifaddr *ifa;	if (dn_db == NULL)		return;	while((ifa = dn_db->ifa_list) != NULL) {		dn_dev_del_ifa(dn_db, &dn_db->ifa_list, 0);		dn_dev_free_ifa(ifa);	}	dn_dev_delete(dev);}void dn_dev_init_pkt(struct sk_buff *skb){	return;}void dn_dev_veri_pkt(struct sk_buff *skb){	return;}void dn_dev_hello(struct sk_buff *skb){	return;}void dn_dev_devices_off(void){	struct net_device *dev;	rtnl_lock();	for(dev = dev_base; dev; dev = dev->next)		dn_dev_down(dev);	rtnl_unlock();}void dn_dev_devices_on(void){	struct net_device *dev;	rtnl_lock();	for(dev = dev_base; dev; dev = dev->next) {		if (dev->flags & IFF_UP)			dn_dev_up(dev);	}	rtnl_unlock();}int register_dnaddr_notifier(struct notifier_block *nb){	return notifier_chain_register(&dnaddr_chain, nb);}int unregister_dnaddr_notifier(struct notifier_block *nb){	return notifier_chain_unregister(&dnaddr_chain, nb);}#ifdef CONFIG_DECNET_SIOCGIFCONF/* * Now we support multiple addresses per interface. * Since we don't want to break existing code, you have to enable * it as a compile time option. Probably you should use the * rtnetlink interface instead. */int dnet_gifconf(struct net_device *dev, char __user *buf, int len){	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;	struct dn_ifaddr *ifa;	char buffer[DN_IFREQ_SIZE];	struct ifreq *ifr = (struct ifreq *)buffer;	struct sockaddr_dn *addr = (struct sockaddr_dn *)&ifr->ifr_addr;	int done = 0;	if ((dn_db == NULL) || ((ifa = dn_db->ifa_list) == NULL))		return 0;	for(; ifa; ifa = ifa->ifa_next) {		if (!buf) {			done += sizeof(DN_IFREQ_SIZE);			continue;		}		if (len < DN_IFREQ_SIZE)			return done;		memset(buffer, 0, DN_IFREQ_SIZE);		if (ifa->ifa_label)			strcpy(ifr->ifr_name, ifa->ifa_label);		else			strcpy(ifr->ifr_name, dev->name);		addr->sdn_family = AF_DECnet;		addr->sdn_add.a_len = 2;		memcpy(addr->sdn_add.a_addr, &ifa->ifa_local,			sizeof(dn_address));		if (copy_to_user(buf, buffer, DN_IFREQ_SIZE)) {			done = -EFAULT;			break;		}		buf  += DN_IFREQ_SIZE;		len  -= DN_IFREQ_SIZE;		done += DN_IFREQ_SIZE;	}	return done;}#endif /* CONFIG_DECNET_SIOCGIFCONF */#ifdef CONFIG_PROC_FSstatic inline struct net_device *dn_dev_get_next(struct seq_file *seq, struct net_device *dev){	do {		dev = dev->next;	} while(dev && !dev->dn_ptr);	return dev;}static struct net_device *dn_dev_get_idx(struct seq_file *seq, loff_t pos){	struct net_device *dev;	dev = dev_base;	if (dev && !dev->dn_ptr)		dev = dn_dev_get_next(seq, dev);	if (pos) {		while(dev && (dev = dn_dev_get_next(seq, dev)))			--pos;	}	return dev;}static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos){	if (*pos) {		struct net_device *dev;		read_lock(&dev_base_lock);		dev = dn_dev_get_idx(seq, *pos - 1);		if (dev == NULL)			read_unlock(&dev_base_lock);		return dev;	}	return SEQ_START_TOKEN;}static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct net_device *dev = v;	loff_t one = 1;	if (v == SEQ_START_TOKEN) {		dev = dn_dev_seq_start(seq, &one);	} else {		dev = dn_dev_get_next(seq, dev);		if (dev == NULL)			read_unlock(&dev_base_lock);	}	++*pos;	return dev;}static void dn_dev_seq_stop(struct seq_file *seq, void *v){	if (v && v != SEQ_START_TOKEN)		read_unlock(&dev_base_lock);}static char *dn_type2asc(char type){	switch(type) {		case DN_DEV_BCAST:			return "B";		case DN_DEV_UCAST:			return "U";		case DN_DEV_MPOINT:			return "M";	}	return "?";}static int dn_dev_seq_show(struct seq_file *seq, void *v){	if (v == SEQ_START_TOKEN)        	seq_puts(seq, "Name     Flags T1   Timer1 T3   Timer3 BlkSize Pri State DevType    Router Peer\n");	else {		struct net_device *dev = v;		char peer_buf[DN_ASCBUF_LEN];		char router_buf[DN_ASCBUF_LEN];		struct dn_dev *dn_db = dev->dn_ptr;                seq_printf(seq, "%-8s %1s     %04u %04u   %04lu %04lu"				"   %04hu    %03d %02x    %-10s %-7s %-7s\n",                             	dev->name ? dev->name : "???",                             	dn_type2asc(dn_db->parms.mode),                             	0, 0,				dn_db->t3, dn_db->parms.t3,				mtu2blksize(dev),				dn_db->parms.priority,				dn_db->parms.state, dn_db->parms.name,				dn_db->router ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->router->primary_key), router_buf) : "",				dn_db->peer ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->peer->primary_key), peer_buf) : "");	}	return 0;}static struct seq_operations dn_dev_seq_ops = {	.start	= dn_dev_seq_start,	.next	= dn_dev_seq_next,	.stop	= dn_dev_seq_stop,	.show	= dn_dev_seq_show,};static int dn_dev_seq_open(struct inode *inode, struct file *file){	return seq_open(file, &dn_dev_seq_ops);}static struct file_operations dn_dev_seq_fops = {	.owner	 = THIS_MODULE,	.open	 = dn_dev_seq_open,	.read	 = seq_read,	.llseek	 = seq_lseek,	.release = seq_release,};#endif /* CONFIG_PROC_FS */static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] = {	 [4] = { .doit   = dn_dev_rtm_newaddr,	},	 [5] = { .doit   = dn_dev_rtm_deladdr,	},	 [6] = { .dumpit = dn_dev_dump_ifaddr,	},#ifdef CONFIG_DECNET_ROUTER	 [8] = { .doit   = dn_fib_rtm_newroute,	},	 [9] = { .doit   = dn_fib_rtm_delroute,	},	[10] = { .doit   = dn_cache_getroute, .dumpit = dn_fib_dump, },	[16] = { .doit   = dn_fib_rtm_newrule, },	[17] = { .doit   = dn_fib_rtm_delrule, },	[18] = { .dumpit = dn_fib_dump_rules,  },#else	[10] = { .doit   = dn_cache_getroute, .dumpit = dn_cache_dump, },#endif};static int __initdata addr[2];static int __initdata num;module_param_array(addr, int, num, 0444);MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");void __init dn_dev_init(void){        if (addr[0] > 63 || addr[0] < 0) {                printk(KERN_ERR "DECnet: Area must be between 0 and 63");                return;        }        if (addr[1] > 1023 || addr[1] < 0) {                printk(KERN_ERR "DECnet: Node must be between 0 and 1023");                return;        }        decnet_address = dn_htons((addr[0] << 10) | addr[1]);	dn_dev_devices_on();#ifdef CONFIG_DECNET_SIOCGIFCONF	register_gifconf(PF_DECnet, dnet_gifconf);#endif /* CONFIG_DECNET_SIOCGIFCONF */	rtnetlink_links[PF_DECnet] = dnet_rtnetlink_table;	proc_net_fops_create("decnet_dev", S_IRUGO, &dn_dev_seq_fops);#ifdef CONFIG_SYSCTL	{		int i;		for(i = 0; i < DN_DEV_LIST_SIZE; i++)			dn_dev_sysctl_register(NULL, &dn_dev_list[i]);	}#endif /* CONFIG_SYSCTL */}void __exit dn_dev_cleanup(void){	rtnetlink_links[PF_DECnet] = NULL;#ifdef CONFIG_DECNET_SIOCGIFCONF	unregister_gifconf(PF_DECnet);#endif /* CONFIG_DECNET_SIOCGIFCONF */#ifdef CONFIG_SYSCTL	{		int i;		for(i = 0; i < DN_DEV_LIST_SIZE; i++)			dn_dev_sysctl_unregister(&dn_dev_list[i]);	}#endif /* CONFIG_SYSCTL */	proc_net_remove("decnet_dev");	dn_dev_devices_off();}

⌨️ 快捷键说明

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