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

📄 arp.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
字号:
/* arp.c * linqianghe@163.com * 2006-09-26 */#include "neighbour.h"#include "dev.h"#include "dev_dummy.h"#include "af_inet.h"#include "arp.h"#include "log.h"#include "route.h"#include <linux/inetdevice.h>#include <linux/if_arp.h>#include <linux/rtnetlink.h>#include <linux/jhash.h>extern struct neigh_table myarp_tbl;static void myarp_solicit(struct neighbour *neigh, struct sk_buff *skb){/*	u32 saddr = 0;	u8  *dst_ha = NULL;	struct net_device *dev = neigh->dev;	u32 target = *(u32*)neigh->primary_key;	int probes = atomic_read(&neigh->probes);	struct in_device *in_dev = in_dev_get(dev);	PR_DEBUG( "%s, %u.%u.%u.%u %d, %p\n", dev->name, NIPQUAD(target), probes, in_dev);	if (!in_dev)		return;	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {		default:		case 0:			if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)				saddr = skb->nh.iph->saddr;			break;		case 1:			if (!skb)				break;			saddr = skb->nh.iph->saddr;			if (inet_addr_type(saddr) == RTN_LOCAL) {				if (inet_addr_onlink(in_dev, target, saddr))					break;			}			saddr = 0;			break;		case 2:			break;	}*//*	if (in_dev)		in_dev_put(in_dev);	if( !saddr )		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);*/}static void myarp_error_report(struct neighbour *neigh, struct sk_buff *skb){	PR_DEBUG( "myarp_error_report!\n" );	dst_link_failure( skb );	kfree_skb(skb);}static struct neigh_ops myarp_dummy_ops = {	.family =			MY_AF_INET,	.solicit =			myarp_solicit,	.error_report =		myarp_error_report,	.output =			myneigh_resolve_output,	.connected_output =	myneigh_connected_output,	.hh_output =		dev_queue_xmit_dummy,	.queue_xmit =		dev_queue_xmit_dummy,};static struct neigh_ops myarp_generic_ops = {	.family =			MY_AF_INET,	.solicit =			myarp_solicit,	.error_report =		myarp_error_report,	.output =			myneigh_resolve_output,	.connected_output =	myneigh_connected_output,	.hh_output =		mydev_queue_xmit,	.queue_xmit =		mydev_queue_xmit,};static struct neigh_ops myarp_hh_ops = {	.family =			MY_AF_INET,	.solicit =			myarp_solicit,	.error_report =		myarp_error_report,	.output =			myneigh_resolve_output,	.connected_output =	myneigh_resolve_output,	.hh_output =		mydev_queue_xmit,	.queue_xmit =		mydev_queue_xmit,};static struct neigh_ops myarp_direct_ops = {	.family =			MY_AF_INET,	.output =			mydev_queue_xmit,	.connected_output =	mydev_queue_xmit,	.hh_output =		mydev_queue_xmit,	.queue_xmit =		mydev_queue_xmit,};struct neigh_ops myarp_broken_ops = {	.family =			MY_AF_INET,	.solicit =			myarp_solicit,	.error_report =		myarp_error_report,	.output =			myneigh_compat_output,	.connected_output =	myneigh_compat_output,	.hh_output =		mydev_queue_xmit,	.queue_xmit =		mydev_queue_xmit,};static u32 myarp_hash(const void *pkey, const struct net_device *dev){	return jhash_2words( *(u32 *)pkey, dev->ifindex, myarp_tbl.hash_rnd);}static int myarp_constructor( struct neighbour *neigh ){	u32 addr = *(u32*)neigh->primary_key;	struct net_device *dev = neigh->dev;	struct in_device *in_dev;	struct neigh_parms *parms;	//neigh->type = inet_addr_type(addr);	neigh->type = RTN_UNICAST;	neigh->ops = &myarp_dummy_ops;	neigh->output = neigh->ops->output;		return 0;					//temp code FIXME	rcu_read_lock();	in_dev = __in_dev_get_rcu( dev );	if( in_dev == NULL ){		PR_ERR( "the in_dev is NULL\n" );		rcu_read_unlock();		return -EINVAL;	}	parms = in_dev->arp_parms;	__neigh_parms_put( neigh->parms );	neigh->parms = neigh_parms_clone( parms );	rcu_read_unlock();	if (dev->hard_header == NULL) {		neigh->nud_state = NUD_NOARP;		neigh->ops = &myarp_direct_ops;		neigh->output = neigh->ops->queue_xmit;	}else{		switch( dev->type ){		default:			break;		case ARPHRD_ROSE:	#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)		case ARPHRD_AX25:#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)		case ARPHRD_NETROM:#endif			neigh->ops = &myarp_broken_ops;			neigh->output = neigh->ops->output;			return 0;#endif		;}		if( neigh->type == RTN_MULTICAST ){			neigh->nud_state = NUD_NOARP;			//arp_mc_map(addr, neigh->ha, dev, 1);		}else if( dev->flags & (IFF_NOARP|IFF_LOOPBACK) ){			neigh->nud_state = NUD_NOARP;			memcpy(neigh->ha, dev->dev_addr, dev->addr_len);		}else if( neigh->type == RTN_BROADCAST || dev->flags & IFF_POINTOPOINT ){			neigh->nud_state = NUD_NOARP;			memcpy(neigh->ha, dev->broadcast, dev->addr_len);		}		if( dev->hard_header_cache )			neigh->ops = &myarp_hh_ops;		else			neigh->ops = &myarp_generic_ops;		if( neigh->nud_state & NUD_VALID )			neigh->output = neigh->ops->connected_output;		else			neigh->output = neigh->ops->output;	}	return 0;}struct neigh_table tmp_tbl = {	.family =	MY_AF_INET,	.entry_size =	sizeof(struct neighbour) + 4,	.key_len =	4,	.hash =		myarp_hash,	.constructor =	myarp_constructor,	//.proxy_redo =	parp_redo,	.id =		"myarp_cache",	.parms = {		.tbl =			&myarp_tbl,		.base_reachable_time =	30 * HZ,		.retrans_time =	1 * HZ,		.gc_staletime =	60 * HZ,		.reachable_time =		30 * HZ,		.delay_probe_time =	5 * HZ,		.queue_len =		3,		.ucast_probes =	3,		.mcast_probes =	3,		.anycast_delay =	1 * HZ,		.proxy_delay =		(8 * HZ) / 10,		.proxy_qlen =		64,		.locktime =		1 * HZ,	},	.gc_interval =	30 * HZ,	.gc_thresh1 =	128,	.gc_thresh2 =	512,	.gc_thresh3 =	1024,};int myarp_bind_neighbour(struct dst_entry *dst){	struct net_device *dev = dst->dev;	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_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){	return 0;}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 );	//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( &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 );

⌨️ 快捷键说明

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