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

📄 dn_dev.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	ptr += 7;	i2 = ptr++;	n = dn_neigh_elist(dev, ptr, n);	*i2 = 7 * n;	*i1 = 8 + *i2;	skb_trim(skb, (27 + *i2));	pktlen = (__le16 *)skb_push(skb, 2);	*pktlen = dn_htons(skb->len - 2);	skb_reset_network_header(skb);	if (dn_am_i_a_router(dn, dn_db, ifa)) {		struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);		if (skb2) {			dn_rt_finish_output(skb2, dn_rt_all_end_mcast, src);		}	}	dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src);}static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa){	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;	if (dn_db->parms.forwarding == 0)		dn_send_endnode_hello(dev, ifa);	else		dn_send_router_hello(dev, ifa);}static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa){	int tdlen = 16;	int size = dev->hard_header_len + 2 + 4 + tdlen;	struct sk_buff *skb = dn_alloc_skb(NULL, size, GFP_ATOMIC);	int i;	unsigned char *ptr;	char src[ETH_ALEN];	if (skb == NULL)		return ;	skb->dev = dev;	skb_push(skb, dev->hard_header_len);	ptr = skb_put(skb, 2 + 4 + tdlen);	*ptr++ = DN_RT_PKT_HELO;	*((__le16 *)ptr) = ifa->ifa_local;	ptr += 2;	*ptr++ = tdlen;	for(i = 0; i < tdlen; i++)		*ptr++ = 0252;	dn_dn2eth(src, ifa->ifa_local);	dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src);}static int dn_eth_up(struct net_device *dev){	struct dn_dev *dn_db = dev->dn_ptr;	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);	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 = kzalloc(sizeof(struct dn_dev), GFP_ATOMIC)) == NULL)		return NULL;	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;	dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);	if (!dn_db->neigh_parms) {		dev->dn_ptr = NULL;		kfree(dn_db);		return NULL;	}	if (dn_db->parms.up) {		if (dn_db->parms.up(dev) < 0) {			neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);			dev->dn_ptr = NULL;			kfree(dn_db);			return NULL;		}	}	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;	__le16 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_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_each_netdev(&init_net, dev)		dn_dev_down(dev);	rtnl_unlock();}void dn_dev_devices_on(void){	struct net_device *dev;	rtnl_lock();	for_each_netdev(&init_net, dev) {		if (dev->flags & IFF_UP)			dn_dev_up(dev);	}	rtnl_unlock();}int register_dnaddr_notifier(struct notifier_block *nb){	return blocking_notifier_chain_register(&dnaddr_chain, nb);}int unregister_dnaddr_notifier(struct notifier_block *nb){	return blocking_notifier_chain_unregister(&dnaddr_chain, nb);}#ifdef CONFIG_PROC_FSstatic inline int is_dn_dev(struct net_device *dev){	return dev->dn_ptr != NULL;}static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos){	int i;	struct net_device *dev;	read_lock(&dev_base_lock);	if (*pos == 0)		return SEQ_START_TOKEN;	i = 1;	for_each_netdev(&init_net, dev) {		if (!is_dn_dev(dev))			continue;		if (i++ == *pos)			return dev;	}	return NULL;}static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct net_device *dev;	++*pos;	dev = (struct net_device *)v;	if (v == SEQ_START_TOKEN)		dev = net_device_entry(&init_net.dev_base_head);	for_each_netdev_continue(&init_net, dev) {		if (!is_dn_dev(dev))			continue;		return dev;	}	return NULL;}static void dn_dev_seq_stop(struct seq_file *seq, void *v){	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(*(__le16 *)dn_db->router->primary_key), router_buf) : "",				dn_db->peer ? dn_addr2asc(dn_ntohs(*(__le16 *)dn_db->peer->primary_key), peer_buf) : "");	}	return 0;}static const 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 const 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 int addr[2];module_param_array(addr, int, NULL, 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();	rtnl_register(PF_DECnet, RTM_NEWADDR, dn_nl_newaddr, NULL);	rtnl_register(PF_DECnet, RTM_DELADDR, dn_nl_deladdr, NULL);	rtnl_register(PF_DECnet, RTM_GETADDR, NULL, dn_nl_dump_ifaddr);	proc_net_fops_create(&init_net, "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){#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(&init_net, "decnet_dev");	dn_dev_devices_off();}

⌨️ 快捷键说明

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