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

📄 arp.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		goto out_of_mem;	memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));	return NF_HOOK(NF_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);freeskb:	kfree_skb(skb);out_of_mem:	return 0;}/* *	User level interface (ioctl) *//* *	Set (create) an ARP cache entry. */static int arp_req_set(struct arpreq *r, struct net_device * dev){	__be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;	struct neighbour *neigh;	int err;	if (r->arp_flags&ATF_PUBL) {		__be32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr;		if (mask && mask != htonl(0xFFFFFFFF))			return -EINVAL;		if (!dev && (r->arp_flags & ATF_COM)) {			dev = dev_getbyhwaddr(&init_net, r->arp_ha.sa_family, r->arp_ha.sa_data);			if (!dev)				return -ENODEV;		}		if (mask) {			if (pneigh_lookup(&arp_tbl, &ip, dev, 1) == NULL)				return -ENOBUFS;			return 0;		}		if (dev == NULL) {			IPV4_DEVCONF_ALL(PROXY_ARP) = 1;			return 0;		}		if (__in_dev_get_rtnl(dev)) {			IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, 1);			return 0;		}		return -ENXIO;	}	if (r->arp_flags & ATF_PERM)		r->arp_flags |= ATF_COM;	if (dev == NULL) {		struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,							 .tos = RTO_ONLINK } } };		struct rtable * rt;		if ((err = ip_route_output_key(&rt, &fl)) != 0)			return err;		dev = rt->u.dst.dev;		ip_rt_put(rt);		if (!dev)			return -EINVAL;	}	switch (dev->type) {#ifdef CONFIG_FDDI	case ARPHRD_FDDI:		/*		 * According to RFC 1390, FDDI devices should accept ARP		 * hardware types of 1 (Ethernet).  However, to be more		 * robust, we'll accept hardware types of either 1 (Ethernet)		 * or 6 (IEEE 802.2).		 */		if (r->arp_ha.sa_family != ARPHRD_FDDI &&		    r->arp_ha.sa_family != ARPHRD_ETHER &&		    r->arp_ha.sa_family != ARPHRD_IEEE802)			return -EINVAL;		break;#endif	default:		if (r->arp_ha.sa_family != dev->type)			return -EINVAL;		break;	}	neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev);	err = PTR_ERR(neigh);	if (!IS_ERR(neigh)) {		unsigned state = NUD_STALE;		if (r->arp_flags & ATF_PERM)			state = NUD_PERMANENT;		err = neigh_update(neigh, (r->arp_flags&ATF_COM) ?				   r->arp_ha.sa_data : NULL, state,				   NEIGH_UPDATE_F_OVERRIDE|				   NEIGH_UPDATE_F_ADMIN);		neigh_release(neigh);	}	return err;}static unsigned arp_state_to_flags(struct neighbour *neigh){	unsigned flags = 0;	if (neigh->nud_state&NUD_PERMANENT)		flags = ATF_PERM|ATF_COM;	else if (neigh->nud_state&NUD_VALID)		flags = ATF_COM;	return flags;}/* *	Get an ARP cache entry. */static int arp_req_get(struct arpreq *r, struct net_device *dev){	__be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;	struct neighbour *neigh;	int err = -ENXIO;	neigh = neigh_lookup(&arp_tbl, &ip, dev);	if (neigh) {		read_lock_bh(&neigh->lock);		memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);		r->arp_flags = arp_state_to_flags(neigh);		read_unlock_bh(&neigh->lock);		r->arp_ha.sa_family = dev->type;		strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev));		neigh_release(neigh);		err = 0;	}	return err;}static int arp_req_delete(struct arpreq *r, struct net_device * dev){	int err;	__be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;	struct neighbour *neigh;	if (r->arp_flags & ATF_PUBL) {		__be32 mask =		       ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;		if (mask == htonl(0xFFFFFFFF))			return pneigh_delete(&arp_tbl, &ip, dev);		if (mask == 0) {			if (dev == NULL) {				IPV4_DEVCONF_ALL(PROXY_ARP) = 0;				return 0;			}			if (__in_dev_get_rtnl(dev)) {				IN_DEV_CONF_SET(__in_dev_get_rtnl(dev),						PROXY_ARP, 0);				return 0;			}			return -ENXIO;		}		return -EINVAL;	}	if (dev == NULL) {		struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,							 .tos = RTO_ONLINK } } };		struct rtable * rt;		if ((err = ip_route_output_key(&rt, &fl)) != 0)			return err;		dev = rt->u.dst.dev;		ip_rt_put(rt);		if (!dev)			return -EINVAL;	}	err = -ENXIO;	neigh = neigh_lookup(&arp_tbl, &ip, dev);	if (neigh) {		if (neigh->nud_state&~NUD_NOARP)			err = neigh_update(neigh, NULL, NUD_FAILED,					   NEIGH_UPDATE_F_OVERRIDE|					   NEIGH_UPDATE_F_ADMIN);		neigh_release(neigh);	}	return err;}/* *	Handle an ARP layer I/O control request. */int arp_ioctl(unsigned int cmd, void __user *arg){	int err;	struct arpreq r;	struct net_device *dev = NULL;	switch (cmd) {		case SIOCDARP:		case SIOCSARP:			if (!capable(CAP_NET_ADMIN))				return -EPERM;		case SIOCGARP:			err = copy_from_user(&r, arg, sizeof(struct arpreq));			if (err)				return -EFAULT;			break;		default:			return -EINVAL;	}	if (r.arp_pa.sa_family != AF_INET)		return -EPFNOSUPPORT;	if (!(r.arp_flags & ATF_PUBL) &&	    (r.arp_flags & (ATF_NETMASK|ATF_DONTPUB)))		return -EINVAL;	if (!(r.arp_flags & ATF_NETMASK))		((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr =							   htonl(0xFFFFFFFFUL);	rtnl_lock();	if (r.arp_dev[0]) {		err = -ENODEV;		if ((dev = __dev_get_by_name(&init_net, r.arp_dev)) == NULL)			goto out;		/* Mmmm... It is wrong... ARPHRD_NETROM==0 */		if (!r.arp_ha.sa_family)			r.arp_ha.sa_family = dev->type;		err = -EINVAL;		if ((r.arp_flags & ATF_COM) && r.arp_ha.sa_family != dev->type)			goto out;	} else if (cmd == SIOCGARP) {		err = -ENODEV;		goto out;	}	switch (cmd) {	case SIOCDARP:		err = arp_req_delete(&r, dev);		break;	case SIOCSARP:		err = arp_req_set(&r, dev);		break;	case SIOCGARP:		err = arp_req_get(&r, dev);		if (!err && copy_to_user(arg, &r, sizeof(r)))			err = -EFAULT;		break;	}out:	rtnl_unlock();	return err;}static int arp_netdev_event(struct notifier_block *this, unsigned long event, void *ptr){	struct net_device *dev = ptr;	if (dev->nd_net != &init_net)		return NOTIFY_DONE;	switch (event) {	case NETDEV_CHANGEADDR:		neigh_changeaddr(&arp_tbl, dev);		rt_cache_flush(0);		break;	default:		break;	}	return NOTIFY_DONE;}static struct notifier_block arp_netdev_notifier = {	.notifier_call = arp_netdev_event,};/* Note, that it is not on notifier chain.   It is necessary, that this routine was called after route cache will be   flushed. */void arp_ifdown(struct net_device *dev){	neigh_ifdown(&arp_tbl, dev);}/* *	Called once on startup. */static struct packet_type arp_packet_type = {	.type =	__constant_htons(ETH_P_ARP),	.func =	arp_rcv,};static int arp_proc_init(void);void __init arp_init(void){	neigh_table_init(&arp_tbl);	dev_add_pack(&arp_packet_type);	arp_proc_init();#ifdef CONFIG_SYSCTL	neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,			      NET_IPV4_NEIGH, "ipv4", NULL, NULL);#endif	register_netdevice_notifier(&arp_netdev_notifier);}#ifdef CONFIG_PROC_FS#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)/* ------------------------------------------------------------------------ *//* *	ax25 -> ASCII conversion */static char *ax2asc2(ax25_address *a, char *buf){	char c, *s;	int n;	for (n = 0, s = buf; n < 6; n++) {		c = (a->ax25_call[n] >> 1) & 0x7F;		if (c != ' ') *s++ = c;	}	*s++ = '-';	if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {		*s++ = '1';		n -= 10;	}	*s++ = n + '0';	*s++ = '\0';	if (*buf == '\0' || *buf == '-')	   return "*";	return buf;}#endif /* CONFIG_AX25 */#define HBUFFERLEN 30static void arp_format_neigh_entry(struct seq_file *seq,				   struct neighbour *n){	char hbuffer[HBUFFERLEN];	const char hexbuf[] = "0123456789ABCDEF";	int k, j;	char tbuf[16];	struct net_device *dev = n->dev;	int hatype = dev->type;	read_lock(&n->lock);	/* Convert hardware address to XX:XX:XX:XX ... form. */#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)	if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)		ax2asc2((ax25_address *)n->ha, hbuffer);	else {#endif	for (k = 0, j = 0; k < HBUFFERLEN - 3 && j < dev->addr_len; j++) {		hbuffer[k++] = hexbuf[(n->ha[j] >> 4) & 15];		hbuffer[k++] = hexbuf[n->ha[j] & 15];		hbuffer[k++] = ':';	}	hbuffer[--k] = 0;#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)	}#endif	sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key));	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",		   tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);	read_unlock(&n->lock);}static void arp_format_pneigh_entry(struct seq_file *seq,				    struct pneigh_entry *n){	struct net_device *dev = n->dev;	int hatype = dev ? dev->type : 0;	char tbuf[16];	sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key));	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",		   tbuf, hatype, ATF_PUBL | ATF_PERM, "00:00:00:00:00:00",		   dev ? dev->name : "*");}static int arp_seq_show(struct seq_file *seq, void *v){	if (v == SEQ_START_TOKEN) {		seq_puts(seq, "IP address       HW type     Flags       "			      "HW address            Mask     Device\n");	} else {		struct neigh_seq_state *state = seq->private;		if (state->flags & NEIGH_SEQ_IS_PNEIGH)			arp_format_pneigh_entry(seq, v);		else			arp_format_neigh_entry(seq, v);	}	return 0;}static void *arp_seq_start(struct seq_file *seq, loff_t *pos){	/* Don't want to confuse "arp -a" w/ magic entries,	 * so we tell the generic iterator to skip NUD_NOARP.	 */	return neigh_seq_start(seq, pos, &arp_tbl, NEIGH_SEQ_SKIP_NOARP);}/* ------------------------------------------------------------------------ */static const struct seq_operations arp_seq_ops = {	.start  = arp_seq_start,	.next   = neigh_seq_next,	.stop   = neigh_seq_stop,	.show   = arp_seq_show,};static int arp_seq_open(struct inode *inode, struct file *file){	return seq_open_private(file, &arp_seq_ops,			sizeof(struct neigh_seq_state));}static const struct file_operations arp_seq_fops = {	.owner		= THIS_MODULE,	.open           = arp_seq_open,	.read           = seq_read,	.llseek         = seq_lseek,	.release	= seq_release_private,};static int __init arp_proc_init(void){	if (!proc_net_fops_create(&init_net, "arp", S_IRUGO, &arp_seq_fops))		return -ENOMEM;	return 0;}#else /* CONFIG_PROC_FS */static int __init arp_proc_init(void){	return 0;}#endif /* CONFIG_PROC_FS */EXPORT_SYMBOL(arp_broken_ops);EXPORT_SYMBOL(arp_find);EXPORT_SYMBOL(arp_create);EXPORT_SYMBOL(arp_xmit);EXPORT_SYMBOL(arp_send);EXPORT_SYMBOL(arp_tbl);#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)EXPORT_SYMBOL(clip_tbl_hook);#endif

⌨️ 快捷键说明

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