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

📄 my_route.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	return err;#else	return myip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);#endif}static int myip_error(struct sk_buff *skb){	struct rtable *rt = (struct rtable*)skb->dst;	unsigned long now;	int code;	switch (rt->u.dst.error) {		case EINVAL:		default:			goto out;		case EHOSTUNREACH:			code = ICMP_HOST_UNREACH;			break;		case ENETUNREACH:			code = ICMP_NET_UNREACH;			break;		case EACCES:			code = ICMP_PKT_FILTERED;			break;	}	now = jiffies;	rt->u.dst.rate_tokens += now - rt->u.dst.rate_last;	if (rt->u.dst.rate_tokens > myip_rt_error_burst)		rt->u.dst.rate_tokens = myip_rt_error_burst;	rt->u.dst.rate_last = now;	if (rt->u.dst.rate_tokens >= myip_rt_error_cost) {		rt->u.dst.rate_tokens -= myip_rt_error_cost;		;//icmp_send(skb, ICMP_DEST_UNREACH, code, 0);	}out:		kfree_skb(skb);	return 0;} int myip_mr_input(struct sk_buff *skb);static int myip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,				u8 tos, struct net_device *dev, int our){	unsigned hash;	struct rtable *rth;	u32 spec_dst;	struct in_device *in_dev = in_dev_get(dev);	u32 itag = 0;	if (in_dev == NULL)		return -EINVAL;	if (MULTICAST(saddr) || BADCLASS(saddr) || LOOPBACK(saddr) ||					skb->protocol != htons(ETH_P_IP))		goto e_inval;	if (ZERONET(saddr)) {		if (!LOCAL_MCAST(daddr))			goto e_inval;		spec_dst = myinet_select_addr(dev, 0, RT_SCOPE_LINK);	}else if( myfib_validate_source(saddr, 0, tos, 0,							dev, &spec_dst, &itag) < 0)		goto e_inval;	rth = dst_alloc(&myipv4_dst_ops);	if (!rth)		goto e_nobufs;	rth->u.dst.output= myip_rt_bug;	atomic_set(&rth->u.dst.__refcnt, 1);	rth->u.dst.flags= DST_HOST;	if (in_dev->cnf.no_policy)		rth->u.dst.flags |= DST_NOPOLICY;	rth->fl.fl4_dst	= daddr;	rth->rt_dst	= daddr;	rth->fl.fl4_tos	= tos;#ifdef CONFIG_IP_ROUTE_FWMARK	rth->fl.fl4_fwmark= skb->nfmark;#endif	rth->fl.fl4_src	= saddr;	rth->rt_src	= saddr;#ifdef CONFIG_NET_CLS_ROUTE	rth->u.dst.tclassid = itag;#endif	rth->rt_iif	=	rth->fl.iif	= dev->ifindex;	rth->u.dst.dev	= &loopback_dev;	dev_hold(rth->u.dst.dev);	rth->idev	= in_dev_get(rth->u.dst.dev);	rth->fl.oif	= 0;	rth->rt_gateway	= daddr;	rth->rt_spec_dst= spec_dst;	rth->rt_type	= RTN_MULTICAST;	rth->rt_flags	= RTCF_MULTICAST;	if (our) {		rth->u.dst.input= myip_local_deliver;		rth->rt_flags |= RTCF_LOCAL;	}#ifdef CONFIG_IP_MROUTE	if (!LOCAL_MCAST(daddr) && MYIN_DEV_MFORWARD(in_dev))		rth->u.dst.input = myip_mr_input;#endif	MYRT_CACHE_STAT_INC(in_slow_mc);	in_dev_put(in_dev);	hash = myrt_hash_code(daddr, saddr ^ (dev->ifindex << 5), tos);	return myrt_intern_hash(hash, rth, (struct rtable**) &skb->dst);e_nobufs:	in_dev_put(in_dev);	return -ENOBUFS;e_inval:	in_dev_put(in_dev);	return -EINVAL;}static int myip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,				u8 tos, struct net_device *dev){	struct fib_result res;	struct in_device *in_dev = in_dev_get(dev);	struct flowi fl = { .nl_u = { .ip4_u =			{ .daddr = daddr,					.saddr = saddr,					.tos = tos,					.scope = RT_SCOPE_UNIVERSE,#ifdef CONFIG_IP_ROUTE_FWMARK					.fwmark = skb->nfmark#endif			} },				 .iif = dev->ifindex };	unsigned		flags = 0;	u32				itag = 0;	struct rtable * rth;	unsigned		hash;	u32				spec_dst;	int				err = -EINVAL;	int				free_res = 0;	if (!in_dev)		goto out;	if (MULTICAST(saddr) || BADCLASS(saddr) || LOOPBACK(saddr))		goto martian_source;	if (daddr == 0xFFFFFFFF || (saddr == 0 && daddr == 0))		goto brd_input;	if (ZERONET(saddr))		goto martian_source;	if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr))		goto martian_destination;	if( (err = myfib_lookup(&fl, &res)) != 0 ){		if (!IN_DEV_FORWARD(in_dev))			goto e_hostunreach;		goto no_route;	}	free_res = 1;	MYRT_CACHE_STAT_INC(in_slow_tot);	printk(KERN_INFO "info: %u.%u.%u.%u\n", NIPQUAD((res.fi)->fib_prefsrc) );	printk(KERN_INFO "fa type: %d\n", res.type);	printk(KERN_INFO "fa scope: %d\n", res.scope);	if (res.type == RTN_BROADCAST)		goto brd_input;	if (res.type == RTN_LOCAL) {		int result;		result = myfib_validate_source(saddr, daddr, tos,						loopback_dev.ifindex, dev, &spec_dst, &itag);		printk(KERN_INFO "the res: %d\n", result );		printk(KERN_INFO "spec dst: %u.%u.%u.%u\n", NIPQUAD(spec_dst) );		if (result < 0)			goto martian_source;		if (result)			flags |= RTCF_DIRECTSRC;		spec_dst = daddr;		goto local_input;	}	if (!IN_DEV_FORWARD(in_dev))		goto e_hostunreach;	if (res.type != RTN_UNICAST)		goto martian_destination;	err = myip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);	if (err == -ENOBUFS)		goto e_nobufs;	if (err == -EINVAL)		goto e_inval;done:	in_dev_put(in_dev);	if (free_res)		fib_res_put(&res);out:	return err;brd_input:	if (skb->protocol != htons(ETH_P_IP))		goto e_inval;	if( ZERONET(saddr) )		spec_dst = myinet_select_addr(dev, 0, RT_SCOPE_LINK);	else{		err = myfib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag);		if( err < 0 )			goto martian_source;		if( err )			flags |= RTCF_DIRECTSRC;	}	flags |= RTCF_BROADCAST;	res.type = RTN_BROADCAST;	MYRT_CACHE_STAT_INC(in_brd);local_input:	rth = dst_alloc( &myipv4_dst_ops );	if (!rth)		goto e_nobufs;	rth->u.dst.output= myip_rt_bug;	atomic_set(&rth->u.dst.__refcnt, 1);	rth->u.dst.flags= DST_HOST;	if (in_dev->cnf.no_policy)		rth->u.dst.flags |= DST_NOPOLICY;	rth->fl.fl4_dst	= daddr;	rth->rt_dst	= daddr;	rth->fl.fl4_tos	= tos;#ifdef CONFIG_IP_ROUTE_FWMARK	rth->fl.fl4_fwmark= skb->nfmark;#endif	rth->fl.fl4_src	= saddr;	rth->rt_src	= saddr;#ifdef CONFIG_NET_CLS_ROUTE	rth->u.dst.tclassid = itag;#endif	rth->rt_iif	=	rth->fl.iif	= dev->ifindex;	rth->u.dst.dev	= &loopback_dev;	dev_hold(rth->u.dst.dev);	rth->idev	= in_dev_get(rth->u.dst.dev);	rth->rt_gateway	= daddr;	rth->rt_spec_dst= spec_dst;	rth->u.dst.input= myip_local_deliver;	rth->rt_flags 	= flags|RTCF_LOCAL;	if (res.type == RTN_UNREACHABLE) {		rth->u.dst.input= myip_error;		rth->u.dst.error= -err;		rth->rt_flags 	&= ~RTCF_LOCAL;	}	rth->rt_type	= res.type;	hash = myrt_hash_code(daddr, saddr ^ (fl.iif << 5), tos);	err = myrt_intern_hash(hash, rth, (struct rtable**)&skb->dst);	goto done;no_route:	MYRT_CACHE_STAT_INC(in_no_route);	spec_dst = myinet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);	res.type = RTN_UNREACHABLE;	goto local_input;martian_destination:	MYRT_CACHE_STAT_INC(in_martian_dst);#ifdef CONFIG_IP_ROUTE_VERBOSE	if (MYIN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())		printk(KERN_WARNING "martian destination %u.%u.%u.%u from "			"%u.%u.%u.%u, dev %s\n",			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);#endife_hostunreach:        err = -EHOSTUNREACH;        goto done;e_inval:	err = -EINVAL;	goto done;e_nobufs:	err = -ENOBUFS;	goto done;martian_source:	myip_handle_martian_source(dev, in_dev, skb, daddr, saddr);	goto e_inval;}extern int myip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto);int myip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,				u8 tos, struct net_device *dev){	struct rtable * rth;	unsigned	hash;	int iif = dev->ifindex;	tos &= IPTOS_RT_MASK;	hash = myrt_hash_code(daddr, saddr ^ (iif << 5), tos);		rcu_read_lock();	for (rth = rcu_dereference(myrt_hash_table[hash].chain); rth;					rth = rcu_dereference(rth->u.rt_next)) {		if (rth->fl.fl4_dst == daddr && rth->fl.fl4_src == saddr &&						rth->fl.iif == iif && rth->fl.oif == 0 &&#ifdef CONFIG_IP_ROUTE_FWMARK						rth->fl.fl4_fwmark == skb->nfmark &&#endif						rth->fl.fl4_tos == tos) {			rth->u.dst.lastuse = jiffies;			dst_hold(&rth->u.dst);			rth->u.dst.__use++;			MYRT_CACHE_STAT_INC(in_hit);			rcu_read_unlock();			skb->dst = (struct dst_entry*)rth;			return 0;		}		MYRT_CACHE_STAT_INC(in_hlist_search);	}	rcu_read_unlock();	if( MULTICAST(daddr) ){		struct in_device *in_dev;		rcu_read_lock();		if ((in_dev = __in_dev_get_rcu(dev)) != NULL) {			int our = myip_check_mc(in_dev, daddr, saddr, skb->nh.iph->protocol);			if (our#ifdef CONFIG_IP_MROUTE							|| (!LOCAL_MCAST(daddr) && MYIN_DEV_MFORWARD(in_dev))#endif			   ){				rcu_read_unlock();				return myip_route_input_mc(skb, daddr, saddr, tos, dev, our);			}		}		rcu_read_unlock();		return -EINVAL;	}	return myip_route_input_slow(skb, daddr, saddr, tos, dev);}static int myrt_cache_seq_open(struct inode *inode, struct file *file){	return 0;}ssize_t myseq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos){	return 0;}loff_t myseq_lseek(struct file *file, loff_t offset, int origin){	return 0;}int myseq_release_private(struct inode *inode, struct file *file){	return 0;}static int myip_rt_acct_read(char *buffer, char **start, off_t offset,			   int length, int *eof, void *data){	return 0;}static struct file_operations myrt_cache_seq_fops = {	.owner	 = THIS_MODULE,	.open	 = myrt_cache_seq_open,	.read	 = myseq_read,	.llseek	 = myseq_lseek,	.release = myseq_release_private,};static int myrt_cpu_seq_open(struct inode *inode, struct file *file){	return 0;}int myseq_release(struct inode *inode, struct file *file){	return 0;}static struct file_operations myrt_cpu_seq_fops = {	.owner	 = THIS_MODULE,	.open	 = myrt_cpu_seq_open,	.read	 = myseq_read,	.llseek	 = myseq_lseek,	.release = myseq_release,};void myip_rt_multicast_event(struct in_device *in_dev){	myrt_cache_flush(0);}int __init myip_rt_init(void){	myrt_hash_rnd = (int) ((num_physpages ^ (num_physpages>>8)) ^			     (jiffies ^ (jiffies >> 7)));#ifdef CONFIG_NET_CLS_ROUTE	{		int order;		for (order = 0;				(PAGE_SIZE << order) < 256 * sizeof(struct ip_rt_acct) * NR_CPUS; order++)				/* NOTHING */;		myip_rt_acct = (struct ip_rt_acct *)__get_free_pages(GFP_KERNEL, order);		if (!myip_rt_acct)			panic("IP: failed to allocate ip_rt_acct\n");		memset(myip_rt_acct, 0, PAGE_SIZE << order);		myip_rt_acct_order = order;	}#endif	myipv4_dst_ops.kmem_cachep = kmem_cache_create("myip_dst_cache",						     sizeof(struct rtable),						     0, SLAB_HWCACHE_ALIGN,						     NULL, NULL);	if (!myipv4_dst_ops.kmem_cachep)		panic("IP: failed to allocate myip_dst_cache\n");	myrt_hash_table = (struct myrt_hash_bucket *)					myalloc_large_system_hash("MYIP route cache", sizeof(struct myrt_hash_bucket),												myrhash_entries,(num_physpages >= 128 * 1024) ?												(27 - PAGE_SHIFT) : (29 - PAGE_SHIFT),												HASH_HIGHMEM, &myrt_hash_log, &myrt_hash_mask, 0,												&mytable_order );	memset(myrt_hash_table, 0, (myrt_hash_mask + 1) * sizeof(struct myrt_hash_bucket));	myrt_hash_lock_init();	myipv4_dst_ops.gc_thresh = (myrt_hash_mask + 1);	myip_rt_max_size = (myrt_hash_mask + 1) * 16;	init_timer( &myrt_flush_timer );	myrt_flush_timer.function = myrt_run_flush;	init_timer( &myrt_periodic_timer );	myrt_periodic_timer.function = myrt_check_expire;	init_timer( &myrt_secret_timer );	myrt_secret_timer.function = myrt_secret_rebuild;	myrt_periodic_timer.expires = jiffies + net_random() % myip_rt_gc_interval +									myip_rt_gc_interval;	add_timer(&myrt_periodic_timer);	myrt_secret_timer.expires = jiffies + net_random() % myip_rt_secret_interval +									myip_rt_secret_interval;	add_timer(&myrt_secret_timer);#ifdef CONFIG_PROC_FS	{		struct proc_dir_entry *myrtstat_pde = NULL; /* keep gcc happy */		if (!proc_net_fops_create("myrt_cache", S_IRUGO, &myrt_cache_seq_fops) ||							!(myrtstat_pde = create_proc_entry("myrt_cache", S_IRUGO, 											proc_net_stat))) {			return -ENOMEM;		}		myrtstat_pde->proc_fops = &myrt_cpu_seq_fops;	}#ifdef CONFIG_NET_CLS_ROUTE	create_proc_read_entry("myrt_acct", 0, proc_net, myip_rt_acct_read, NULL);#endif#endif	mydevinet_init();	myip_fib_init();#if 0			//left to future.#ifdef CONFIG_XFRM	xfrm_init();	xfrm4_init();#endif#endif	return 0;}void __exit myip_rt_exit(void){	int i;	remove_proc_entry("myrt_acct", proc_net);		remove_proc_entry( "myrt_cache", proc_net );	remove_proc_entry( "myrt_cache", proc_net_stat );	del_timer( &myrt_periodic_timer );    del_timer( &myrt_secret_timer );	mydevinet_exit();	myip_fib_exit();	for( i = 0; i < myrt_hash_mask + 1; i ++ ){		struct rtable *node_n = myrt_hash_table[i].chain;		struct rtable *node_p = node_n;		while( node_n != NULL ){			node_n = node_n->u.rt_next;			printk(KERN_INFO "ip: %u.%u.%u.%u\n", NIPQUAD(node_p->rt_dst) );			kmem_cache_free( myipv4_dst_ops.kmem_cachep, node_p );			node_p = node_n;		}	}	if( myrt_hash_table )        free_pages( (unsigned long)myrt_hash_table, mytable_order );	if( myipv4_dst_ops.kmem_cachep )			kmem_cache_destroy( myipv4_dst_ops.kmem_cachep );	if( myip_rt_acct )		free_pages( (unsigned long)myip_rt_acct, myip_rt_acct_order );}

⌨️ 快捷键说明

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