📄 my_route.c
字号:
#define MYIN_DEV_LOG_MARTIANS(in_dev)\ (myipv4_devconf.log_martians || (in_dev)->cnf.log_martians)#define RT_FL_TOS(oldflp) \ ((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))#define MYIN_DEV_SHARED_MEDIA(in_dev) \ (myipv4_devconf.shared_media || (in_dev)->cnf.shared_media)#define MYIN_DEV_MFORWARD(in_dev) \ (myipv4_devconf.mc_forwarding && (in_dev)->cnf.mc_forwarding)#define IP_MAX_MTU 0xFFF0#define RT_GC_TIMEOUT (300*HZ)static int myip_rt_min_delay = 2 * HZ;static int myip_rt_max_delay = 10 * HZ;static int myip_rt_max_size;static int myip_rt_gc_timeout = RT_GC_TIMEOUT;static int myip_rt_gc_interval = 60 * HZ;static int myip_rt_gc_min_interval = HZ / 2;static int myip_rt_redirect_number = 9;static int myip_rt_redirect_load = HZ / 50;static int myip_rt_redirect_silence = ((HZ / 50) << (9 + 1));static int myip_rt_error_cost = HZ;static int myip_rt_error_burst = 5 * HZ;static int myip_rt_gc_elasticity = 8;static int myip_rt_mtu_expires = 10 * 60 * HZ;static int myip_rt_min_pmtu = 512 + 20 + 20;static int myip_rt_min_advmss = 256;static int myip_rt_secret_interval = 10 * 60 * HZ;static unsigned long myrt_deadline;static struct timer_list myrt_flush_timer;static struct timer_list myrt_periodic_timer;static struct timer_list myrt_secret_timer;static int myip_rt_max_size;# define myrt_hash_lock_addr(slot) NULL# define myrt_hash_lock_init()struct myrt_hash_bucket{ struct rtable *chain;};static __initdata unsigned long myrhash_entries;#ifdef CONFIG_NET_CLS_ROUTEstruct ip_rt_acct *myip_rt_acct;unsigned long myip_rt_acct_order;#endifstatic struct myrt_hash_bucket *myrt_hash_table;static unsigned long mytable_order;static unsigned myrt_hash_mask;static int myrt_hash_log;static unsigned int myrt_hash_rnd;static DEFINE_PER_CPU(struct rt_cache_stat, myrt_cache_stat);#define MYRT_CACHE_STAT_INC(field) \ (per_cpu(myrt_cache_stat, raw_smp_processor_id()).field++)void myip_rt_get_source(u8 *addr, struct rtable *rt){ u32 src; struct fib_result res; if (rt->fl.iif == 0) src = rt->rt_src; else if(myfib_lookup(&rt->fl, &res) == 0) { src = MYFIB_RES_PREFSRC(res); fib_res_put(&res); } else src = myinet_select_addr(rt->u.dst.dev, rt->rt_gateway, RT_SCOPE_UNIVERSE); memcpy(addr, &src, 4);}static __inline__ void myrt_free(struct rtable *rt){ multipath_remove(rt); call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);}void myrt_bind_peer(struct rtable *rt, int create){ static DEFINE_SPINLOCK(rt_peer_lock); struct inet_peer *peer; peer = myinet_getpeer(rt->rt_dst, create); spin_lock_bh(&rt_peer_lock); if (rt->peer == NULL) { rt->peer = peer; peer = NULL; } spin_unlock_bh(&rt_peer_lock); if (peer) myinet_putpeer(peer);}static struct inet_peer *myrt_get_peer(struct rtable *rt){ if (rt->peer) return rt->peer; myrt_bind_peer(rt, 0); return rt->peer;}void __myip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more){/* struct rtable *rt = (struct rtable *) dst; if (rt) { if (rt->peer == NULL) myrt_bind_peer(rt, 1); if (rt->peer) { iph->id = htons(inet_getid(rt->peer, more)); return; } } else ; ip_select_fb_ident(iph);*/}static DEFINE_SPINLOCK( myrt_flush_lock );static void myrt_run_flush(unsigned long dummy);void myrt_cache_flush(int delay){ unsigned long now = jiffies; int user_mode = !in_softirq(); if (delay < 0) delay = myip_rt_min_delay; multipath_flush(); spin_lock_bh( &myrt_flush_lock ); if( del_timer( &myrt_flush_timer ) && delay > 0 && myrt_deadline ){ long tmo = (long)( myrt_deadline - now ); if (user_mode && tmo < myip_rt_max_delay - myip_rt_min_delay ) tmo = 0; if (delay > tmo) delay = tmo; } if (delay <= 0) { spin_unlock_bh( &myrt_flush_lock ); myrt_run_flush(0); return; } if( myrt_deadline == 0 ) myrt_deadline = now + myip_rt_max_delay; mod_timer(&myrt_flush_timer, now+delay); spin_unlock_bh(&myrt_flush_lock);}static unsigned int myrt_hash_code(u32 daddr, u32 saddr, u8 tos){ return (jhash_3words(daddr, saddr, (u32) tos, myrt_hash_rnd) & myrt_hash_mask);}extern int myip_output(struct sk_buff *skb);extern int myip_mc_output(struct sk_buff *skb);extern int myip_mr_input(struct sk_buff *skb);extern int myip_local_deliver(struct sk_buff *skb);static struct dst_ops myipv4_dst_ops;static void myrt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag);int myip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto);static inline int __mymkroute_output(struct rtable **result, struct fib_result* res, const struct flowi *fl, const struct flowi *oldflp, struct net_device *dev_out, unsigned flags) { struct rtable *rth; struct in_device *in_dev; u32 tos = RT_FL_TOS(oldflp); int err = 0; printk(KERN_INFO "old src: %u.%u.%u.%u, dst: %u.%u.%u.%u\n", NIPQUAD(oldflp->fl4_src), NIPQUAD(oldflp->fl4_dst) ); printk(KERN_INFO "new src: %u.%u.%u.%u., dst: %u.%u.%u.%u\n", NIPQUAD(fl->fl4_src), NIPQUAD(fl->fl4_dst) ); if( LOOPBACK(fl->fl4_src) && !( dev_out->flags & IFF_LOOPBACK ) ) return -EINVAL; if( fl->fl4_dst == 0xFFFFFFFF ) res->type = RTN_BROADCAST; else if( MULTICAST(fl->fl4_dst) ) res->type = RTN_MULTICAST; else if( BADCLASS(fl->fl4_dst) || ZERONET(fl->fl4_dst) ) return -EINVAL; if( dev_out->flags & IFF_LOOPBACK ) flags |= RTCF_LOCAL; in_dev = in_dev_get(dev_out); if( !in_dev ) return -EINVAL; if( res->type == RTN_BROADCAST ){ flags |= RTCF_BROADCAST | RTCF_LOCAL; if( res->fi ){ fib_info_put(res->fi); res->fi = NULL; } }else if( res->type == RTN_MULTICAST ){ flags |= RTCF_MULTICAST | RTCF_LOCAL; if( !myip_check_mc(in_dev, oldflp->fl4_dst, oldflp->fl4_src, oldflp->proto) ) flags &= ~RTCF_LOCAL; if( res->fi && res->prefixlen < 4 ){ fib_info_put(res->fi); res->fi = NULL; } } rth = dst_alloc( &myipv4_dst_ops ); if (!rth) { err = -ENOBUFS; goto cleanup; } atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST;#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED if (res->fi) { rth->rt_multipath_alg = res->fi->fib_mp_alg; if (res->fi->fib_nhs > 1) rth->u.dst.flags |= DST_BALANCED; }#endif if (in_dev->cnf.no_xfrm) rth->u.dst.flags |= DST_NOXFRM; if (in_dev->cnf.no_policy) rth->u.dst.flags |= DST_NOPOLICY; rth->fl.fl4_dst = oldflp->fl4_dst; rth->fl.fl4_tos = tos; rth->fl.fl4_src = oldflp->fl4_src; rth->fl.oif = oldflp->oif;#ifdef CONFIG_IP_ROUTE_FWMARK rth->fl.fl4_fwmark= oldflp->fl4_fwmark;#endif rth->rt_dst = fl->fl4_dst; rth->rt_src = fl->fl4_src; rth->rt_iif = oldflp->oif ? : dev_out->ifindex; rth->u.dst.dev = dev_out; dev_hold(dev_out); rth->idev = in_dev_get(dev_out); rth->rt_gateway = fl->fl4_dst; rth->rt_spec_dst= fl->fl4_src; rth->u.dst.output=myip_output; MYRT_CACHE_STAT_INC(out_slow_tot); if (flags & RTCF_LOCAL) { rth->u.dst.input = myip_local_deliver; rth->rt_spec_dst = fl->fl4_dst; } if( flags & (RTCF_BROADCAST | RTCF_MULTICAST) ){ rth->rt_spec_dst = fl->fl4_src; if(flags & RTCF_LOCAL && !(dev_out->flags & IFF_LOOPBACK) ){ rth->u.dst.output = myip_mc_output; MYRT_CACHE_STAT_INC(out_slow_mc); }#ifdef CONFIG_IP_MROUTE if( res->type == RTN_MULTICAST ){ if( MYIN_DEV_MFORWARD(in_dev) && !LOCAL_MCAST(oldflp->fl4_dst) ){ rth->u.dst.input = myip_mr_input; rth->u.dst.output = myip_mc_output; } }#endif } myrt_set_nexthop(rth, res, 0); rth->rt_flags = flags; *result = rth;cleanup: /* release work reference to inet device */ in_dev_put(in_dev); return err;}static int myrt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp);static inline int myip_mkroute_output_def(struct rtable **rp, struct fib_result* res, const struct flowi *fl, const struct flowi *oldflp, struct net_device *dev_out, unsigned flags){ struct rtable *rth = NULL; int err = __mymkroute_output(&rth, res, fl, oldflp, dev_out, flags); unsigned hash; if (err == 0) { u32 tos = RT_FL_TOS(oldflp); hash = myrt_hash_code(oldflp->fl4_dst, oldflp->fl4_src ^ (oldflp->oif << 5), tos); err = myrt_intern_hash(hash, rth, rp); } return err;}static inline int myip_mkroute_output( struct rtable** rp, struct fib_result* res, const struct flowi *fl, const struct flowi *oldflp, struct net_device *dev_out, unsigned flags ){#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED u32 tos = RT_FL_TOS(oldflp); unsigned char hop; unsigned hash; int err = -EINVAL; struct rtable *rth = NULL; if( res->fi && res->fi->fib_nhs > 1 ){ unsigned char hopcount = res->fi->fib_nhs; for( hop = 0; hop < hopcount; hop++ ){ } }#else return myip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags);#endif}static int myip_route_output_slow(struct rtable **rp, const struct flowi *oldflp){ u32 tos = RT_FL_TOS(oldflp); struct flowi fl = { .nl_u = { .ip4_u = { .daddr = oldflp->fl4_dst, .saddr = oldflp->fl4_src, .tos = tos & IPTOS_RT_MASK, .scope = ((tos & RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE),#ifdef CONFIG_IP_ROUTE_FWMARK .fwmark = oldflp->fl4_fwmark#endif } }, .iif = loopback_dev.ifindex, .oif = oldflp->oif }; struct fib_result res; unsigned flags = 0; struct net_device *dev_out = NULL; int free_res = 0; int err; res.fi = NULL;#ifdef CONFIG_IP_MULTIPLE_TABLES res.r = NULL;#endif if( oldflp->fl4_src ){ err = -EINVAL; if( MULTICAST(oldflp->fl4_src) || BADCLASS(oldflp->fl4_src) || ZERONET(oldflp->fl4_src) ) goto out; dev_out = myip_dev_find(oldflp->fl4_src); if (dev_out == NULL) goto out; if (oldflp->oif == 0 && (MULTICAST(oldflp->fl4_dst) || oldflp->fl4_dst == 0xFFFFFFFF)) { fl.oif = dev_out->ifindex; goto make_route; } if( dev_out ) dev_put( dev_out ); dev_out = NULL; } if( oldflp->oif ){ dev_out = dev_get_by_index( oldflp->oif ); err = -ENODEV; if (dev_out == NULL) goto out; if (__in_dev_get_rtnl(dev_out) == NULL) { dev_put(dev_out); goto out; } if( LOCAL_MCAST(oldflp->fl4_dst) || oldflp->fl4_dst == 0xFFFFFFFF ){ if (!fl.fl4_src) fl.fl4_src = myinet_select_addr(dev_out, 0, RT_SCOPE_LINK); goto make_route; } if( !fl.fl4_src ){ if( MULTICAST(oldflp->fl4_dst) ) fl.fl4_src = myinet_select_addr(dev_out, 0, fl.fl4_scope); else if( !oldflp->fl4_dst ) fl.fl4_src = myinet_select_addr(dev_out, 0, RT_SCOPE_HOST); } } if (!fl.fl4_dst){ fl.fl4_dst = fl.fl4_src; if (!fl.fl4_dst) fl.fl4_dst = fl.fl4_src = htonl(INADDR_LOOPBACK); if (dev_out) dev_put(dev_out); dev_out = &loopback_dev; dev_hold(dev_out); fl.oif = loopback_dev.ifindex; res.type = RTN_LOCAL; flags |= RTCF_LOCAL; goto make_route; } if( myfib_lookup(&fl, &res) ){ res.fi = NULL; if (oldflp->oif) { if (fl.fl4_src == 0) fl.fl4_src = myinet_select_addr(dev_out, 0, RT_SCOPE_LINK); res.type = RTN_UNICAST; goto make_route; } if (dev_out) dev_put(dev_out); err = -ENETUNREACH; goto out; } free_res = 1; if (res.type == RTN_LOCAL) { if( !fl.fl4_src ) fl.fl4_src = fl.fl4_dst; if( dev_out ) dev_put(dev_out); dev_out = &loopback_dev; dev_hold(dev_out); fl.oif = dev_out->ifindex; if( res.fi ) fib_info_put(res.fi); res.fi = NULL; flags |= RTCF_LOCAL; goto make_route; }#ifdef CONFIG_IP_ROUTE_MULTIPATH if (res.fi->fib_nhs > 1 && fl.oif == 0) myfib_select_multipath(&fl, &res); else#endif if (!res.prefixlen && res.type == RTN_UNICAST && !fl.oif) myfib_select_default(&fl, &res); if (!fl.fl4_src) fl.fl4_src = MYFIB_RES_PREFSRC(res); if( dev_out ) dev_put(dev_out); dev_out = FIB_RES_DEV(res); dev_hold(dev_out); fl.oif = dev_out->ifindex;make_route: err = myip_mkroute_output(rp, &res, &fl, oldflp, dev_out, flags); if (free_res) fib_res_put(&res); if (dev_out) dev_put(dev_out);out: return err;}int __myip_route_output_key(struct rtable **rp, const struct flowi *flp){ unsigned hash; struct rtable *rth; hash = myrt_hash_code(flp->fl4_dst, flp->fl4_src ^ (flp->oif << 5), flp->fl4_tos); rcu_read_lock_bh(); for (rth = rcu_dereference(myrt_hash_table[hash].chain); rth; rth = rcu_dereference(rth->u.rt_next)) { if (rth->fl.fl4_dst == flp->fl4_dst && rth->fl.fl4_src == flp->fl4_src && rth->fl.iif == 0 && rth->fl.oif == flp->oif &&#ifdef CONFIG_IP_ROUTE_FWMARK rth->fl.fl4_fwmark == flp->fl4_fwmark &&#endif !((rth->fl.fl4_tos ^ flp->fl4_tos) & (IPTOS_RT_MASK | RTO_ONLINK))) { if( multipath_select_route(flp, rth, rp) ){ dst_hold(&(*rp)->u.dst); MYRT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); return 0; } rth->u.dst.lastuse = jiffies; dst_hold(&rth->u.dst); rth->u.dst.__use++; MYRT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); *rp = rth; return 0; } MYRT_CACHE_STAT_INC(out_hlist_search); } rcu_read_unlock_bh(); return myip_route_output_slow(rp, flp);}int myip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags){ int err; if ((err = __myip_route_output_key(rp, flp)) != 0) return err; if (flp->proto) { if (!flp->fl4_src) flp->fl4_src = (*rp)->rt_src; if (!flp->fl4_dst) flp->fl4_dst = (*rp)->rt_dst;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -