--- v2.4.5/linux/include/net/ip_fib.h~ Sat Jun 2 09:41:52 2001 +++ linux/include/net/ip_fib.h Sat Jun 2 11:10:25 2001 @@ -203,7 +203,7 @@ extern int inet_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); extern int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb); extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, - struct net_device *dev, u32 *spec_dst, u32 *itag); + struct net_device *dev, u32 *spec_dst, u32 *itag, int our); extern void fib_select_multipath(const struct rt_key *key, struct fib_result *res); /* Exported by fib_semantics.c */ --- v2.4.5/linux/net/ipv4/fib_frontend.c~ Sat Jun 2 08:59:38 2001 +++ linux/net/ipv4/fib_frontend.c Sat Jun 2 11:10:25 2001 @@ -204,7 +204,8 @@ */ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, - struct net_device *dev, u32 *spec_dst, u32 *itag) + struct net_device *dev, u32 *spec_dst, u32 *itag, + int our) { struct in_device *in_dev; struct rt_key key; @@ -233,7 +234,8 @@ if (fib_lookup(&key, &res)) goto last_resort; - if (res.type != RTN_UNICAST) + if ((res.type != RTN_UNICAST) && + ((res.type != RTN_LOCAL) || our)) goto e_inval_res; *spec_dst = FIB_RES_PREFSRC(res); if (itag) @@ -244,6 +246,10 @@ if (FIB_RES_DEV(res) == dev) #endif { + if (res.type == RTN_LOCAL) { + *itag = 0; + goto e_inval_res; + } ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; fib_res_put(&res); return ret; @@ -254,6 +260,7 @@ if (rpf) goto e_inval; key.oif = dev->ifindex; + if (res.type == RTN_LOCAL) key.iif = loopback_dev.ifindex; ret = 0; if (fib_lookup(&key, &res) == 0) { --- v2.4.5/linux/net/ipv4/route.c~ Sat Jun 2 08:59:39 2001 +++ linux/net/ipv4/route.c Sat Jun 2 11:15:31 2001 @@ -1206,7 +1206,7 @@ goto e_inval; spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); } else if (fib_validate_source(saddr, 0, tos, 0, - dev, &spec_dst, &itag) < 0) + dev, &spec_dst, &itag, our) < 0) goto e_inval; rth = dst_alloc(&ipv4_dst_ops); @@ -1367,7 +1367,7 @@ int result; result = fib_validate_source(saddr, daddr, tos, loopback_dev.ifindex, - dev, &spec_dst, &itag); + dev, &spec_dst, &itag, 1); if (result < 0) goto martian_source; if (result) @@ -1394,7 +1394,7 @@ } err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(res), dev, - &spec_dst, &itag); + &spec_dst, &itag, 0); if (err < 0) goto martian_source; @@ -1478,7 +1478,7 @@ spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); else { err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, - &itag); + &itag, 1); if (err < 0) goto martian_source; if (err)