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

📄 arp.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct neighbour *n = dst->neighbour;	PR_DEBUG( "bind a neighbour to a dst on device: %s!\n", dev->name );	if( dev == NULL )		return -EINVAL;	if( n == NULL ){		u32 nexthop = ((struct rtable*)dst)->rt_gateway;		if( dev->flags & ( IFF_LOOPBACK | IFF_POINTOPOINT ) )			nexthop = 0;		n = __myneigh_lookup_errno( &myarp_tbl, &nexthop, dev );		if( IS_ERR(n) )			return PTR_ERR(n);		PR_DEEP_DEBUG( "bind a neighbour %p successed!\n", n );		dst->neighbour = n;	}	return 0;}static int myarp_req_delete(struct arpreq *r, struct net_device * dev){	int err;	u32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;	struct neighbour *neigh;	if( r->arp_flags & ATF_PUBL ){		u32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;		if( mask == 0xFFFFFFFF )			return mypneigh_delete( &myarp_tbl, &ip, dev );		if( mask == 0 ){			if( dev == NULL ){				//myipv4_devconf.proxy_arp = 0;				return 0;			}			if( __in_dev_get_rtnl(dev) ){				__in_dev_get_rtnl(dev)->cnf.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 = myneigh_lookup( &myarp_tbl, &ip, dev );	if( neigh ){		if( neigh->nud_state & ~NUD_NOARP )			err = myneigh_update( neigh, NULL, NUD_FAILED, 							NEIGH_UPDATE_F_OVERRIDE|NEIGH_UPDATE_F_ADMIN );		myneigh_release(neigh);	}	return err;}static int myarp_req_set(struct arpreq *r, struct net_device * dev){	u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;	struct neighbour *neigh;	int err;	if( r->arp_flags & ATF_PUBL ){		u32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr;		if( mask && mask != 0xFFFFFFFF )			return -EINVAL;		if( !dev && (r->arp_flags & ATF_COM) ){			dev = dev_getbyhwaddr( r->arp_ha.sa_family, r->arp_ha.sa_data );			if (!dev)				return -ENODEV;		}		if( mask ){			if( mypneigh_lookup(&myarp_tbl, &ip, dev, 1) == NULL )				return -ENOBUFS;			return 0;		}		if (dev == NULL) {			//ipv4_devconf.proxy_arp = 1;			return 0;		}		if (__in_dev_get_rtnl(dev)) {			__in_dev_get_rtnl(dev)->cnf.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 ){	default:		if( r->arp_ha.sa_family != dev->type )			return -EINVAL;		break;	}	neigh = __myneigh_lookup_errno( &myarp_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 = myneigh_update(neigh, (r->arp_flags & ATF_COM) ? r->arp_ha.sa_data : NULL, state, 				   NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN);		myneigh_release(neigh);	}	return err;}static unsigned myarp_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;}static int myarp_req_get(struct arpreq *r, struct net_device *dev){	u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;	struct neighbour *neigh;	int err = -ENXIO;	neigh = myneigh_lookup( &myarp_tbl, &ip, dev );	if( neigh ){		read_lock_bh( &neigh->lock );		memcpy( r->arp_ha.sa_data, neigh->ha, dev->addr_len );		r->arp_flags = myarp_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) );		myneigh_release(neigh);		err = 0;	}	return err;}int myarp_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 != MY_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(r.arp_dev)) == NULL )			goto out;		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;	}else{		err = -ENODEV;					//tmp code FIXME!!		goto out;	}	switch(cmd) {	case SIOCDARP:		err = myarp_req_delete( &r, dev );		break;	case SIOCSARP:		err = myarp_req_set( &r, dev );		break;	case SIOCGARP:		err = myarp_req_get( &r, dev );		if( !err && copy_to_user(arg, &r, sizeof(r)) )			err = -EFAULT;		break;	}out:	rtnl_unlock();	return err;}static int myarp_netdev_event(struct notifier_block *this, 				unsigned long event, void *ptr){	//struct net_device *dev = ptr;	switch( event ){/*	case NETDEV_CHANGEADDR:		neigh_changeaddr(&arp_tbl, dev);		rt_cache_flush(0);		break;*/	default:		break;	}	return NOTIFY_DONE;}static struct notifier_block myarp_netdev_notifier = {	.notifier_call = myarp_netdev_event,};int myarp_rcv(struct sk_buff *skb, struct net_device *dev, 				struct packet_type *pt, struct net_device *orig_dev){	struct arphdr *arp;	if( !pskb_may_pull(skb, (sizeof(struct arphdr) +				 (2 * dev->addr_len) + (2 * sizeof(u32)))) )		goto freeskb;	arp = skb->nh.arph;	if (arp->ar_hln != dev->addr_len || dev->flags & IFF_NOARP ||					skb->pkt_type == PACKET_OTHERHOST || skb->pkt_type == PACKET_LOOPBACK ||					arp->ar_pln != 4)		goto freeskb;	if( (skb = skb_share_check(skb, GFP_ATOMIC)) == NULL )		goto out_of_mem;	memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));	PR_DEBUG( "arp packet received!\n");	return NF_HOOK(NF_ARP, NF_ARP_IN, skb, dev, NULL, myarp_process);freeskb:	kfree_skb(skb);out_of_mem:	return 0;}#ifdef CONFIG_PROC_FS#define HBUFFERLEN 30static void myarp_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. */	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;	sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key));	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",		   tbuf, hatype, myarp_state_to_flags(n), hbuffer, dev->name);	read_unlock(&n->lock);}static void myarp_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 myarp_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)			myarp_format_pneigh_entry(seq, v);		else			myarp_format_neigh_entry(seq, v);	}	return 0;}static void *myarp_seq_start(struct seq_file *seq, loff_t *pos){	return myneigh_seq_start( seq, pos, &myarp_tbl, NEIGH_SEQ_SKIP_NOARP );}static struct seq_operations myarp_seq_ops = {	.start  = myarp_seq_start,	.next   = myneigh_seq_next,	.stop   = myneigh_seq_stop,	.show   = myarp_seq_show,};static int myarp_seq_open(struct inode *inode, struct file *file){	struct seq_file *seq;	int rc = -ENOMEM;	struct neigh_seq_state *s = kmalloc( sizeof(*s), GFP_KERNEL );	if( !s )		goto out;	memset(s, 0, sizeof(*s));	rc = seq_open(file, &myarp_seq_ops);	if (rc)		goto out_kfree;	seq	= file->private_data;	seq->private = s;out:	return rc;out_kfree:	kfree(s);	goto out;}static struct file_operations myarp_seq_fops = {	.owner		= THIS_MODULE,	.open		= myarp_seq_open,	.read		= seq_read,	.llseek		= seq_lseek,	.release	= seq_release_private,};static int __init myarp_proc_init(void){	if( !proc_net_fops_create("myarp", S_IRUGO, &myarp_seq_fops) )		return -ENOMEM;	return 0;}#else /* CONFIG_PROC_FS */static int __init myarp_proc_init(void){	return 0;}#endif /* CONFIG_PROC_FS */void myarp_ifdown(struct net_device *dev){	myneigh_ifdown( &myarp_tbl, dev );}static struct packet_type myarp_packet_type = {	.type =	__constant_htons(ETH_P_ARP),	.func =	myarp_rcv,};void __init myarp_init(void){	memcpy( &myarp_tbl, &tmp_tbl, sizeof(myarp_tbl) );	myneigh_table_init( &myarp_tbl );	mydev_add_pack( &myarp_packet_type );	myarp_proc_init();#ifdef CONFIG_SYSCTL	//neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,	//				NET_IPV4_NEIGH, "ipv4", NULL, NULL);#endif	register_netdevice_notifier( &myarp_netdev_notifier );}void __exit myarp_exit(void){	unregister_netdevice_notifier( &myarp_netdev_notifier );	mydev_remove_pack( &myarp_packet_type );	myneigh_table_destroy( &myarp_tbl );}EXPORT_SYMBOL_GPL( myarp_bind_neighbour );EXPORT_SYMBOL_GPL( myarp_ioctl );

⌨️ 快捷键说明

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