📄 my_route.c
字号:
return err;#else return myip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);#endif}static int myip_error(struct sk_buff *skb){ struct rtable *rt = (struct rtable*)skb->dst; unsigned long now; int code; switch (rt->u.dst.error) { case EINVAL: default: goto out; case EHOSTUNREACH: code = ICMP_HOST_UNREACH; break; case ENETUNREACH: code = ICMP_NET_UNREACH; break; case EACCES: code = ICMP_PKT_FILTERED; break; } now = jiffies; rt->u.dst.rate_tokens += now - rt->u.dst.rate_last; if (rt->u.dst.rate_tokens > myip_rt_error_burst) rt->u.dst.rate_tokens = myip_rt_error_burst; rt->u.dst.rate_last = now; if (rt->u.dst.rate_tokens >= myip_rt_error_cost) { rt->u.dst.rate_tokens -= myip_rt_error_cost; ;//icmp_send(skb, ICMP_DEST_UNREACH, code, 0); }out: kfree_skb(skb); return 0;} int myip_mr_input(struct sk_buff *skb);static int myip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr, u8 tos, struct net_device *dev, int our){ unsigned hash; struct rtable *rth; u32 spec_dst; struct in_device *in_dev = in_dev_get(dev); u32 itag = 0; if (in_dev == NULL) return -EINVAL; if (MULTICAST(saddr) || BADCLASS(saddr) || LOOPBACK(saddr) || skb->protocol != htons(ETH_P_IP)) goto e_inval; if (ZERONET(saddr)) { if (!LOCAL_MCAST(daddr)) goto e_inval; spec_dst = myinet_select_addr(dev, 0, RT_SCOPE_LINK); }else if( myfib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag) < 0) goto e_inval; rth = dst_alloc(&myipv4_dst_ops); if (!rth) goto e_nobufs; rth->u.dst.output= myip_rt_bug; atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; if (in_dev->cnf.no_policy) rth->u.dst.flags |= DST_NOPOLICY; rth->fl.fl4_dst = daddr; rth->rt_dst = daddr; rth->fl.fl4_tos = tos;#ifdef CONFIG_IP_ROUTE_FWMARK rth->fl.fl4_fwmark= skb->nfmark;#endif rth->fl.fl4_src = saddr; rth->rt_src = saddr;#ifdef CONFIG_NET_CLS_ROUTE rth->u.dst.tclassid = itag;#endif rth->rt_iif = rth->fl.iif = dev->ifindex; rth->u.dst.dev = &loopback_dev; dev_hold(rth->u.dst.dev); rth->idev = in_dev_get(rth->u.dst.dev); rth->fl.oif = 0; rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; rth->rt_type = RTN_MULTICAST; rth->rt_flags = RTCF_MULTICAST; if (our) { rth->u.dst.input= myip_local_deliver; rth->rt_flags |= RTCF_LOCAL; }#ifdef CONFIG_IP_MROUTE if (!LOCAL_MCAST(daddr) && MYIN_DEV_MFORWARD(in_dev)) rth->u.dst.input = myip_mr_input;#endif MYRT_CACHE_STAT_INC(in_slow_mc); in_dev_put(in_dev); hash = myrt_hash_code(daddr, saddr ^ (dev->ifindex << 5), tos); return myrt_intern_hash(hash, rth, (struct rtable**) &skb->dst);e_nobufs: in_dev_put(in_dev); return -ENOBUFS;e_inval: in_dev_put(in_dev); return -EINVAL;}static int myip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr, u8 tos, struct net_device *dev){ struct fib_result res; struct in_device *in_dev = in_dev_get(dev); struct flowi fl = { .nl_u = { .ip4_u = { .daddr = daddr, .saddr = saddr, .tos = tos, .scope = RT_SCOPE_UNIVERSE,#ifdef CONFIG_IP_ROUTE_FWMARK .fwmark = skb->nfmark#endif } }, .iif = dev->ifindex }; unsigned flags = 0; u32 itag = 0; struct rtable * rth; unsigned hash; u32 spec_dst; int err = -EINVAL; int free_res = 0; if (!in_dev) goto out; if (MULTICAST(saddr) || BADCLASS(saddr) || LOOPBACK(saddr)) goto martian_source; if (daddr == 0xFFFFFFFF || (saddr == 0 && daddr == 0)) goto brd_input; if (ZERONET(saddr)) goto martian_source; if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr)) goto martian_destination; if( (err = myfib_lookup(&fl, &res)) != 0 ){ if (!IN_DEV_FORWARD(in_dev)) goto e_hostunreach; goto no_route; } free_res = 1; MYRT_CACHE_STAT_INC(in_slow_tot); printk(KERN_INFO "info: %u.%u.%u.%u\n", NIPQUAD((res.fi)->fib_prefsrc) ); printk(KERN_INFO "fa type: %d\n", res.type); printk(KERN_INFO "fa scope: %d\n", res.scope); if (res.type == RTN_BROADCAST) goto brd_input; if (res.type == RTN_LOCAL) { int result; result = myfib_validate_source(saddr, daddr, tos, loopback_dev.ifindex, dev, &spec_dst, &itag); printk(KERN_INFO "the res: %d\n", result ); printk(KERN_INFO "spec dst: %u.%u.%u.%u\n", NIPQUAD(spec_dst) ); if (result < 0) goto martian_source; if (result) flags |= RTCF_DIRECTSRC; spec_dst = daddr; goto local_input; } if (!IN_DEV_FORWARD(in_dev)) goto e_hostunreach; if (res.type != RTN_UNICAST) goto martian_destination; err = myip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos); if (err == -ENOBUFS) goto e_nobufs; if (err == -EINVAL) goto e_inval;done: in_dev_put(in_dev); if (free_res) fib_res_put(&res);out: return err;brd_input: if (skb->protocol != htons(ETH_P_IP)) goto e_inval; if( ZERONET(saddr) ) spec_dst = myinet_select_addr(dev, 0, RT_SCOPE_LINK); else{ err = myfib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag); if( err < 0 ) goto martian_source; if( err ) flags |= RTCF_DIRECTSRC; } flags |= RTCF_BROADCAST; res.type = RTN_BROADCAST; MYRT_CACHE_STAT_INC(in_brd);local_input: rth = dst_alloc( &myipv4_dst_ops ); if (!rth) goto e_nobufs; rth->u.dst.output= myip_rt_bug; atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; if (in_dev->cnf.no_policy) rth->u.dst.flags |= DST_NOPOLICY; rth->fl.fl4_dst = daddr; rth->rt_dst = daddr; rth->fl.fl4_tos = tos;#ifdef CONFIG_IP_ROUTE_FWMARK rth->fl.fl4_fwmark= skb->nfmark;#endif rth->fl.fl4_src = saddr; rth->rt_src = saddr;#ifdef CONFIG_NET_CLS_ROUTE rth->u.dst.tclassid = itag;#endif rth->rt_iif = rth->fl.iif = dev->ifindex; rth->u.dst.dev = &loopback_dev; dev_hold(rth->u.dst.dev); rth->idev = in_dev_get(rth->u.dst.dev); rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; rth->u.dst.input= myip_local_deliver; rth->rt_flags = flags|RTCF_LOCAL; if (res.type == RTN_UNREACHABLE) { rth->u.dst.input= myip_error; rth->u.dst.error= -err; rth->rt_flags &= ~RTCF_LOCAL; } rth->rt_type = res.type; hash = myrt_hash_code(daddr, saddr ^ (fl.iif << 5), tos); err = myrt_intern_hash(hash, rth, (struct rtable**)&skb->dst); goto done;no_route: MYRT_CACHE_STAT_INC(in_no_route); spec_dst = myinet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); res.type = RTN_UNREACHABLE; goto local_input;martian_destination: MYRT_CACHE_STAT_INC(in_martian_dst);#ifdef CONFIG_IP_ROUTE_VERBOSE if (MYIN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) printk(KERN_WARNING "martian destination %u.%u.%u.%u from " "%u.%u.%u.%u, dev %s\n", NIPQUAD(daddr), NIPQUAD(saddr), dev->name);#endife_hostunreach: err = -EHOSTUNREACH; goto done;e_inval: err = -EINVAL; goto done;e_nobufs: err = -ENOBUFS; goto done;martian_source: myip_handle_martian_source(dev, in_dev, skb, daddr, saddr); goto e_inval;}extern int myip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto);int myip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr, u8 tos, struct net_device *dev){ struct rtable * rth; unsigned hash; int iif = dev->ifindex; tos &= IPTOS_RT_MASK; hash = myrt_hash_code(daddr, saddr ^ (iif << 5), tos); rcu_read_lock(); for (rth = rcu_dereference(myrt_hash_table[hash].chain); rth; rth = rcu_dereference(rth->u.rt_next)) { if (rth->fl.fl4_dst == daddr && rth->fl.fl4_src == saddr && rth->fl.iif == iif && rth->fl.oif == 0 &&#ifdef CONFIG_IP_ROUTE_FWMARK rth->fl.fl4_fwmark == skb->nfmark &&#endif rth->fl.fl4_tos == tos) { rth->u.dst.lastuse = jiffies; dst_hold(&rth->u.dst); rth->u.dst.__use++; MYRT_CACHE_STAT_INC(in_hit); rcu_read_unlock(); skb->dst = (struct dst_entry*)rth; return 0; } MYRT_CACHE_STAT_INC(in_hlist_search); } rcu_read_unlock(); if( MULTICAST(daddr) ){ struct in_device *in_dev; rcu_read_lock(); if ((in_dev = __in_dev_get_rcu(dev)) != NULL) { int our = myip_check_mc(in_dev, daddr, saddr, skb->nh.iph->protocol); if (our#ifdef CONFIG_IP_MROUTE || (!LOCAL_MCAST(daddr) && MYIN_DEV_MFORWARD(in_dev))#endif ){ rcu_read_unlock(); return myip_route_input_mc(skb, daddr, saddr, tos, dev, our); } } rcu_read_unlock(); return -EINVAL; } return myip_route_input_slow(skb, daddr, saddr, tos, dev);}static int myrt_cache_seq_open(struct inode *inode, struct file *file){ return 0;}ssize_t myseq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos){ return 0;}loff_t myseq_lseek(struct file *file, loff_t offset, int origin){ return 0;}int myseq_release_private(struct inode *inode, struct file *file){ return 0;}static int myip_rt_acct_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data){ return 0;}static struct file_operations myrt_cache_seq_fops = { .owner = THIS_MODULE, .open = myrt_cache_seq_open, .read = myseq_read, .llseek = myseq_lseek, .release = myseq_release_private,};static int myrt_cpu_seq_open(struct inode *inode, struct file *file){ return 0;}int myseq_release(struct inode *inode, struct file *file){ return 0;}static struct file_operations myrt_cpu_seq_fops = { .owner = THIS_MODULE, .open = myrt_cpu_seq_open, .read = myseq_read, .llseek = myseq_lseek, .release = myseq_release,};void myip_rt_multicast_event(struct in_device *in_dev){ myrt_cache_flush(0);}int __init myip_rt_init(void){ myrt_hash_rnd = (int) ((num_physpages ^ (num_physpages>>8)) ^ (jiffies ^ (jiffies >> 7)));#ifdef CONFIG_NET_CLS_ROUTE { int order; for (order = 0; (PAGE_SIZE << order) < 256 * sizeof(struct ip_rt_acct) * NR_CPUS; order++) /* NOTHING */; myip_rt_acct = (struct ip_rt_acct *)__get_free_pages(GFP_KERNEL, order); if (!myip_rt_acct) panic("IP: failed to allocate ip_rt_acct\n"); memset(myip_rt_acct, 0, PAGE_SIZE << order); myip_rt_acct_order = order; }#endif myipv4_dst_ops.kmem_cachep = kmem_cache_create("myip_dst_cache", sizeof(struct rtable), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (!myipv4_dst_ops.kmem_cachep) panic("IP: failed to allocate myip_dst_cache\n"); myrt_hash_table = (struct myrt_hash_bucket *) myalloc_large_system_hash("MYIP route cache", sizeof(struct myrt_hash_bucket), myrhash_entries,(num_physpages >= 128 * 1024) ? (27 - PAGE_SHIFT) : (29 - PAGE_SHIFT), HASH_HIGHMEM, &myrt_hash_log, &myrt_hash_mask, 0, &mytable_order ); memset(myrt_hash_table, 0, (myrt_hash_mask + 1) * sizeof(struct myrt_hash_bucket)); myrt_hash_lock_init(); myipv4_dst_ops.gc_thresh = (myrt_hash_mask + 1); myip_rt_max_size = (myrt_hash_mask + 1) * 16; init_timer( &myrt_flush_timer ); myrt_flush_timer.function = myrt_run_flush; init_timer( &myrt_periodic_timer ); myrt_periodic_timer.function = myrt_check_expire; init_timer( &myrt_secret_timer ); myrt_secret_timer.function = myrt_secret_rebuild; myrt_periodic_timer.expires = jiffies + net_random() % myip_rt_gc_interval + myip_rt_gc_interval; add_timer(&myrt_periodic_timer); myrt_secret_timer.expires = jiffies + net_random() % myip_rt_secret_interval + myip_rt_secret_interval; add_timer(&myrt_secret_timer);#ifdef CONFIG_PROC_FS { struct proc_dir_entry *myrtstat_pde = NULL; /* keep gcc happy */ if (!proc_net_fops_create("myrt_cache", S_IRUGO, &myrt_cache_seq_fops) || !(myrtstat_pde = create_proc_entry("myrt_cache", S_IRUGO, proc_net_stat))) { return -ENOMEM; } myrtstat_pde->proc_fops = &myrt_cpu_seq_fops; }#ifdef CONFIG_NET_CLS_ROUTE create_proc_read_entry("myrt_acct", 0, proc_net, myip_rt_acct_read, NULL);#endif#endif mydevinet_init(); myip_fib_init();#if 0 //left to future.#ifdef CONFIG_XFRM xfrm_init(); xfrm4_init();#endif#endif return 0;}void __exit myip_rt_exit(void){ int i; remove_proc_entry("myrt_acct", proc_net); remove_proc_entry( "myrt_cache", proc_net ); remove_proc_entry( "myrt_cache", proc_net_stat ); del_timer( &myrt_periodic_timer ); del_timer( &myrt_secret_timer ); mydevinet_exit(); myip_fib_exit(); for( i = 0; i < myrt_hash_mask + 1; i ++ ){ struct rtable *node_n = myrt_hash_table[i].chain; struct rtable *node_p = node_n; while( node_n != NULL ){ node_n = node_n->u.rt_next; printk(KERN_INFO "ip: %u.%u.%u.%u\n", NIPQUAD(node_p->rt_dst) ); kmem_cache_free( myipv4_dst_ops.kmem_cachep, node_p ); node_p = node_n; } } if( myrt_hash_table ) free_pages( (unsigned long)myrt_hash_table, mytable_order ); if( myipv4_dst_ops.kmem_cachep ) kmem_cache_destroy( myipv4_dst_ops.kmem_cachep ); if( myip_rt_acct ) free_pages( (unsigned long)myip_rt_acct, myip_rt_acct_order );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -