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

📄 arp.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 "fib_frontend.h"#include "devinet.h"#include <linux/inetdevice.h>#include <linux/if_arp.h>#include <linux/rtnetlink.h>#include <linux/jhash.h>#include <linux/netfilter_arp.h>#include <linux/in.h>extern struct neigh_table myarp_tbl;struct sk_buff *myarp_create(int type, int ptype, u32 dest_ip, struct net_device *dev, u32 src_ip,			   unsigned char *dest_hw, unsigned char *src_hw, unsigned char *target_hw){	struct sk_buff *skb;	struct arphdr *arp;	unsigned char *arp_ptr;	skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)					+ LL_RESERVED_SPACE(dev), GFP_ATOMIC);	if( skb == NULL )		return NULL;	skb_reserve( skb, LL_RESERVED_SPACE(dev) );	skb->nh.raw = skb->data;	arp = (struct arphdr *) skb_put( skb,sizeof(struct arphdr) + 2*(dev->addr_len+4) );	skb->dev = dev;	skb->protocol = htons(ETH_P_ARP);	if( src_hw == NULL )		src_hw = dev->dev_addr;	if( dest_hw == NULL )		dest_hw = dev->broadcast;	if( dev->hard_header &&					dev->hard_header(skb,dev,ptype,dest_hw,src_hw,skb->len) < 0 )		goto out;	switch( dev->type ){		default:			arp->ar_hrd = htons(dev->type);			arp->ar_pro = htons(ETH_P_IP);			break;	}	arp->ar_hln = dev->addr_len;	arp->ar_pln = 4;	arp->ar_op = htons(type);	arp_ptr=(unsigned char *)(arp+1);	memcpy(arp_ptr, src_hw, dev->addr_len);	arp_ptr+=dev->addr_len;	memcpy(arp_ptr, &src_ip,4);	arp_ptr+=4;	if (target_hw != NULL)		memcpy(arp_ptr, target_hw, dev->addr_len);	else		memset(arp_ptr, 0, dev->addr_len);	arp_ptr += dev->addr_len;	memcpy(arp_ptr, &dest_ip, 4);	return skb;out:	kfree_skb(skb);	return NULL;}void myarp_xmit(struct sk_buff *skb){	NF_HOOK( NF_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit );}void myarp_send( int type, int ptype, u32 dest_ip, struct net_device *dev, u32 src_ip, 	      unsigned char *dest_hw, unsigned char *src_hw, unsigned char *target_hw ){	struct sk_buff *skb;		if( dev->flags & IFF_NOARP )		return;	skb = myarp_create(type, ptype, dest_ip, dev, src_ip, dest_hw, src_hw, target_hw);	if (skb == NULL)		return;	myarp_xmit(skb);}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);	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;	}*/	saddr = 0x023010AC;	if (in_dev)		in_dev_put(in_dev);	if( !saddr )		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);		if( (probes -= neigh->parms->ucast_probes) < 0 ){		if( !(neigh->nud_state & NUD_VALID) )			PR_DEBUG( "trying to ucast probe in NUD_INVALID\n" );		dst_ha = neigh->ha;		read_lock_bh(&neigh->lock);	} else if ((probes -= neigh->parms->app_probes) < 0) {		return;	}	myarp_send( ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, dst_ha, dev->dev_addr, NULL );	if( dst_ha )		read_unlock_bh(&neigh->lock);	dev_put(dev);}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 =	dev_queue_xmit_dummy,	.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 = myinet_addr_type(addr);	rcu_read_lock();	in_dev = __in_dev_get_rcu( dev );	if( in_dev == NULL ){		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);		}		PR_DEBUG( "the hh->hh_data's len: %d, %d\n", sizeof(neigh->hh->hh_data), LL_MAX_HEADER );		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;}static int myarp_process(struct sk_buff *skb){	struct net_device *dev = skb->dev;	struct in_device *in_dev = in_dev_get(dev);	struct arphdr *arp;	unsigned char *arp_ptr;	struct rtable *rt;	unsigned char *sha, *tha;	u32 sip, tip;	u16 dev_type = dev->type;	int addr_type;	struct neighbour *n;	if (in_dev == NULL)		goto out;	arp = skb->nh.arph;	switch( dev_type ){	default:			if( arp->ar_pro != htons(ETH_P_IP) || htons(dev_type) != arp->ar_hrd )			goto out;		break;	}	if( arp->ar_op != htons(ARPOP_REPLY) && arp->ar_op != htons(ARPOP_REQUEST) )		goto out;	arp_ptr= (unsigned char *)(arp+1);	sha	= arp_ptr;	arp_ptr += dev->addr_len;	memcpy(&sip, arp_ptr, 4);	arp_ptr += 4;	tha	= arp_ptr;	arp_ptr += dev->addr_len;	memcpy(&tip, arp_ptr, 4);	if( LOOPBACK(tip) || MULTICAST(tip) )		goto out;		if( sip == 0 ){		if( arp->ar_op == htons(ARPOP_REQUEST) &&						inet_addr_type(tip) == RTN_LOCAL						/* &&!arp_ignore(in_dev,dev,sip,tip)*/ )			myarp_send( ARPOP_REPLY, ETH_P_ARP, tip, dev, tip, sha, dev->dev_addr, dev->dev_addr);		goto out;	}	if( arp->ar_op == htons(ARPOP_REQUEST) /*&& ip_route_input(skb, tip, sip, 0, dev) == 0*/){		//rt = (struct rtable*)skb->dst;		//addr_type = rt->rt_type;		addr_type = RTN_LOCAL;		if( addr_type == RTN_LOCAL ){			n = myneigh_event_ns( &myarp_tbl, sha, &sip, dev );			if( n ){				int dont_send = 0;				//if( !dont_send )				//	dont_send |= arp_ignore( in_dev,dev,sip,tip );				//if( !dont_send && IN_DEV_ARPFILTER(in_dev) )				//	dont_send |= arp_filter( sip, tip, dev );				PR_DEBUG( "arp replay!!\n" ); 				if( !dont_send )					myarp_send( ARPOP_REPLY, ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha );				myneigh_release(n);			}			goto out;		}/*else if( IN_DEV_FORWARD(in_dev) ){			if( (rt->rt_flags & RTCF_DNAT) || 							(addr_type == RTN_UNICAST  && rt->u.dst.dev != dev &&							 (arp_fwd_proxy(in_dev, rt) 							  || pneigh_lookup(&myarp_tbl, &tip, dev, 0))) ){				n = neigh_event_ns( &myarp_tbl, sha, &sip, dev );				if( n )					neigh_release(n);				if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED || 								skb->pkt_type == PACKET_HOST ||								in_dev->arp_parms->proxy_delay == 0) {					myarp_send( ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha );				}else{					pneigh_enqueue( &myarp_tbl, in_dev->arp_parms, skb );					in_dev_put( in_dev );					return 0;				}				goto out;			}		}*/	}	PR_DEBUG( "do the __myneigh_lookup now!\n");	n = __myneigh_lookup( &myarp_tbl, &sip, dev, 0 );	if( n ){		int state = NUD_REACHABLE;		int override;		override = time_after(jiffies, n->updated + n->parms->locktime);		if( arp->ar_op != htons(ARPOP_REPLY) || skb->pkt_type != PACKET_HOST )			state = NUD_STALE;		PR_DEBUG( "neigh_update here!!!\n");		myneigh_update( n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0 );		myneigh_release(n);	}else		PR_DEBUG( "can't find the neighbour!\n");out:	if( in_dev )		in_dev_put(in_dev);	kfree_skb(skb);	return 0;}static void myparp_redo(struct sk_buff *skb){	myarp_process(skb);}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 =	myparp_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;

⌨️ 快捷键说明

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