diff options
author | Thomas Graf <tgraf@suug.ch> | 2012-06-11 20:44:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-06-12 18:25:46 -0400 |
commit | d0daebc3d622f95db181601cb0c4a0781f74f758 (patch) | |
tree | cbce3159c160d49675dba0d720d186be7f0d79d3 /net/ipv4/route.c | |
parent | 0440507bbc44149e63bbfb9df730ba3820371904 (diff) |
ipv4: Add interface option to enable routing of 127.0.0.0/8
Routing of 127/8 is tradtionally forbidden, we consider
packets from that address block martian when routing and do
not process corresponding ARP requests.
This is a sane default but renders a huge address space
practically unuseable.
The RFC states that no address within the 127/8 block should
ever appear on any network anywhere but it does not forbid
the use of such addresses outside of the loopback device in
particular. For example to address a pool of virtual guests
behind a load balancer.
This patch adds a new interface option 'route_localnet'
enabling routing of the 127/8 address block and processing
of ARP requests on a specific interface.
Note that for the feature to work, the default local route
covering 127/8 dev lo needs to be removed.
Example:
$ sysctl -w net.ipv4.conf.eth0.route_localnet=1
$ ip route del 127.0.0.0/8 dev lo table local
$ ip addr add 127.1.0.1/16 dev eth0
$ ip route flush cache
V2: Fix invalid check to auto flush cache (thanks davem)
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r-- | net/ipv4/route.c | 30 |
1 files changed, 21 insertions, 9 deletions
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; |