static void rt_redirect_1(__u32 dst, __u32 gw, struct device *dev) { struct rtable *rt; unsigned long hash = ip_rt_hash_code(dst); if (gw == dev->pa_addr) return; if (dev != get_gw_dev(gw)) return; rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC); if (rt == NULL) return; memset(rt, 0, sizeof(struct rtable)); rt->rt_flags = RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY | RTF_UP; rt->rt_dst = dst; rt->rt_dev = dev; rt->rt_gateway = gw; rt->rt_src = dev->pa_addr; rt->rt_mtu = dev->mtu; #ifdef CONFIG_NO_PATH_MTU_DISCOVERY if (dev->mtu > 576) rt->rt_mtu = 576; #endif rt->rt_lastuse = jiffies; rt->rt_refcnt = 1; rt_cache_add(hash, rt); ip_rt_put(rt); return; }
void ip_rt_add(short flags, unsigned long dst, unsigned long mask, unsigned long gw, struct net_device *dev, \ unsigned short mtu, unsigned long window) { struct rtable *rt,*r,*prev; struct rtable **rtp; unsigned long rtflags; // is dst is host address if(flags & RTF_HOST) mask = 0xffffffff; // network address else if(!mask) { // if(!((dst ^ dev->pa_mask) ^ dev->pa_addr)) if(!((dst ^ dev->pa_addr ) & dev->pa_mask )) { mask = dev->pa_mask; flags &= ~RTF_GATEWAY; } else mask = guess_mask(dst,dev); dst &= mask; } if(gw == dev->pa_addr) { flags &= ~RTF_GATEWAY; } if(flags & RTF_GATEWAY) { if(dev != get_gw_dev(gw)) return; flags |= RTF_GATEWAY; } else gw = 0; // rt = (struct rtable *)kmalloc(sizeof(struct rtable),GFP_ATOMIC); if(rt == NULL) return; memset((char *)rt, 0, sizeof(struct rtable)); rt->rt_flags = flags | RTF_UP; rt->rt_dst = dst; rt->rt_dev = dev; rt->rt_gateway = gw; rt->rt_mask = mask; // rt->rt_mss = dev->mtu - HEADER_SIZE; rt->rt_window = 0; if(rt->rt_flags & RTF_MSS) rt->rt_mss = mtu; if(rt->rt_flags & RTF_WINDOW) rt->rt_window = window; save_flags(rtflags); cli(); rtp = &rt_base; while((r = *rtp) != NULL) { if((r->rt_dst != dst) || r->rt_mask != mask) { rtp = &r->rt_next; } else *rtp = r->rt_next; // kfree_s(r,sizeof(struct rtable)); } rtp = &rt_base; while((r = *rtp) != NULL) { if((r->rt_mask & mask) != mask) break; rtp = &r->rt_next; prev = r; } rt->rt_next = r; prev->rt_next = rt; // *rtp = rt; // if((rt->rt_dev->flags & IFF_LOOPBACK) && !rt_loopback) // rt_loopback = rt; restore_flags(rtflags); return; }