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

📄 my_route.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 3 页
字号:
#define MYIN_DEV_LOG_MARTIANS(in_dev)\	(myipv4_devconf.log_martians || (in_dev)->cnf.log_martians)#define RT_FL_TOS(oldflp) \		((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))#define MYIN_DEV_SHARED_MEDIA(in_dev)	\		(myipv4_devconf.shared_media || (in_dev)->cnf.shared_media)#define MYIN_DEV_MFORWARD(in_dev)	\		(myipv4_devconf.mc_forwarding && (in_dev)->cnf.mc_forwarding)#define IP_MAX_MTU	0xFFF0#define RT_GC_TIMEOUT (300*HZ)static int myip_rt_min_delay		= 2 * HZ;static int myip_rt_max_delay		= 10 * HZ;static int myip_rt_max_size;static int myip_rt_gc_timeout		= RT_GC_TIMEOUT;static int myip_rt_gc_interval		= 60 * HZ;static int myip_rt_gc_min_interval	= HZ / 2;static int myip_rt_redirect_number	= 9;static int myip_rt_redirect_load		= HZ / 50;static int myip_rt_redirect_silence	= ((HZ / 50) << (9 + 1));static int myip_rt_error_cost		= HZ;static int myip_rt_error_burst		= 5 * HZ;static int myip_rt_gc_elasticity		= 8;static int myip_rt_mtu_expires		= 10 * 60 * HZ;static int myip_rt_min_pmtu		= 512 + 20 + 20;static int myip_rt_min_advmss		= 256;static int myip_rt_secret_interval	= 10 * 60 * HZ;static unsigned long myrt_deadline;static struct timer_list myrt_flush_timer;static struct timer_list myrt_periodic_timer;static struct timer_list myrt_secret_timer;static int myip_rt_max_size;# define myrt_hash_lock_addr(slot) NULL# define myrt_hash_lock_init()struct myrt_hash_bucket{	struct rtable	*chain;};static __initdata unsigned long myrhash_entries;#ifdef CONFIG_NET_CLS_ROUTEstruct ip_rt_acct *myip_rt_acct;unsigned long myip_rt_acct_order;#endifstatic struct myrt_hash_bucket *myrt_hash_table;static unsigned long mytable_order;static unsigned		myrt_hash_mask;static int			myrt_hash_log;static unsigned int	myrt_hash_rnd;static DEFINE_PER_CPU(struct rt_cache_stat, myrt_cache_stat);#define MYRT_CACHE_STAT_INC(field) \	(per_cpu(myrt_cache_stat, raw_smp_processor_id()).field++)void myip_rt_get_source(u8 *addr, struct rtable *rt){	u32 src;	struct fib_result res;	if (rt->fl.iif == 0)		src = rt->rt_src;	else if(myfib_lookup(&rt->fl, &res) == 0) {		src = MYFIB_RES_PREFSRC(res);		fib_res_put(&res);	} else		src = myinet_select_addr(rt->u.dst.dev, rt->rt_gateway,					RT_SCOPE_UNIVERSE);	memcpy(addr, &src, 4);}static __inline__ void myrt_free(struct rtable *rt){	multipath_remove(rt);	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);}void myrt_bind_peer(struct rtable *rt, int create){	static DEFINE_SPINLOCK(rt_peer_lock);	struct inet_peer *peer;	peer = myinet_getpeer(rt->rt_dst, create);	spin_lock_bh(&rt_peer_lock);	if (rt->peer == NULL) {		rt->peer = peer;		peer = NULL;	}	spin_unlock_bh(&rt_peer_lock);	if (peer)		myinet_putpeer(peer);}static struct inet_peer *myrt_get_peer(struct rtable *rt){	if (rt->peer)		return rt->peer;	myrt_bind_peer(rt, 0);	return rt->peer;}void __myip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more){/*	struct rtable *rt = (struct rtable *) dst;	if (rt) {		if (rt->peer == NULL)			myrt_bind_peer(rt, 1);		if (rt->peer) {			iph->id = htons(inet_getid(rt->peer, more));			return;		}	} else		;	ip_select_fb_ident(iph);*/}static DEFINE_SPINLOCK( myrt_flush_lock );static void myrt_run_flush(unsigned long dummy);void myrt_cache_flush(int delay){	unsigned long now = jiffies;	int user_mode = !in_softirq();	if (delay < 0)		delay = myip_rt_min_delay;	multipath_flush();	spin_lock_bh( &myrt_flush_lock );	if( del_timer( &myrt_flush_timer ) && delay > 0 && myrt_deadline ){		long tmo = (long)( myrt_deadline - now );		if (user_mode && tmo < myip_rt_max_delay - myip_rt_min_delay )			tmo = 0;		if (delay > tmo)			delay = tmo;	}	if (delay <= 0) {		spin_unlock_bh( &myrt_flush_lock );		myrt_run_flush(0);		return;	}	if( myrt_deadline == 0 )		myrt_deadline = now + myip_rt_max_delay;		mod_timer(&myrt_flush_timer, now+delay);	spin_unlock_bh(&myrt_flush_lock);}static unsigned int myrt_hash_code(u32 daddr, u32 saddr, u8 tos){	return (jhash_3words(daddr, saddr, (u32) tos, myrt_hash_rnd) & myrt_hash_mask);}extern int myip_output(struct sk_buff *skb);extern int myip_mc_output(struct sk_buff *skb);extern int myip_mr_input(struct sk_buff *skb);extern int myip_local_deliver(struct sk_buff *skb);static struct dst_ops myipv4_dst_ops;static void myrt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag);int myip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto);static inline int __mymkroute_output(struct rtable **result, struct fib_result* res, 				const struct flowi *fl, const struct flowi *oldflp, 				struct net_device *dev_out, unsigned flags) {	struct rtable *rth;	struct in_device *in_dev;	u32 tos = RT_FL_TOS(oldflp);	int err = 0;	printk(KERN_INFO "old src: %u.%u.%u.%u, dst: %u.%u.%u.%u\n", NIPQUAD(oldflp->fl4_src),												NIPQUAD(oldflp->fl4_dst) );	printk(KERN_INFO "new src: %u.%u.%u.%u., dst: %u.%u.%u.%u\n", NIPQUAD(fl->fl4_src),												NIPQUAD(fl->fl4_dst) );	if( LOOPBACK(fl->fl4_src) && !( dev_out->flags & IFF_LOOPBACK ) )		return -EINVAL;	if( fl->fl4_dst == 0xFFFFFFFF )		res->type = RTN_BROADCAST;	else if( MULTICAST(fl->fl4_dst) )		res->type = RTN_MULTICAST;	else if( BADCLASS(fl->fl4_dst) || ZERONET(fl->fl4_dst) )		return -EINVAL;	if( dev_out->flags & IFF_LOOPBACK )		flags |= RTCF_LOCAL;	in_dev = in_dev_get(dev_out);	if( !in_dev )		return -EINVAL;	if( res->type == RTN_BROADCAST ){		flags |= RTCF_BROADCAST | RTCF_LOCAL;		if( res->fi ){			fib_info_put(res->fi);			res->fi = NULL;		}	}else if( res->type == RTN_MULTICAST ){		flags |= RTCF_MULTICAST | RTCF_LOCAL;		if( !myip_check_mc(in_dev, oldflp->fl4_dst, oldflp->fl4_src, oldflp->proto) )			flags &= ~RTCF_LOCAL;		if( res->fi && res->prefixlen < 4 ){			fib_info_put(res->fi);			res->fi = NULL;		}	}		rth = dst_alloc( &myipv4_dst_ops );	if (!rth) {		err = -ENOBUFS;		goto cleanup;	}			atomic_set(&rth->u.dst.__refcnt, 1);	rth->u.dst.flags= DST_HOST;#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED	if (res->fi) {		rth->rt_multipath_alg = res->fi->fib_mp_alg;		if (res->fi->fib_nhs > 1)			rth->u.dst.flags |= DST_BALANCED;	}#endif	if (in_dev->cnf.no_xfrm)		rth->u.dst.flags |= DST_NOXFRM;	if (in_dev->cnf.no_policy)		rth->u.dst.flags |= DST_NOPOLICY;	rth->fl.fl4_dst	= oldflp->fl4_dst;	rth->fl.fl4_tos	= tos;	rth->fl.fl4_src	= oldflp->fl4_src;	rth->fl.oif	= oldflp->oif;#ifdef CONFIG_IP_ROUTE_FWMARK	rth->fl.fl4_fwmark= oldflp->fl4_fwmark;#endif	rth->rt_dst	= fl->fl4_dst;	rth->rt_src	= fl->fl4_src;	rth->rt_iif	= oldflp->oif ? : dev_out->ifindex;	rth->u.dst.dev	= dev_out;	dev_hold(dev_out);	rth->idev = in_dev_get(dev_out);	rth->rt_gateway = fl->fl4_dst;	rth->rt_spec_dst= fl->fl4_src;	rth->u.dst.output=myip_output;	MYRT_CACHE_STAT_INC(out_slow_tot);	if (flags & RTCF_LOCAL) {		rth->u.dst.input = myip_local_deliver;		rth->rt_spec_dst = fl->fl4_dst;	}	if( flags & (RTCF_BROADCAST | RTCF_MULTICAST) ){		rth->rt_spec_dst = fl->fl4_src;		if(flags & RTCF_LOCAL && !(dev_out->flags & IFF_LOOPBACK) ){			rth->u.dst.output = myip_mc_output;			MYRT_CACHE_STAT_INC(out_slow_mc);		}#ifdef CONFIG_IP_MROUTE		if( res->type == RTN_MULTICAST ){			if( MYIN_DEV_MFORWARD(in_dev) && !LOCAL_MCAST(oldflp->fl4_dst) ){				rth->u.dst.input = myip_mr_input;				rth->u.dst.output = myip_mc_output;			}		}#endif	}	myrt_set_nexthop(rth, res, 0);	rth->rt_flags = flags;	*result = rth;cleanup:	/* release work reference to inet device */	in_dev_put(in_dev);	return err;}static int myrt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp);static inline int myip_mkroute_output_def(struct rtable **rp, struct fib_result* res,				const struct flowi *fl, const struct flowi *oldflp,				struct net_device *dev_out, unsigned flags){	struct rtable *rth = NULL;	int err = __mymkroute_output(&rth, res, fl, oldflp, dev_out, flags);	unsigned hash;	if (err == 0) {		u32 tos = RT_FL_TOS(oldflp);		hash = myrt_hash_code(oldflp->fl4_dst, 				    oldflp->fl4_src ^ (oldflp->oif << 5), tos);		err = myrt_intern_hash(hash, rth, rp);	}	return err;}static inline int myip_mkroute_output( struct rtable** rp, struct fib_result* res,				const struct flowi *fl, const struct flowi *oldflp,				struct net_device *dev_out, unsigned flags ){#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED	u32 tos = RT_FL_TOS(oldflp);	unsigned char hop;	unsigned hash;	int err = -EINVAL;	struct rtable *rth = NULL;	if( res->fi && res->fi->fib_nhs > 1 ){		unsigned char hopcount = res->fi->fib_nhs;		for( hop = 0; hop < hopcount; hop++ ){					}	}#else	return myip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags);#endif}static int myip_route_output_slow(struct rtable **rp, const struct flowi *oldflp){	u32 tos	= RT_FL_TOS(oldflp);	struct flowi fl = { .nl_u = { .ip4_u =			{ .daddr = oldflp->fl4_dst,					.saddr = oldflp->fl4_src,					.tos = tos & IPTOS_RT_MASK,					.scope = ((tos & RTO_ONLINK) ?									RT_SCOPE_LINK :									RT_SCOPE_UNIVERSE),#ifdef CONFIG_IP_ROUTE_FWMARK					.fwmark = oldflp->fl4_fwmark#endif			} },				 .iif = loopback_dev.ifindex,				 .oif = oldflp->oif };	struct fib_result res;	unsigned flags = 0;	struct net_device *dev_out = NULL;	int free_res = 0;	int err;	res.fi		= NULL;#ifdef CONFIG_IP_MULTIPLE_TABLES	res.r		= NULL;#endif	if( oldflp->fl4_src ){		err = -EINVAL;		if( MULTICAST(oldflp->fl4_src) || BADCLASS(oldflp->fl4_src) ||						ZERONET(oldflp->fl4_src) )			goto out;		dev_out = myip_dev_find(oldflp->fl4_src);		if (dev_out == NULL)			goto out;		if (oldflp->oif == 0						&& (MULTICAST(oldflp->fl4_dst) || oldflp->fl4_dst == 0xFFFFFFFF)) {			fl.oif = dev_out->ifindex;			goto make_route;		}		if( dev_out )			dev_put( dev_out );		dev_out = NULL;	}	if( oldflp->oif ){		dev_out = dev_get_by_index( oldflp->oif );		err = -ENODEV;		if (dev_out == NULL)			goto out;		if (__in_dev_get_rtnl(dev_out) == NULL) {			dev_put(dev_out);			goto out;		}		if( LOCAL_MCAST(oldflp->fl4_dst) || oldflp->fl4_dst == 0xFFFFFFFF ){			if (!fl.fl4_src)				fl.fl4_src = myinet_select_addr(dev_out, 0, RT_SCOPE_LINK);			goto make_route;		}		if( !fl.fl4_src ){			if( MULTICAST(oldflp->fl4_dst) )				fl.fl4_src = myinet_select_addr(dev_out, 0, fl.fl4_scope);			else if( !oldflp->fl4_dst )				fl.fl4_src = myinet_select_addr(dev_out, 0, RT_SCOPE_HOST);		}	}	if (!fl.fl4_dst){		fl.fl4_dst = fl.fl4_src;		if (!fl.fl4_dst)			fl.fl4_dst = fl.fl4_src = htonl(INADDR_LOOPBACK);		if (dev_out)			dev_put(dev_out);		dev_out = &loopback_dev;		dev_hold(dev_out);		fl.oif = loopback_dev.ifindex;		res.type = RTN_LOCAL;		flags |= RTCF_LOCAL;		goto make_route;	}		if( myfib_lookup(&fl, &res) ){		res.fi = NULL;		if (oldflp->oif) {			if (fl.fl4_src == 0)				fl.fl4_src = myinet_select_addr(dev_out, 0,								RT_SCOPE_LINK);			res.type = RTN_UNICAST;			goto make_route;		}		if (dev_out)			dev_put(dev_out);		err = -ENETUNREACH;		goto out;	}	free_res = 1;	if (res.type == RTN_LOCAL) {		if( !fl.fl4_src )			fl.fl4_src = fl.fl4_dst;		if( dev_out )			dev_put(dev_out);		dev_out = &loopback_dev;		dev_hold(dev_out);		fl.oif = dev_out->ifindex;		if( res.fi )			fib_info_put(res.fi);		res.fi = NULL;		flags |= RTCF_LOCAL;		goto make_route;	}#ifdef CONFIG_IP_ROUTE_MULTIPATH	if (res.fi->fib_nhs > 1 && fl.oif == 0)		myfib_select_multipath(&fl, &res);	else#endif	if (!res.prefixlen && res.type == RTN_UNICAST && !fl.oif)		myfib_select_default(&fl, &res);	if (!fl.fl4_src)		fl.fl4_src = MYFIB_RES_PREFSRC(res);	if( dev_out )		dev_put(dev_out);	dev_out = FIB_RES_DEV(res);	dev_hold(dev_out);	fl.oif = dev_out->ifindex;make_route:	err = myip_mkroute_output(rp, &res, &fl, oldflp, dev_out, flags);	if (free_res)		fib_res_put(&res);	if (dev_out)		dev_put(dev_out);out:	return err;}int __myip_route_output_key(struct rtable **rp, const struct flowi *flp){	unsigned hash;	struct rtable *rth;	hash = myrt_hash_code(flp->fl4_dst, flp->fl4_src ^ (flp->oif << 5), flp->fl4_tos);		rcu_read_lock_bh();	for (rth = rcu_dereference(myrt_hash_table[hash].chain); rth;					rth = rcu_dereference(rth->u.rt_next))	{			if (rth->fl.fl4_dst == flp->fl4_dst && rth->fl.fl4_src == flp->fl4_src &&							rth->fl.iif == 0 && rth->fl.oif == flp->oif &&#ifdef CONFIG_IP_ROUTE_FWMARK							rth->fl.fl4_fwmark == flp->fl4_fwmark &&#endif							!((rth->fl.fl4_tos ^ flp->fl4_tos) &									(IPTOS_RT_MASK | RTO_ONLINK))) 			{					if( multipath_select_route(flp, rth, rp) ){							dst_hold(&(*rp)->u.dst);							MYRT_CACHE_STAT_INC(out_hit);							rcu_read_unlock_bh();							return 0;					}					rth->u.dst.lastuse = jiffies;					dst_hold(&rth->u.dst);					rth->u.dst.__use++;					MYRT_CACHE_STAT_INC(out_hit);					rcu_read_unlock_bh();					*rp = rth;					return 0;			}			MYRT_CACHE_STAT_INC(out_hlist_search);	}	rcu_read_unlock_bh();	return myip_route_output_slow(rp, flp);}int myip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags){	int err;	if ((err = __myip_route_output_key(rp, flp)) != 0)		return err;	if (flp->proto) {		if (!flp->fl4_src)			flp->fl4_src = (*rp)->rt_src;		if (!flp->fl4_dst)			flp->fl4_dst = (*rp)->rt_dst;

⌨️ 快捷键说明

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