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

📄 aarp.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	write_unlock_bh(&aarp_lock);out:	return retval;}/* Send a DDP frame */int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb,		  struct atalk_addr *sa, void *hwaddr){	static char ddp_eth_multicast[ETH_ALEN] =		{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };	int hash;	struct aarp_entry *a;	skb_reset_network_header(skb);	/* Check for LocalTalk first */	if (dev->type == ARPHRD_LOCALTLK) {		struct atalk_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(*ddp) - 4);			/*			 *	The upper two remaining bytes are the port			 *	numbers	we just happen to need. Now put the			 *	length in the lower two.			 */			*((__be16 *)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) {		/* Send it */		ddp_dl->request(ddp_dl, skb, ddp_eth_multicast);		goto sent;	}	write_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->request(ddp_dl, skb, a->hwaddr);		write_unlock_bh(&aarp_lock);		goto sent;	}	/* 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);		goto out_unlock;	}	/* Allocate a new entry */	a = aarp_alloc();	if (!a) {		/* Whoops slipped... good job it's an unreliable protocol 8) */		write_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. */out_unlock:	write_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->sk_priority;	dev_queue_xmit(skb);sent:	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->request(ddp_dl, skb, a->hwaddr);			}		} 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 net_device *orig_dev){	struct elapaarp *ea = aarp_hdr(skb);	int hash, ret = 0;	__u16 function;	struct aarp_entry *a;	struct atalk_addr sa, *ma, da;	struct atalk_iface *ifa;	if (dev->nd_net != &init_net)		goto out0;	/* 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;	write_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.				 */				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:	write_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 unsigned 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;	write_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);	}	write_unlock_bh(&aarp_lock);}#ifdef CONFIG_PROC_FSstruct aarp_iter_state {	int bucket;	struct aarp_entry **table;};/* * Get the aarp entry that is in the chain described * by the iterator. * If pos is set then skip till that index. * pos = 1 is the first entry */static struct aarp_entry *iter_next(struct aarp_iter_state *iter, loff_t *pos){	int ct = iter->bucket;	struct aarp_entry **table = iter->table;	loff_t off = 0;	struct aarp_entry *entry; rescan:	while(ct < AARP_HASH_SIZE) {		for (entry = table[ct]; entry; entry = entry->next) {			if (!pos || ++off == *pos) {				iter->table = table;				iter->bucket = ct;				return entry;			}		}		++ct;	}	if (table == resolved) {		ct = 0;		table = unresolved;		goto rescan;	}	if (table == unresolved) {		ct = 0;		table = proxies;		goto rescan;	}	return NULL;}static void *aarp_seq_start(struct seq_file *seq, loff_t *pos){	struct aarp_iter_state *iter = seq->private;	read_lock_bh(&aarp_lock);	iter->table     = resolved;	iter->bucket    = 0;	return *pos ? iter_next(iter, pos) : SEQ_START_TOKEN;}static void *aarp_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct aarp_entry *entry = v;	struct aarp_iter_state *iter = seq->private;	++*pos;	/* first line after header */	if (v == SEQ_START_TOKEN)		entry = iter_next(iter, NULL);	/* next entry in current bucket */	else if (entry->next)		entry = entry->next;	/* next bucket or table */	else {		++iter->bucket;		entry = iter_next(iter, NULL);	}	return entry;}static void aarp_seq_stop(struct seq_file *seq, void *v){	read_unlock_bh(&aarp_lock);}static const char *dt2str(unsigned long ticks){	static char buf[32];	sprintf(buf, "%ld.%02ld", ticks / HZ, ((ticks % HZ) * 100 ) / HZ);	return buf;}static int aarp_seq_show(struct seq_file *seq, void *v){	struct aarp_iter_state *iter = seq->private;	struct aarp_entry *entry = v;	unsigned long now = jiffies;	DECLARE_MAC_BUF(mac);	if (v == SEQ_START_TOKEN)		seq_puts(seq,			 "Address  Interface   Hardware Address"			 "   Expires LastSend  Retry Status\n");	else {		seq_printf(seq, "%04X:%02X  %-12s",			   ntohs(entry->target_addr.s_net),			   (unsigned int) entry->target_addr.s_node,			   entry->dev ? entry->dev->name : "????");		seq_printf(seq, "%s", print_mac(mac, entry->hwaddr));		seq_printf(seq, " %8s",			   dt2str((long)entry->expires_at - (long)now));		if (iter->table == unresolved)			seq_printf(seq, " %8s %6hu",				   dt2str(now - entry->last_sent),				   entry->xmit_count);		else			seq_puts(seq, "                ");		seq_printf(seq, " %s\n",			   (iter->table == resolved) ? "resolved"			   : (iter->table == unresolved) ? "unresolved"			   : (iter->table == proxies) ? "proxies"			   : "unknown");	}	return 0;}static const struct seq_operations aarp_seq_ops = {	.start  = aarp_seq_start,	.next   = aarp_seq_next,	.stop   = aarp_seq_stop,	.show   = aarp_seq_show,};static int aarp_seq_open(struct inode *inode, struct file *file){	struct seq_file *seq;	int rc = -ENOMEM;	struct aarp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);	if (!s)		goto out;	rc = seq_open(file, &aarp_seq_ops);	if (rc)		goto out_kfree;	seq	     = file->private_data;	seq->private = s;	memset(s, 0, sizeof(*s));out:	return rc;out_kfree:	kfree(s);	goto out;}const struct file_operations atalk_seq_arp_fops = {	.owner		= THIS_MODULE,	.open           = aarp_seq_open,	.read           = seq_read,	.llseek         = seq_lseek,	.release	= seq_release_private,};#endif/* General module cleanup. Called from cleanup_module() in ddp.c. */void aarp_cleanup_module(void){	del_timer_sync(&aarp_timer);	unregister_netdevice_notifier(&aarp_notifier);	unregister_snap_client(aarp_dl);	aarp_purge();}

⌨️ 快捷键说明

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