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

📄 aarp.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
		entry->expires_at = jiffies - 1;				/* return network full */		retval = -EADDRINUSE;	} else {		/* clear the probing flag */		entry->status &= ~ATIF_PROBE;	}	spin_unlock_bh(&aarp_lock);	return retval;}/* *	Send a DDP frame */int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa, void *hwaddr){	static char ddp_eth_multicast[ETH_ALEN] = { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };	int hash;	struct aarp_entry *a;		skb->nh.raw = skb->data;		/*	 *	Check for LocalTalk first	 */	 	 	if (dev->type == ARPHRD_LOCALTLK) {		struct at_addr *at = atalk_find_dev_addr(dev);		struct ddpehdr *ddp = (struct ddpehdr *)skb->data;		int ft = 2;				/*		 *	Compressible ?		 * 		 *	IFF: src_net==dest_net==device_net		 *	(zero matches anything)		 */		 		if( ( ddp->deh_snet==0 || at->s_net==ddp->deh_snet) &&		    ( ddp->deh_dnet==0 || at->s_net==ddp->deh_dnet) ) {			skb_pull(skb, sizeof(struct ddpehdr) - 4);			/*			 *	The upper two remaining bytes are the port 			 *	numbers	we just happen to need. Now put the 			 *	length in the lower two.			 */			*((__u16 *)skb->data) = htons(skb->len);			ft = 1;		}		/*		 *	Nice and easy. No AARP type protocols occur here		 *	so we can just shovel it out with a 3 byte LLAP header		 */		 		skb_push(skb, 3);		skb->data[0] = sa->s_node;		skb->data[1] = at->s_node;		skb->data[2] = ft;		 		if (skb->sk)			skb->priority = skb->sk->priority;		skb->dev = dev;		dev_queue_xmit(skb);		return 1;	}		/*	 *	On a PPP link we neither compress nor aarp.	 */	if (dev->type == ARPHRD_PPP) {		skb->protocol = htons(ETH_P_PPPTALK);		if (skb->sk)			skb->priority = skb->sk->priority;		skb->dev = dev;		dev_queue_xmit(skb);		return 1;	}	 	/*	 *	Non ELAP we cannot do.	 */	if (dev->type != ARPHRD_ETHER)		return -1;	skb->dev = dev;	skb->protocol = htons(ETH_P_ATALK);				hash = sa->s_node % (AARP_HASH_SIZE - 1);		/*	 *	Do we have a resolved entry ?	 */	 	if (sa->s_node == ATADDR_BCAST) {		ddp_dl->datalink_header(ddp_dl, skb, ddp_eth_multicast);		if (skb->sk)			skb->priority = skb->sk->priority;		dev_queue_xmit(skb);		return 1;	}	spin_lock_bh(&aarp_lock);	a = __aarp_find_entry(resolved[hash], dev, sa);	if (a != NULL) {		/*		 *	Return 1 and fill in the address		 */		a->expires_at = jiffies + (sysctl_aarp_expiry_time * 10);		ddp_dl->datalink_header(ddp_dl, skb, a->hwaddr);		if(skb->sk)			skb->priority = skb->sk->priority;		dev_queue_xmit(skb);		spin_unlock_bh(&aarp_lock);		return 1;	}	/*	 *	Do we have an unresolved entry: This is the less common path	 */	a = __aarp_find_entry(unresolved[hash], dev, sa);	if (a != NULL) {		/*		 *	Queue onto the unresolved queue		 */		skb_queue_tail(&a->packet_queue, skb);		spin_unlock_bh(&aarp_lock);		return 0;	}	/*	 *	Allocate a new entry	 */	a = aarp_alloc();	if (a == NULL) {		/*		 *	Whoops slipped... good job it's an unreliable 		 *	protocol 8)			 */		spin_unlock_bh(&aarp_lock);		return -1;	}	/*	 *	Set up the queue	 */	skb_queue_tail(&a->packet_queue, skb);	a->expires_at = jiffies + sysctl_aarp_resolve_time;	a->dev = dev;	a->next = unresolved[hash];	a->target_addr = *sa;	a->xmit_count = 0;	unresolved[hash] = a;	unresolved_count++;	/*	 *	Send an initial request for the address	 */	__aarp_send_query(a);	/*	 *	Switch to fast timer if needed (That is if this is the	 *	first unresolved entry to get added)	 */	if (unresolved_count == 1)		mod_timer(&aarp_timer, jiffies + sysctl_aarp_tick_time);	/*	 *	Now finally, it is safe to drop the lock.	 */	spin_unlock_bh(&aarp_lock);	/*	 *	Tell the ddp layer we have taken over for this frame.	 */	return 0;}/* *	An entry in the aarp unresolved queue has become resolved. Send *	all the frames queued under it. * *	Must run under aarp_lock. */static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a, int hash){	struct sk_buff *skb;	while (*list != NULL) {		if (*list == a) {			unresolved_count--;			*list = a->next;			/* 			 *	Move into the resolved list 			 */			a->next = resolved[hash];			resolved[hash] = a;			/*			 *	Kick frames off 			 */			while ((skb = skb_dequeue(&a->packet_queue)) != NULL) {				a->expires_at = jiffies + (sysctl_aarp_expiry_time*10);				ddp_dl->datalink_header(ddp_dl, skb, a->hwaddr);				if (skb->sk)					skb->priority = skb->sk->priority;				dev_queue_xmit(skb);			}		} else {			list = &((*list)->next);		}	}}/* *	This is called by the SNAP driver whenever we see an AARP SNAP *	frame. We currently only support Ethernet. */static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt){	struct elapaarp *ea=(struct elapaarp *)skb->h.raw;	struct aarp_entry *a;	struct at_addr sa, *ma, da;	int hash;	struct atalk_iface *ifa;	/*	 *	We only do Ethernet SNAP AARP.	 */	if (dev->type != ARPHRD_ETHER) {		kfree_skb(skb);		return 0;	}	/*	 *	Frame size ok ?	 */	if (!skb_pull(skb, sizeof(*ea))) {		kfree_skb(skb);		return 0;	}	ea->function = ntohs(ea->function);	/*	 *	Sanity check fields.	 */	if (ea->function < AARP_REQUEST ||	    ea->function > AARP_PROBE ||	    ea->hw_len != ETH_ALEN ||	    ea->pa_len != AARP_PA_ALEN ||	    ea->pa_src_zero != 0 ||	    ea->pa_dst_zero != 0) {		kfree_skb(skb);		return 0;	}	/*	 *	Looks good.	 */	hash = ea->pa_src_node % (AARP_HASH_SIZE - 1);	/*	 *	Build an address.	 */	sa.s_node = ea->pa_src_node;	sa.s_net = ea->pa_src_net;	/*	 *	Process the packet.	 *	Check for replies of me.	 */	ifa = atalk_find_dev(dev);	if (ifa == NULL) {		kfree_skb(skb);		return 1;	}	if (ifa->status & ATIF_PROBE) {		if (ifa->address.s_node == ea->pa_dst_node &&		    ifa->address.s_net == ea->pa_dst_net) {			/*			 *	Fail the probe (in use)			 */			ifa->status |= ATIF_PROBE_FAIL;			kfree_skb(skb);			return 1;		}	}	/*	 * Check for replies of proxy AARP entries	 */	da.s_node = ea->pa_dst_node;	da.s_net = ea->pa_dst_net;	spin_lock_bh(&aarp_lock);	a = __aarp_find_entry(proxies[hash], dev, &da);	if (a != NULL) {		if (a->status & ATIF_PROBE) {			a->status |= ATIF_PROBE_FAIL;			spin_unlock_bh(&aarp_lock);			/*			 * we do not respond to probe or request packets for			 * this address while we are probing this address			 */			kfree_skb(skb);			return 1;		}	}	switch (ea->function) {		case AARP_REPLY:				if (unresolved_count == 0)	/* Speed up */				break;			/*			 *	Find the entry.			 */			 			if ((a = __aarp_find_entry(unresolved[hash],dev,&sa)) == NULL ||			    (dev != a->dev))				break;			/*			 *	We can fill one in - this is good.			 */			 			memcpy(a->hwaddr,ea->hw_src,ETH_ALEN);			__aarp_resolved(&unresolved[hash],a,hash);			if (unresolved_count == 0)				mod_timer(&aarp_timer,					  jiffies + sysctl_aarp_expiry_time);			break;					case AARP_REQUEST:		case AARP_PROBE:			/*			 *	If it is my address set ma to my address and reply. We can treat probe and			 *	request the same. Probe simply means we shouldn't cache the querying host, 			 *	as in a probe they are proposing an address not using one.			 *				 *	Support for proxy-AARP added.  We check if the address is one			 *	of our proxies before we toss the packet out.			 */			 			sa.s_node = ea->pa_dst_node;			sa.s_net = ea->pa_dst_net;			/*			 * See if we have a matching proxy.			 */			ma = __aarp_proxy_find(dev, &sa);			if (!ma) {				ma = &ifa->address;			} else {				/*				 * We need to make a copy of the entry.				 */				da.s_node = sa.s_node;				da.s_net = da.s_net;				ma = &da;			}			if (ea->function == AARP_PROBE) {				/* A probe implies someone trying to get an				 * address. So as a precaution flush any				 * entries we have for this address.				 */				struct aarp_entry *a = __aarp_find_entry(						resolved[sa.s_node%(AARP_HASH_SIZE-1)],						skb->dev,						&sa);				/* Make it expire next tick - that avoids us				 * getting into a probe/flush/learn/probe/flush/learn				 * cycle during probing of a slow to respond host addr.				 */				if (a != NULL)				{					a->expires_at = jiffies - 1;					mod_timer(&aarp_timer, jiffies + sysctl_aarp_tick_time);				}			}			if (sa.s_node != ma->s_node)				break;			if (sa.s_net && ma->s_net && sa.s_net != ma->s_net)				break;			sa.s_node = ea->pa_src_node;			sa.s_net = ea->pa_src_net;						/*			 *	aarp_my_address has found the address to use for us.			 */			 			aarp_send_reply(dev, ma, &sa, ea->hw_src);			break;	};	spin_unlock_bh(&aarp_lock);	kfree_skb(skb);	return 1;}static struct notifier_block aarp_notifier = {	aarp_device_event,	NULL,	0};static char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 };void __init aarp_proto_init(void){	if ((aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv)) == NULL)		printk(KERN_CRIT "Unable to register AARP with SNAP.\n");	init_timer(&aarp_timer);	aarp_timer.function = aarp_expire_timeout;	aarp_timer.data = 0;	aarp_timer.expires = jiffies + sysctl_aarp_expiry_time;	add_timer(&aarp_timer);	register_netdevice_notifier(&aarp_notifier);}/* * Remove the AARP entries associated with a device. */void aarp_device_down(struct net_device *dev){	int ct;	spin_lock_bh(&aarp_lock);	for (ct = 0; ct < AARP_HASH_SIZE; ct++) {		__aarp_expire_device(&resolved[ct], dev);		__aarp_expire_device(&unresolved[ct], dev);		__aarp_expire_device(&proxies[ct], dev);	}	spin_unlock_bh(&aarp_lock);}/* * Called from proc fs */static int aarp_get_info(char *buffer, char **start, off_t offset, int length){	/* we should dump all our AARP entries */	struct aarp_entry	*entry;	int			len, ct;	len = sprintf(buffer,		"%-10.10s  ""%-10.10s""%-18.18s""%12.12s""%12.12s"" xmit_count  status\n",		"address","device","hw addr","last_sent", "expires");	spin_lock_bh(&aarp_lock);	for (ct = 0; ct < AARP_HASH_SIZE; ct++) {		for (entry = resolved[ct]; entry; entry = entry->next) {			len+= sprintf(buffer+len,"%6u:%-3u  ",				(unsigned int)ntohs(entry->target_addr.s_net),				(unsigned int)(entry->target_addr.s_node));			len+= sprintf(buffer+len,"%-10.10s",				entry->dev->name);			len+= sprintf(buffer+len,"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",				(int)(entry->hwaddr[0] & 0x000000FF),				(int)(entry->hwaddr[1] & 0x000000FF),				(int)(entry->hwaddr[2] & 0x000000FF),				(int)(entry->hwaddr[3] & 0x000000FF),				(int)(entry->hwaddr[4] & 0x000000FF),				(int)(entry->hwaddr[5] & 0x000000FF));			len+= sprintf(buffer+len,"%12lu ""%12lu ",				(unsigned long)entry->last_sent,				(unsigned long)entry->expires_at);			len+=sprintf(buffer+len,"%10u",				(unsigned int)entry->xmit_count);			len+=sprintf(buffer+len,"   resolved\n");		}	}	for (ct = 0; ct < AARP_HASH_SIZE; ct++) {		for (entry = unresolved[ct]; entry; entry = entry->next) {			len+= sprintf(buffer+len,"%6u:%-3u  ",				(unsigned int)ntohs(entry->target_addr.s_net),				(unsigned int)(entry->target_addr.s_node));			len+= sprintf(buffer+len,"%-10.10s",				entry->dev->name);			len+= sprintf(buffer+len,"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",				(int)(entry->hwaddr[0] & 0x000000FF),				(int)(entry->hwaddr[1] & 0x000000FF),				(int)(entry->hwaddr[2] & 0x000000FF),				(int)(entry->hwaddr[3] & 0x000000FF),				(int)(entry->hwaddr[4] & 0x000000FF),				(int)(entry->hwaddr[5] & 0x000000FF));			len+= sprintf(buffer+len,"%12lu ""%12lu ",				(unsigned long)entry->last_sent,				(unsigned long)entry->expires_at);			len+=sprintf(buffer+len,"%10u",				(unsigned int)entry->xmit_count);			len+=sprintf(buffer+len," unresolved\n");		}	}	for (ct = 0; ct < AARP_HASH_SIZE; ct++) {		for (entry = proxies[ct]; entry; entry = entry->next) {			len+= sprintf(buffer+len,"%6u:%-3u  ",				(unsigned int)ntohs(entry->target_addr.s_net),				(unsigned int)(entry->target_addr.s_node));			len+= sprintf(buffer+len,"%-10.10s",				entry->dev->name);			len+= sprintf(buffer+len,"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",				(int)(entry->hwaddr[0] & 0x000000FF),				(int)(entry->hwaddr[1] & 0x000000FF),				(int)(entry->hwaddr[2] & 0x000000FF),				(int)(entry->hwaddr[3] & 0x000000FF),				(int)(entry->hwaddr[4] & 0x000000FF),				(int)(entry->hwaddr[5] & 0x000000FF));			len+= sprintf(buffer+len,"%12lu ""%12lu ",				(unsigned long)entry->last_sent,				(unsigned long)entry->expires_at);			len+=sprintf(buffer+len,"%10u",				(unsigned int)entry->xmit_count);			len+=sprintf(buffer+len,"      proxy\n");		}	}	spin_unlock_bh(&aarp_lock);	return len;}#ifdef MODULE/* * General module cleanup. Called from cleanup_module() in ddp.c. */void aarp_cleanup_module(void){	del_timer(&aarp_timer);	unregister_netdevice_notifier(&aarp_notifier);	unregister_snap_client(aarp_snap_id);}#endif  /* MODULE */#ifdef CONFIG_PROC_FSvoid aarp_register_proc_fs(void){	proc_net_create("aarp", 0, aarp_get_info);}void aarp_unregister_proc_fs(void){	proc_net_remove("aarp");}#endif#endif  /* CONFIG_ATALK || CONFIG_ATALK_MODULE */

⌨️ 快捷键说明

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