📄 myfib_frontend.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 + -