--- linux/include/net/ip_fib.h.orig Wed Feb 23 16:54:27 2000 +++ linux/include/net/ip_fib.h Wed Mar 15 13:46:22 2000 @@ -200,7 +200,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 device *dev, u32 *spec_dst, u32 *itag); + struct 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 */ --- linux/net/ipv4/fib_frontend.c.orig Wed Feb 23 16:54:27 2000 +++ linux/net/ipv4/fib_frontend.c Wed Mar 15 14:44:45 2000 @@ -189,7 +189,7 @@ */ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, - struct device *dev, u32 *spec_dst, u32 *itag) + struct device *dev, u32 *spec_dst, u32 *itag, int our) { struct in_device *in_dev = dev->ip_ptr; struct rt_key key; @@ -206,7 +206,8 @@ return -EINVAL; if (fib_lookup(&key, &res)) goto last_resort; - if (res.type != RTN_UNICAST) + if ((res.type != RTN_UNICAST) && + ((res.type != RTN_LOCAL) || our)) return -EINVAL; *spec_dst = FIB_RES_PREFSRC(res); if (itag) @@ -216,13 +217,20 @@ #else if (FIB_RES_DEV(res) == dev) #endif + { + if (res.type == RTN_LOCAL) { + *itag = 0; + return -EINVAL; + } return FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; + } if (in_dev->ifa_list == NULL) goto last_resort; if (IN_DEV_RPFILTER(in_dev)) return -EINVAL; key.oif = dev->ifindex; + if (res.type == RTN_LOCAL) key.iif = loopback_dev.ifindex; if (fib_lookup(&key, &res) == 0 && res.type == RTN_UNICAST) { *spec_dst = FIB_RES_PREFSRC(res); return FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; --- linux/net/ipv4/route.c.orig Wed Feb 23 17:00:07 2000 +++ linux/net/ipv4/route.c Wed Mar 15 13:07:28 2000 @@ -1037,7 +1037,7 @@ if (!LOCAL_MCAST(daddr)) return -EINVAL; spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); - } else if (fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag) < 0) + } else if (fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag, our) < 0) return -EINVAL; rth = dst_alloc(sizeof(struct rtable), &ipv4_dst_ops); @@ -1181,7 +1181,7 @@ if (res.type == RTN_LOCAL) { 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) @@ -1206,7 +1206,7 @@ return -EINVAL; } - err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(res), dev, &spec_dst, &itag); + err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(res), dev, &spec_dst, &itag, 0); if (err < 0) goto martian_source; @@ -1279,7 +1279,7 @@ if (ZERONET(saddr)) { spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); } else { - err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag); + err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag, 1); if (err < 0) goto martian_source; if (err)