📄 fib_rules.c
字号:
/* fib_rules.c * linqianghe@163.com * 2006-11-07 */#include "fib_rules.h"#include "rtnetlink.h"#include "log.h"#include "ip_fib.h"#include <linux/if.h>#include <linux/netdevice.h>struct fib_rule{ struct fib_rule *r_next; atomic_t r_clntref; u32 r_preference; unsigned char r_table; unsigned char r_action; unsigned char r_dst_len; unsigned char r_src_len; u32 r_src; u32 r_srcmask; u32 r_dst; u32 r_dstmask; u32 r_srcmap; u8 r_flags; u8 r_tos;#ifdef CONFIG_IP_ROUTE_FWMARK u32 r_fwmark;#endif int r_ifindex;#ifdef CONFIG_NET_CLS_ROUTE __u32 r_tclassid;#endif char r_ifname[IFNAMSIZ]; int r_dead;};static struct fib_rule mydefault_rule = { .r_clntref = ATOMIC_INIT(2), .r_preference = 0x7FFF, .r_table = RT_TABLE_DEFAULT, .r_action = RTN_UNICAST,};static struct fib_rule mymain_rule = { .r_next = &mydefault_rule, .r_clntref = ATOMIC_INIT(2), .r_preference = 0x7FFE, .r_table = RT_TABLE_MAIN, .r_action = RTN_UNICAST,};static struct fib_rule mylocal_rule = { .r_next = &mymain_rule, .r_clntref = ATOMIC_INIT(2), .r_table = RT_TABLE_LOCAL, .r_action = RTN_UNICAST,};static struct fib_rule *myfib_rules = &mylocal_rule;static DEFINE_RWLOCK( myfib_rules_lock );#ifdef CONFIG_NET_CLS_ROUTEu32 myfib_rules_tclass(struct fib_result *res){ if( res->r ) return res->r->r_tclassid; return 0;}#endifstatic void myfib_rules_detach(struct net_device *dev){ struct fib_rule *r; for( r = myfib_rules; r; r = r->r_next ){ if( r->r_ifindex == dev->ifindex ){ write_lock_bh( &myfib_rules_lock ); r->r_ifindex = -1; write_unlock_bh( &myfib_rules_lock ); } }}static void myfib_rules_attach( struct net_device *dev ){ struct fib_rule *r; for( r = myfib_rules; r; r = r->r_next ){ if( r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0 ) { write_lock_bh( &myfib_rules_lock ); r->r_ifindex = dev->ifindex; write_unlock_bh( &myfib_rules_lock ); } }}int myfib_lookup(const struct flowi *flp, struct fib_result *res){ int err; struct fib_rule *r, *policy; struct fib_table *tb; u32 daddr = flp->fl4_dst; u32 saddr = flp->fl4_src; PR_DEBUG("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ", NIPQUAD(flp->fl4_dst), NIPQUAD(flp->fl4_src)); read_lock(&myfib_rules_lock); for( r = myfib_rules; r; r=r->r_next) { if( ((saddr^r->r_src) & r->r_srcmask) || ((daddr^r->r_dst) & r->r_dstmask) || (r->r_tos && r->r_tos != flp->fl4_tos) ||#ifdef CONFIG_IP_ROUTE_FWMARK (r->r_fwmark && r->r_fwmark != flp->fl4_fwmark) ||#endif (r->r_ifindex && r->r_ifindex != flp->iif)) continue; PR_DEBUG("tb %d r %d ", r->r_table, r->r_action); switch (r->r_action) { case RTN_UNICAST: policy = r; break; case RTN_UNREACHABLE: read_unlock( &myfib_rules_lock ); return -ENETUNREACH; default: case RTN_BLACKHOLE: read_unlock( &myfib_rules_lock ); return -EINVAL; case RTN_PROHIBIT: read_unlock( &myfib_rules_lock ); return -EACCES; } if ((tb = myfib_get_table(r->r_table)) == NULL) continue; err = tb->tb_lookup( tb, flp, res ); if( err == 0 ){ res->r = policy; if( policy ) atomic_inc(&policy->r_clntref); read_unlock( &myfib_rules_lock ); return 0; } if (err < 0 && err != -EAGAIN) { read_unlock( &myfib_rules_lock ); return err; } } PR_DEBUG("FAILURE\n"); read_unlock( &myfib_rules_lock ); return -ENETUNREACH;}static int myfib_rules_event( struct notifier_block *this, unsigned long event, void *ptr ){ struct net_device *dev = ptr; if( event == NETDEV_UNREGISTER ) myfib_rules_detach(dev); else if( event == NETDEV_REGISTER ) myfib_rules_attach(dev); return NOTIFY_DONE;}void myfib_select_default( const struct flowi *flp, struct fib_result *res ){ if( res->r && res->r->r_action == RTN_UNICAST && FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) { struct fib_table *tb; if ((tb = myfib_get_table(res->r->r_table)) != NULL) tb->tb_select_default(tb, flp, res); }}void myfib_rule_put(struct fib_rule *r){ if( atomic_dec_and_test(&r->r_clntref) ){ if( r->r_dead ) kfree(r); else PR_NOTICE("Freeing alive rule %p\n", r); }}static struct notifier_block myfib_rules_notifier = { .notifier_call = myfib_rules_event,};void __init myfib_rules_init(void){ register_netdevice_notifier( &myfib_rules_notifier );}void __exit myfib_rules_exit(void){ unregister_netdevice_notifier( &myfib_rules_notifier );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -