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

📄 aarp.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 2 页
字号:
		return -ENOMEM;		entry->expires_at = -1;	entry->status = ATIF_PROBE;	entry->target_addr.s_node = sa->s_node;	entry->target_addr.s_net = sa->s_net;	entry->dev = atif->dev;	spin_lock_bh(&aarp_lock);	hash = sa->s_node % (AARP_HASH_SIZE - 1);	entry->next = proxies[hash];	proxies[hash] = entry;		for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) {		aarp_send_probe(atif->dev, sa);		/* Defer 1/10th */		current->state = TASK_INTERRUPTIBLE;		spin_unlock_bh(&aarp_lock);		schedule_timeout(HZ/10);		spin_lock_bh(&aarp_lock);		if (entry->status & ATIF_PROBE_FAIL)			break;	}		if (entry->status & ATIF_PROBE_FAIL) {		entry->expires_at = jiffies - 1; /* free the entry */		retval = -EADDRINUSE; /* return network full */	} 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 || at->s_net == ddp->deh_snet) &&		    (!ddp->deh_dnet || 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;		skb->dev = dev;		goto sendit;	}		/* On a PPP link we neither compress nor aarp.  */	if (dev->type == ARPHRD_PPP) {		skb->protocol = htons(ETH_P_PPPTALK);		skb->dev = dev;		goto sendit;	}	 	/* 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);		goto sendit;	}	spin_lock_bh(&aarp_lock);	a = __aarp_find_entry(resolved[hash], dev, sa);	if (a) { /* 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);		spin_unlock_bh(&aarp_lock);		goto sendit;	}	/* Do we have an unresolved entry: This is the less common path */	a = __aarp_find_entry(unresolved[hash], dev, sa);	if (a) { /* 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) {		/* 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;sendit: if (skb->sk)		skb->priority = skb->sk->priority;	dev_queue_xmit(skb);	return 1;}/* *	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)		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;	int hash, ret = 0;	__u16 function;	struct aarp_entry *a;	struct at_addr sa, *ma, da;	struct atalk_iface *ifa;	/* We only do Ethernet SNAP AARP. */	if (dev->type != ARPHRD_ETHER)		goto out0;	/* Frame size ok? */	if (!skb_pull(skb, sizeof(*ea)))		goto out0;	function = ntohs(ea->function);	/* Sanity check fields. */	if (function < AARP_REQUEST || function > AARP_PROBE ||	    ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN ||	    ea->pa_src_zero || ea->pa_dst_zero)		goto out0;	/* 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)		goto out1;	if (ifa->status & ATIF_PROBE &&	    ifa->address.s_node == ea->pa_dst_node &&	    ifa->address.s_net == ea->pa_dst_net) {		ifa->status |= ATIF_PROBE_FAIL; /* Fail the probe (in use) */		goto out1;	}	/* 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 && a->status & ATIF_PROBE) {		a->status |= ATIF_PROBE_FAIL;		/*		 * we do not respond to probe or request packets for		 * this address while we are probing this address		 */		goto unlock;	}	switch (function) {		case AARP_REPLY:				if (!unresolved_count)	/* Speed up */				break;			/* Find the entry.  */			a = __aarp_find_entry(unresolved[hash],dev,&sa);			if (!a || 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)				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 (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) {					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;	}unlock:	spin_unlock_bh(&aarp_lock);out1:	ret = 1;out0:	kfree_skb(skb);	return ret;}static struct notifier_block aarp_notifier = {	notifier_call:	aarp_device_event,};static char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 };void __init aarp_proto_init(void){	aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv);	if (!aarp_dl)		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 */MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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