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

📄 fib_frontend.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
字号:
/* fib_frontend.c * linqianghe@163.com * 2006-11-06 */#include "fib_frontend.h"#include "fib_rules.h"#include "rtnetlink.h"#include "log.h"#include "devinet.h"#include "ip_fib.h"#include "fib_hash.h"#include "arp.h"#include "route.h"#include "fib_semantics.h"#include <linux/inetdevice.h>#include <linux/in.h>#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;}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) {			PR_ERR( "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	dump_fib_info();	if( myip_fib_local_table )		dump_fib_node( myip_fib_local_table );	if( myip_fib_main_table )		dump_fib_node( myip_fib_main_table );	{		/*AC103002*/		/*FFFFFF7F*/		struct flowi        fl = { .nl_u = { .ip4_u = { .daddr = 0xFFFFFF7F } } };    	struct fib_result   res;		int j;		if( myip_fib_local_table )			myip_fib_local_table->tb_lookup( myip_fib_local_table, &fl, &res );		printk( KERN_NOTICE "prefixlen: %d\n", res.prefixlen );		printk( KERN_NOTICE "nh_sel: %d\n", res.nh_sel );		printk( KERN_NOTICE "type: %d\n", res.type );		printk( KERN_NOTICE "scope: %d\n", res.scope );		if( res.fi != NULL ){			printk( KERN_NOTICE "info: \n" );			printk( KERN_NOTICE "\tflags:   %x\n", res.fi->fib_flags );			printk( KERN_NOTICE "\tprotocol: %d\n", res.fi->fib_protocol );			printk( KERN_NOTICE "\tprefsrc: %u.%u.%u.%u\n", NIPQUAD(res.fi->fib_prefsrc) );			printk( KERN_NOTICE "\tpriority: %u\n", res.fi->fib_priority );			printk( KERN_NOTICE "\tnhs: %d\n", res.fi->fib_nhs );			for( j=0; j < res.fi->fib_nhs; j ++ ){				printk( KERN_NOTICE "\t\tdev name: %s\n", res.fi->fib_nh[j].nh_dev->name );				printk( KERN_NOTICE "\t\tflags: %x\n", res.fi->fib_nh[j].nh_flags );				printk( KERN_NOTICE "\t\tscope: %x\n", res.fi->fib_nh[j].nh_scope );				printk( KERN_NOTICE "\t\tgw: %u.%u.%u.%u\n", NIPQUAD(res.fi->fib_nh[j].nh_gw) );			}		}	}#endif}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;	res.r = NULL;		if( myip_fib_local_table ){		ret = RTN_UNICAST;		if( !myip_fib_local_table->tb_lookup( myip_fib_local_table, &fl, &res) ){			ret = res.type;			myfib_res_put( &res );		}	}	return ret;}static void myfib_flush(void){	int flushed = 0;	struct fib_table *tb;	int id;	for( id = RT_TABLE_MAX; id > 0; id-- ){		if( (tb = myfib_get_table(id))==NULL )			continue;		flushed += tb->tb_flush( tb );	}	if( flushed )		myrt_cache_flush(-1);}static void myfib_disable_ip( struct net_device *dev, int force ){	if( myfib_sync_down(0, dev, force) )		myfib_flush();	myrt_cache_flush( 0 );	myarp_ifdown( dev );}static void myfib_del_ifaddr( struct in_ifaddr *ifa ){	struct in_device *in_dev = ifa->ifa_dev;	struct net_device *dev = in_dev->dev;	struct in_ifaddr *ifa1;	struct in_ifaddr *prim = ifa;	u32 brd = ifa->ifa_address | ~ifa->ifa_mask;	u32 any = ifa->ifa_address & ifa->ifa_mask;#define LOCAL_OK	1#define BRD_OK		2#define BRD0_OK		4#define BRD1_OK		8	unsigned ok = 0;	if( !(ifa->ifa_flags & IFA_F_SECONDARY) )		myfib_magic( RTM_DELROUTE, dev->flags & IFF_LOOPBACK ? RTN_LOCAL :						RTN_UNICAST, any, ifa->ifa_prefixlen, prim );	else{		prim = myinet_ifa_byprefix(in_dev, any, ifa->ifa_mask);		if (prim == NULL) {			PR_ERR( "fib_del_ifaddr: bug: prim == NULL\n" );			return;		}	}	for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {		if (ifa->ifa_local == ifa1->ifa_local)			ok |= LOCAL_OK;		if (ifa->ifa_broadcast == ifa1->ifa_broadcast)			ok |= BRD_OK;		if (brd == ifa1->ifa_broadcast)			ok |= BRD1_OK;		if (any == ifa1->ifa_broadcast)			ok |= BRD0_OK;	}	if ( !(ok & BRD_OK) )		myfib_magic( RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim );	if ( !(ok & BRD1_OK) )		myfib_magic( RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim );	if ( !(ok & BRD0_OK) )		myfib_magic( RTM_DELROUTE, RTN_BROADCAST, any, 32, prim );	if ( !(ok & LOCAL_OK) ){		myfib_magic( RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim );		if( myinet_addr_type(ifa->ifa_local) != RTN_LOCAL ){			if( myfib_sync_down(ifa->ifa_local, NULL, 0) )				myfib_flush();		}	}#undef LOCAL_OK#undef BRD_OK#undef BRD0_OK#undef BRD1_OK}struct 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:	myfib_res_put( &res );	return dev;}static int myfib_inetaddr_event( struct notifier_block *this, unsigned long event, void *ptr ){	struct in_ifaddr *ifa = (struct in_ifaddr*)ptr;	switch (event) {	case NETDEV_UP:		myfib_add_ifaddr(ifa);#ifdef CONFIG_IP_ROUTE_MULTIPATH		myfib_sync_up(ifa->ifa_dev->dev);#endif		myrt_cache_flush(-1);		break;	case NETDEV_DOWN:		myfib_del_ifaddr(ifa);		if( ifa->ifa_dev->ifa_list == NULL ){			myfib_disable_ip( ifa->ifa_dev->dev, 1 );		}else{			myrt_cache_flush(-1);		}		break;	}	return NOTIFY_DONE;}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) {		myfib_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		myfib_sync_up(dev);#endif		myrt_cache_flush(-1);		break;	case NETDEV_DOWN:		myfib_disable_ip(dev, 0);		break;	case NETDEV_CHANGEMTU:	case NETDEV_CHANGE:		myrt_cache_flush(0);		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){	myfib_rules_init();	register_netdevice_notifier( &myfib_netdev_notifier );	register_inetaddr_notifier( &myfib_inetaddr_notifier );	//nl_fib_lookup_init();}void __exit myip_fib_exit(void){	int i;	struct fn_hash *table;	struct fn_zone *plist1, *plist2;	unregister_inetaddr_notifier( &myfib_inetaddr_notifier );	unregister_netdevice_notifier( &myfib_netdev_notifier );	myfib_rules_exit();	for( i = 0; i < RT_TABLE_MAX+1; i ++ ){		if( myfib_tables[i] != NULL ){			table = (struct fn_hash *) myfib_tables[i]->tb_data;			plist1 = table->fn_zone_list;			while( plist1 != NULL ){				PR_DEBUG( "delete fz_zone!\n");				plist2 = plist1->fz_next;				myfn_zone_free( plist1 );				plist1 = plist2;			}			kfree( table );		}	}		myfib_hash_exit();}

⌨️ 快捷键说明

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