aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt5
-rw-r--r--include/linux/inetdevice.h2
-rw-r--r--net/ipv4/arp.c3
-rw-r--r--net/ipv4/devinet.c5
-rw-r--r--net/ipv4/route.c30
5 files changed, 34 insertions, 11 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 6f896b94abdc..99d0e0504d6e 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -862,6 +862,11 @@ accept_local - BOOLEAN
862 local interfaces over the wire and have them accepted properly. 862 local interfaces over the wire and have them accepted properly.
863 default FALSE 863 default FALSE
864 864
865route_localnet - BOOLEAN
866 Do not consider loopback addresses as martian source or destination
867 while routing. This enables the use of 127/8 for local routing purposes.
868 default FALSE
869
865rp_filter - INTEGER 870rp_filter - INTEGER
866 0 - No source validation. 871 0 - No source validation.
867 1 - Strict mode as defined in RFC3704 Strict Reverse Path 872 1 - Strict mode as defined in RFC3704 Strict Reverse Path
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 597f4a9f3240..67f9ddacb70c 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -38,6 +38,7 @@ enum
38 IPV4_DEVCONF_ACCEPT_LOCAL, 38 IPV4_DEVCONF_ACCEPT_LOCAL,
39 IPV4_DEVCONF_SRC_VMARK, 39 IPV4_DEVCONF_SRC_VMARK,
40 IPV4_DEVCONF_PROXY_ARP_PVLAN, 40 IPV4_DEVCONF_PROXY_ARP_PVLAN,
41 IPV4_DEVCONF_ROUTE_LOCALNET,
41 __IPV4_DEVCONF_MAX 42 __IPV4_DEVCONF_MAX
42}; 43};
43 44
@@ -131,6 +132,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
131#define IN_DEV_PROMOTE_SECONDARIES(in_dev) \ 132#define IN_DEV_PROMOTE_SECONDARIES(in_dev) \
132 IN_DEV_ORCONF((in_dev), \ 133 IN_DEV_ORCONF((in_dev), \
133 PROMOTE_SECONDARIES) 134 PROMOTE_SECONDARIES)
135#define IN_DEV_ROUTE_LOCALNET(in_dev) IN_DEV_ORCONF(in_dev, ROUTE_LOCALNET)
134 136
135#define IN_DEV_RX_REDIRECTS(in_dev) \ 137#define IN_DEV_RX_REDIRECTS(in_dev) \
136 ((IN_DEV_FORWARD(in_dev) && \ 138 ((IN_DEV_FORWARD(in_dev) && \
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index cda37be02f8d..2e560f0c757d 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -790,7 +790,8 @@ static int arp_process(struct sk_buff *skb)
790 * Check for bad requests for 127.x.x.x and requests for multicast 790 * Check for bad requests for 127.x.x.x and requests for multicast
791 * addresses. If this is one such, delete it. 791 * addresses. If this is one such, delete it.
792 */ 792 */
793 if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) 793 if (ipv4_is_multicast(tip) ||
794 (!IN_DEV_ROUTE_LOCALNET(in_dev) && ipv4_is_loopback(tip)))
794 goto out; 795 goto out;
795 796
796/* 797/*
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 10e15a144e95..44bf82e3aef7 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1500,7 +1500,8 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
1500 1500
1501 if (cnf == net->ipv4.devconf_dflt) 1501 if (cnf == net->ipv4.devconf_dflt)
1502 devinet_copy_dflt_conf(net, i); 1502 devinet_copy_dflt_conf(net, i);
1503 if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1) 1503 if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1 ||
1504 i == IPV4_DEVCONF_ROUTE_LOCALNET - 1)
1504 if ((new_value == 0) && (old_value != 0)) 1505 if ((new_value == 0) && (old_value != 0))
1505 rt_cache_flush(net, 0); 1506 rt_cache_flush(net, 0);
1506 } 1507 }
@@ -1617,6 +1618,8 @@ static struct devinet_sysctl_table {
1617 "force_igmp_version"), 1618 "force_igmp_version"),
1618 DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES, 1619 DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES,
1619 "promote_secondaries"), 1620 "promote_secondaries"),
1621 DEVINET_SYSCTL_FLUSHING_ENTRY(ROUTE_LOCALNET,
1622 "route_localnet"),
1620 }, 1623 },
1621}; 1624};
1622 1625
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 842510d50453..655506af47ca 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1960,9 +1960,13 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1960 return -EINVAL; 1960 return -EINVAL;
1961 1961
1962 if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) || 1962 if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) ||
1963 ipv4_is_loopback(saddr) || skb->protocol != htons(ETH_P_IP)) 1963 skb->protocol != htons(ETH_P_IP))
1964 goto e_inval; 1964 goto e_inval;
1965 1965
1966 if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev)))
1967 if (ipv4_is_loopback(saddr))
1968 goto e_inval;
1969
1966 if (ipv4_is_zeronet(saddr)) { 1970 if (ipv4_is_zeronet(saddr)) {
1967 if (!ipv4_is_local_multicast(daddr)) 1971 if (!ipv4_is_local_multicast(daddr))
1968 goto e_inval; 1972 goto e_inval;
@@ -2203,8 +2207,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
2203 by fib_lookup. 2207 by fib_lookup.
2204 */ 2208 */
2205 2209
2206 if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) || 2210 if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr))
2207 ipv4_is_loopback(saddr))
2208 goto martian_source; 2211 goto martian_source;
2209 2212
2210 if (ipv4_is_lbcast(daddr) || (saddr == 0 && daddr == 0)) 2213 if (ipv4_is_lbcast(daddr) || (saddr == 0 && daddr == 0))
@@ -2216,9 +2219,17 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
2216 if (ipv4_is_zeronet(saddr)) 2219 if (ipv4_is_zeronet(saddr))
2217 goto martian_source; 2220 goto martian_source;
2218 2221
2219 if (ipv4_is_zeronet(daddr) || ipv4_is_loopback(daddr)) 2222 if (ipv4_is_zeronet(daddr))
2220 goto martian_destination; 2223 goto martian_destination;
2221 2224
2225 if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev))) {
2226 if (ipv4_is_loopback(daddr))
2227 goto martian_destination;
2228
2229 if (ipv4_is_loopback(saddr))
2230 goto martian_source;
2231 }
2232
2222 /* 2233 /*
2223 * Now we are ready to route packet. 2234 * Now we are ready to route packet.
2224 */ 2235 */
@@ -2457,9 +2468,14 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
2457 u16 type = res->type; 2468 u16 type = res->type;
2458 struct rtable *rth; 2469 struct rtable *rth;
2459 2470
2460 if (ipv4_is_loopback(fl4->saddr) && !(dev_out->flags & IFF_LOOPBACK)) 2471 in_dev = __in_dev_get_rcu(dev_out);
2472 if (!in_dev)
2461 return ERR_PTR(-EINVAL); 2473 return ERR_PTR(-EINVAL);
2462 2474
2475 if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev)))
2476 if (ipv4_is_loopback(fl4->saddr) && !(dev_out->flags & IFF_LOOPBACK))
2477 return ERR_PTR(-EINVAL);
2478
2463 if (ipv4_is_lbcast(fl4->daddr)) 2479 if (ipv4_is_lbcast(fl4->daddr))
2464 type = RTN_BROADCAST; 2480 type = RTN_BROADCAST;
2465 else if (ipv4_is_multicast(fl4->daddr)) 2481 else if (ipv4_is_multicast(fl4->daddr))
@@ -2470,10 +2486,6 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
2470 if (dev_out->flags & IFF_LOOPBACK) 2486 if (dev_out->flags & IFF_LOOPBACK)
2471 flags |= RTCF_LOCAL; 2487 flags |= RTCF_LOCAL;
2472 2488
2473 in_dev = __in_dev_get_rcu(dev_out);
2474 if (!in_dev)
2475 return ERR_PTR(-EINVAL);
2476
2477 if (type == RTN_BROADCAST) { 2489 if (type == RTN_BROADCAST) {
2478 flags |= RTCF_BROADCAST | RTCF_LOCAL; 2490 flags |= RTCF_BROADCAST | RTCF_LOCAL;
2479 fi = NULL; 2491 fi = NULL;