Change 4000258 by mbligh@mbligh-src1 on 2006/09/28 13:32:25 NOTE: The routing cache has to be cleared after enabling/disabling this tunable for it to take effect. --- a/2.6.18/include/linux/sysctl.h +++ b/2.6.18/include/linux/sysctl.h @@ -462,6 +462,7 @@ enum { NET_IPV4_ROUTE_MIN_ADVMSS=17, NET_IPV4_ROUTE_SECRET_INTERVAL=18, NET_IPV4_ROUTE_GC_MIN_INTERVAL_MS=19, + NET_IPV4_ROUTE_NO_LOCAL_LOOPBACK=GOOGLE_SYSCTL(1), }; enum --- a/2.6.18/include/net/ip_fib.h +++ b/2.6.18/include/net/ip_fib.h @@ -192,6 +192,13 @@ static inline int fib_lookup(const struc return 0; } +static inline int fib_lookup_nolocal(const struct flowi *flp, struct fib_result *res) +{ + if (ip_fib_main_table->tb_lookup(ip_fib_main_table, flp, res)) + return -ENETUNREACH; + return 0; +} + static inline void fib_select_default(const struct flowi *flp, struct fib_result *res) { if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) --- a/2.6.18/net/ipv4/route.c +++ b/2.6.18/net/ipv4/route.c @@ -132,6 +132,7 @@ static int ip_rt_mtu_expires = 10 * 60 static int ip_rt_min_pmtu = 512 + 20 + 20; static int ip_rt_min_advmss = 256; static int ip_rt_secret_interval = 10 * 60 * HZ; +int ip_rt_no_local_loopback = 0; static unsigned long rt_deadline; #define RTprint(a...) printk(KERN_DEBUG a) @@ -1968,7 +1969,7 @@ static int ip_route_input_slow(struct sk result = fib_validate_source(saddr, daddr, tos, loopback_dev.ifindex, dev, &spec_dst, &itag); - if (result < 0) + if (result < 0 && (!ip_rt_no_local_loopback)) goto martian_source; if (result) flags |= RTCF_DIRECTSRC; @@ -2484,7 +2485,8 @@ static int ip_route_output_slow(struct r goto make_route; } - if (fib_lookup(&fl, &res)) { + if (ip_rt_no_local_loopback?fib_lookup_nolocal(&fl, &res): + fib_lookup(&fl, &res)) { res.fi = NULL; if (oldflp->oif) { /* Apparently, routing tables are wrong. Assume, @@ -3057,6 +3059,14 @@ ctl_table ipv4_route_table[] = { .proc_handler = &proc_dointvec_jiffies, .strategy = &sysctl_jiffies, }, + { + .ctl_name = NET_IPV4_ROUTE_NO_LOCAL_LOOPBACK, + .procname = "no_local_loopback", + .data = &ip_rt_no_local_loopback, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = 0 } }; #endif --- a/2.6.18/net/ipv4/tcp_input.c +++ b/2.6.18/net/ipv4/tcp_input.c @@ -94,6 +94,8 @@ int sysctl_tcp_nometrics_save; int sysctl_tcp_moderate_rcvbuf = 1; int sysctl_tcp_abc; +extern int ip_rt_no_local_loopback; + #define FLAG_DATA 0x01 /* Incoming frame contained data. */ #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */ #define FLAG_DATA_ACKED 0x04 /* This ACK acknowledged new data. */ @@ -2561,7 +2563,7 @@ static int tcp_ack(struct sock *sk, stru sk->sk_err_soft = 0; /* we have just done some useful work. Kick the watchdog. */ - if ((inet->rcv_saddr != inet->daddr && + if (((inet->rcv_saddr != inet->daddr || ip_rt_no_local_loopback ) && (ntohl(inet->rcv_saddr) & 0xff000000) != 0x7f000000 && (ntohl(inet->daddr) & 0xff000000) != 0x7f000000)|| (skb->dev && !(skb->dev->flags & IFF_LOOPBACK))) {