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

📄 myfib_frontend.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
字号:
#define MYFIB_RES_PREFSRC(res)	((res).fi->fib_prefsrc ? : __myfib_res_prefsrc(&res))#define MYIN_DEV_RPFILTER(in_dev)	(myipv4_devconf.rp_filter && (in_dev)->cnf.rp_filter)extern struct ipv4_devconf myipv4_devconf;#ifdef CONFIG_IP_MULTIPLE_TABLESstruct fib_table * myfib_hash_init(int id)#elsestruct fib_table * __init myfib_hash_init(int id)#endif{	struct fib_table *tb;	if ( myfn_hash_kmem == NULL)		myfn_hash_kmem = kmem_cache_create("myip_fib_hash",							sizeof(struct fib_node),							0, SLAB_HWCACHE_ALIGN,							NULL, NULL);	if ( myfn_alias_kmem == NULL )		myfn_alias_kmem = kmem_cache_create("myip_fib_alias",							sizeof(struct fib_alias),							0, SLAB_HWCACHE_ALIGN,							NULL, NULL);	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct fn_hash),					GFP_KERNEL);	if (tb == NULL)		return NULL;	tb->tb_id = id;	tb->tb_lookup = myfn_hash_lookup;	tb->tb_insert = myfn_hash_insert;	tb->tb_delete = myfn_hash_delete;	tb->tb_flush = myfn_hash_flush;	tb->tb_select_default = myfn_hash_select_default;	tb->tb_dump = myfn_hash_dump;	memset(tb->tb_data, 0, sizeof(struct fn_hash));	return tb;}#ifndef CONFIG_IP_MULTIPLE_TABLES#define RT_TABLE_MIN RT_TABLE_MAINstruct fib_table *myip_fib_local_table;struct fib_table *myip_fib_main_table;#else#define RT_TABLE_MIN 1struct fib_table *myfib_tables[RT_TABLE_MAX+1];struct fib_table *__myfib_new_table(int id){	struct fib_table *tb;	tb = myfib_hash_init(id);	if (!tb)		return NULL;	myfib_tables[id] = tb;	return tb;}#define myip_fib_local_table (myfib_tables[RT_TABLE_LOCAL])#define myip_fib_main_table (myfib_tables[RT_TABLE_MAIN])#endifstruct net_device * myip_dev_find(u32 addr){	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };	struct fib_result res;	struct net_device *dev = NULL;#ifdef CONFIG_IP_MULTIPLE_TABLES	res.r = NULL;#endif	if (!myip_fib_local_table ||					myip_fib_local_table->tb_lookup(myip_fib_local_table, &fl, &res))		return NULL;	if (res.type != RTN_LOCAL)		goto out;	dev = FIB_RES_DEV(res);	if (dev)		dev_hold(dev);out:	fib_res_put(&res);	return dev;}unsigned myinet_addr_type(u32 addr){	struct flowi		fl = { .nl_u = { .ip4_u = { .daddr = addr } } };	struct fib_result	res;	unsigned ret = RTN_BROADCAST;	if (ZERONET(addr) || BADCLASS(addr))		return RTN_BROADCAST;	if (MULTICAST(addr))		return RTN_MULTICAST;#ifdef CONFIG_IP_MULTIPLE_TABLES	res.r = NULL;#endif	if(myip_fib_local_table) {		ret = RTN_UNICAST;		if (!myip_fib_local_table->tb_lookup( myip_fib_local_table, &fl, &res)) {				ret = res.type;				fib_res_put(&res);		}	}	return ret;}struct in_ifaddr *myinet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask){	ASSERT_RTNL();	for_primary_ifa(in_dev) {		if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa))			return ifa;	} endfor_ifa(in_dev);	return NULL;}#ifndef CONFIG_IP_MULTIPLE_TABLESstatic inline struct fib_table *myfib_get_table(int id){	if (id != RT_TABLE_LOCAL)		return myip_fib_main_table;	return myip_fib_local_table;}static inline struct fib_table *myfib_new_table(int id){	return myfib_get_table(id);}#elsestatic inline struct fib_table *myfib_get_table(int id){	if (id == 0)		id = RT_TABLE_MAIN;	return myfib_tables[id];}struct fib_table *__myfib_new_table(int id);static inline struct fib_table *myfib_new_table(int id){	if (id == 0)		id = RT_TABLE_MAIN;	return myfib_tables[id] ? : __myfib_new_table(id);}#endifu32 myinet_select_addr(const struct net_device *dev, u32 dst, int scope);int myfib_validate_source(u32 src, u32 dst, u8 tos, int oif,				struct net_device *dev, u32 *spec_dst, u32 *itag){	struct in_device *in_dev;	struct flowi fl = { .nl_u = { .ip4_u =			{ .daddr = src,					.saddr = dst,					.tos = tos } },				 .iif = oif };	struct fib_result res;	int no_addr, rpf;	int ret;	no_addr = rpf = 0;	rcu_read_lock();	in_dev = __in_dev_get_rcu(dev);	if (in_dev) {		no_addr = in_dev->ifa_list == NULL;		rpf = MYIN_DEV_RPFILTER(in_dev);	}	rcu_read_unlock();	if (in_dev == NULL)		goto e_inval;	if( myfib_lookup(&fl, &res) )		goto last_resort;	if( res.type != RTN_UNICAST )		goto e_inval_res;	*spec_dst = MYFIB_RES_PREFSRC(res);	myfib_combine_itag(itag, &res);#ifdef CONFIG_IP_ROUTE_MULTIPATH	if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)#else	if (FIB_RES_DEV(res) == dev)#endif	{		ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;		fib_res_put(&res);		return ret;	}	fib_res_put(&res);	if (no_addr)		goto last_resort;	if (rpf)		goto e_inval;	fl.oif = dev->ifindex;	ret = 0;	if( myfib_lookup(&fl, &res) == 0 ){		if( res.type == RTN_UNICAST ){			*spec_dst = MYFIB_RES_PREFSRC(res);			ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;		}		fib_res_put(&res);	}	return ret;last_resort:	if (rpf)		goto e_inval;	*spec_dst = myinet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);	*itag = 0;	return 0;e_inval_res:	fib_res_put(&res);e_inval:	return -EINVAL;}static void myfib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr *ifa){	struct fib_table * tb;	struct {		struct nlmsghdr	nlh;		struct rtmsg	rtm;	} req;	struct kern_rta rta;	memset(&req.rtm, 0, sizeof(req.rtm));	memset(&rta, 0, sizeof(rta));	if (type == RTN_UNICAST)		tb = myfib_new_table(RT_TABLE_MAIN);	else		tb = myfib_new_table(RT_TABLE_LOCAL);	if (tb == NULL)		return;	req.nlh.nlmsg_len = sizeof(req);	req.nlh.nlmsg_type = cmd;	req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;	req.nlh.nlmsg_pid = 0;	req.nlh.nlmsg_seq = 0;	req.rtm.rtm_dst_len = dst_len;	req.rtm.rtm_table = tb->tb_id;	req.rtm.rtm_protocol = RTPROT_KERNEL;	req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);	req.rtm.rtm_type = type;	rta.rta_dst = &dst;	rta.rta_prefsrc = &ifa->ifa_local;	rta.rta_oif = &ifa->ifa_dev->dev->ifindex;	if (cmd == RTM_NEWROUTE)		tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);	else		tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);}void myfib_add_ifaddr(struct in_ifaddr *ifa){	struct in_device *in_dev = ifa->ifa_dev;	struct net_device *dev = in_dev->dev;	struct in_ifaddr *prim = ifa;	u32 mask = ifa->ifa_mask;	u32 addr = ifa->ifa_local;	u32 prefix = ifa->ifa_address & mask;	if( ifa->ifa_flags & IFA_F_SECONDARY ){		prim = myinet_ifa_byprefix(in_dev, prefix, mask);		if (prim == NULL) {			printk(KERN_DEBUG "fib_add_ifaddr: bug: prim == NULL\n");			return;		}	}	myfib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);	if( !( dev->flags & IFF_UP ) )		return;	if (ifa->ifa_broadcast && ifa->ifa_broadcast != 0xFFFFFFFF)		myfib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);		if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&					(prefix != addr || ifa->ifa_prefixlen < 32)) {		myfib_magic(RTM_NEWROUTE, dev->flags & IFF_LOOPBACK ? RTN_LOCAL :							RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim);		if (ifa->ifa_prefixlen < 31) {			myfib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);			myfib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix|~mask, 32, prim);		}	}#if 0	{		struct fib_table *tb = myfib_new_table(RT_TABLE_LOCAL);		struct fn_hash *table = (struct fn_hash *)tb->tb_data;		int i;		struct fn_zone *zone;		printk(KERN_INFO "the fib table id: %d, stamp: %u\n", tb->tb_id, tb->tb_stamp );		printk(KERN_INFO "\tthe array of zone in hash table:\n");		for( i = 0; i < 33; i ++ ){			if( table->fn_zones[i] == NULL ){				printk(KERN_INFO "\t%d: have no object!\n", i);			}else{				zone =  table->fn_zones[i];				printk(KERN_INFO "\t%d: have an object!\n", i);				printk(KERN_INFO "\t\tentries: %d\n", zone->fz_nent);				printk(KERN_INFO "\t\thash divisor: %d\n", zone->fz_divisor );				printk(KERN_INFO "\t\thash mask: %x\n", zone->fz_hashmask );				printk(KERN_INFO "\t\tzone order: %d\n", zone->fz_order );				printk(KERN_INFO "\t\tzone mask: %x\n", zone->fz_mask );			}		}		printk(KERN_INFO "\tthe zone list:\n");		zone = table->fn_zone_list;		i = 0;		while( zone != NULL ){			printk(KERN_INFO "\t\tzone: %d\n", i);			struct hlist_head *head;			struct hlist_node *node;			struct fib_node *f;			int j;			for( j = 0; j < zone->fz_divisor; j ++ ){				head = &zone->fz_hash[j];				hlist_for_each_entry( f, node, head, fn_hash ){					printk(KERN_INFO "\t\t\tthe key ip: %u.%u.%u.%u\n", NIPQUAD(f->fn_key));					printk(KERN_INFO "\t\t\tthe alias:\n");					struct fib_alias* alias;					list_for_each_entry( alias, &(f->fn_alias), fa_list ){						printk(KERN_INFO "\t\t\t\tfa tos: %d\n", alias->fa_tos);						printk(KERN_INFO "\t\t\t\tfa type: %d\n", alias->fa_type);						printk(KERN_INFO "\t\t\t\tfa scope: %d\n", alias->fa_scope);						printk(KERN_INFO "\t\t\t\tfa state: %d\n", alias->fa_state); 						printk(KERN_INFO "\t\t\t\tthe fa info:\n");						if( alias->fa_info != NULL ){							int k;							struct fib_info *info = alias->fa_info;							printk(KERN_INFO "\t\t\t\t\ttree ref: %d\n", info->fib_treeref );							printk(KERN_INFO "\t\t\t\t\tclnt ref: %d\n", info->fib_clntref );							printk(KERN_INFO "\t\t\t\t\tfib_dead: %d\n", info->fib_dead );							printk(KERN_INFO "\t\t\t\t\tfib flags: %u\n", info->fib_flags );							printk(KERN_INFO "\t\t\t\t\tprotocol: %d\n", info->fib_protocol );							printk(KERN_INFO "\t\t\t\t\tpref src: %u.%u.%u.%u.\n",												NIPQUAD(info->fib_prefsrc) );							printk(KERN_INFO "\t\t\t\t\tpriority: %u\n", info->fib_priority);							printk(KERN_INFO "\t\t\t\t\tfib_mtu: %u\n", info->fib_mtu );							printk(KERN_INFO "\t\t\t\t\tfib_window: %u\n", info->fib_window);							printk(KERN_INFO "\t\t\t\t\tfib_power: %d\n", info->fib_power);							printk(KERN_INFO "\t\t\t\t\tfib_nhs: %d\n", info->fib_nhs);							printk(KERN_INFO "\t\t\t\t\tall the nhs:\n");							for( k = 0; k < info->fib_nhs; k ++ ){								struct fib_nh *nh = &info->fib_nh[0];								printk(KERN_INFO "\t\t\t\t\t\t%u.%u.%u.%u\n", nh->nh_gw);								printk(KERN_INFO "\n");							}						}						}				}			}				i++;			zone = zone->fz_next;		}	}#endif}static void mynl_fib_lookup_init(void){}static int myfib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr){	return 0;}static int myfib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr){	struct net_device *dev = ptr;	struct in_device *in_dev = __in_dev_get_rtnl(dev);/*	if (event == NETDEV_UNREGISTER) {		fib_disable_ip(dev, 2);		return NOTIFY_DONE;	}*/	if (!in_dev)		return NOTIFY_DONE;	switch (event) {		case NETDEV_UP:			for_ifa(in_dev) {				myfib_add_ifaddr(ifa);			} endfor_ifa(in_dev);#ifdef CONFIG_IP_ROUTE_MULTIPATH			//fib_sync_up(dev);#endif			//rt_cache_flush(-1);			break;	}	return NOTIFY_DONE;}static struct notifier_block myfib_inetaddr_notifier = {	.notifier_call = myfib_inetaddr_event,};static struct notifier_block myfib_netdev_notifier = {	.notifier_call = myfib_netdev_event,};void __init myip_fib_init(void){#ifndef CONFIG_IP_MULTIPLE_TABLES	myip_fib_local_table = myfib_hash_init(RT_TABLE_LOCAL);	myip_fib_main_table  = myfib_hash_init(RT_TABLE_MAIN);#else	myfib_rules_init();#endif	register_netdevice_notifier(&myfib_netdev_notifier);	register_inetaddr_notifier(&myfib_inetaddr_notifier);	mynl_fib_lookup_init();}void __exit myip_fib_delete( int tb_id ){	struct fib_table *tb = myfib_get_table( tb_id );	struct fn_hash *table;	struct fn_zone *zone;	if( tb == NULL )		return;	else		table = (struct fn_hash *)tb->tb_data;	zone = table->fn_zone_list;	while( zone != NULL ){		struct hlist_head *head;		struct hlist_node *node;		struct hlist_node *tmp;		struct fib_node *f;		int j;		for( j = 0; j < zone->fz_divisor; j ++ ){			head = &zone->fz_hash[j];			hlist_for_each_entry_safe( f, node, tmp, head, fn_hash ){				struct fib_alias* alias;				struct fib_alias* tmp;				list_for_each_entry_safe( alias, tmp, &(f->fn_alias), fa_list ){					list_del( &(f->fn_alias) );					kmem_cache_free( myfn_alias_kmem, alias );				}				hlist_del( node );				kmem_cache_free( myfn_hash_kmem, f );			}		}			zone = zone->fz_next;	}}void __exit myip_fib_exit(void){	int i;	unregister_netdevice_notifier( &myfib_netdev_notifier);	unregister_inetaddr_notifier( &myfib_inetaddr_notifier);	for( i = 1; i <= RT_TABLE_MAX; i ++ )		myip_fib_delete( i );	myfib_info_delete();	if ( myfn_hash_kmem != NULL )		kmem_cache_destroy( myfn_hash_kmem );	if ( myfn_alias_kmem != NULL )		kmem_cache_destroy( myfn_alias_kmem );	#ifndef CONFIG_IP_MULTIPLE_TABLES	if( myip_fib_local_table )		kfree( myip_fib_local_table );	if( myip_fib_main_table )		kfree( myip_fib_main_table );#else    unregister_netdevice_notifier( &myfib_rules_notifier );#endif}

⌨️ 快捷键说明

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