aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt6
-rw-r--r--include/linux/inetdevice.h1
-rw-r--r--include/linux/sysctl.h1
-rw-r--r--kernel/sysctl_check.c1
-rw-r--r--net/ipv4/devinet.c1
-rw-r--r--net/ipv4/fib_frontend.c11
6 files changed, 17 insertions, 4 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 989f5538b8dd..006b39dec87d 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -731,6 +731,12 @@ accept_source_route - BOOLEAN
731 default TRUE (router) 731 default TRUE (router)
732 FALSE (host) 732 FALSE (host)
733 733
734accept_local - BOOLEAN
735 Accept packets with local source addresses. In combination with
736 suitable routing, this can be used to direct packets between two
737 local interfaces over the wire and have them accepted properly.
738 default FALSE
739
734rp_filter - INTEGER 740rp_filter - INTEGER
735 0 - No source validation. 741 0 - No source validation.
736 1 - Strict mode as defined in RFC3704 Strict Reverse Path 742 1 - Strict mode as defined in RFC3704 Strict Reverse Path
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index eecfa559bfb4..699e85c01a4d 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -83,6 +83,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
83#define IN_DEV_RPFILTER(in_dev) IN_DEV_MAXCONF((in_dev), RP_FILTER) 83#define IN_DEV_RPFILTER(in_dev) IN_DEV_MAXCONF((in_dev), RP_FILTER)
84#define IN_DEV_SOURCE_ROUTE(in_dev) IN_DEV_ANDCONF((in_dev), \ 84#define IN_DEV_SOURCE_ROUTE(in_dev) IN_DEV_ANDCONF((in_dev), \
85 ACCEPT_SOURCE_ROUTE) 85 ACCEPT_SOURCE_ROUTE)
86#define IN_DEV_ACCEPT_LOCAL(in_dev) IN_DEV_ORCONF((in_dev), ACCEPT_LOCAL)
86#define IN_DEV_BOOTP_RELAY(in_dev) IN_DEV_ANDCONF((in_dev), BOOTP_RELAY) 87#define IN_DEV_BOOTP_RELAY(in_dev) IN_DEV_ANDCONF((in_dev), BOOTP_RELAY)
87 88
88#define IN_DEV_LOG_MARTIANS(in_dev) IN_DEV_ORCONF((in_dev), LOG_MARTIANS) 89#define IN_DEV_LOG_MARTIANS(in_dev) IN_DEV_ORCONF((in_dev), LOG_MARTIANS)
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 1e4743ee6831..9f047d73a216 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -490,6 +490,7 @@ enum
490 NET_IPV4_CONF_PROMOTE_SECONDARIES=20, 490 NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
491 NET_IPV4_CONF_ARP_ACCEPT=21, 491 NET_IPV4_CONF_ARP_ACCEPT=21,
492 NET_IPV4_CONF_ARP_NOTIFY=22, 492 NET_IPV4_CONF_ARP_NOTIFY=22,
493 NET_IPV4_CONF_ACCEPT_LOCAL=23,
493 __NET_IPV4_CONF_MAX 494 __NET_IPV4_CONF_MAX
494}; 495};
495 496
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index b6e7aaea4604..f1d676e4b368 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -220,6 +220,7 @@ static const struct trans_ctl_table trans_net_ipv4_conf_vars_table[] = {
220 { NET_IPV4_CONF_PROMOTE_SECONDARIES, "promote_secondaries" }, 220 { NET_IPV4_CONF_PROMOTE_SECONDARIES, "promote_secondaries" },
221 { NET_IPV4_CONF_ARP_ACCEPT, "arp_accept" }, 221 { NET_IPV4_CONF_ARP_ACCEPT, "arp_accept" },
222 { NET_IPV4_CONF_ARP_NOTIFY, "arp_notify" }, 222 { NET_IPV4_CONF_ARP_NOTIFY, "arp_notify" },
223 { NET_IPV4_CONF_ACCEPT_LOCAL, "accept_local" },
223 {} 224 {}
224}; 225};
225 226
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index c100709d6ddf..e3126612fcbb 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1468,6 +1468,7 @@ static struct devinet_sysctl_table {
1468 DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"), 1468 DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
1469 DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE, 1469 DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
1470 "accept_source_route"), 1470 "accept_source_route"),
1471 DEVINET_SYSCTL_RW_ENTRY(ACCEPT_LOCAL, "accept_local"),
1471 DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"), 1472 DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
1472 DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"), 1473 DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
1473 DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"), 1474 DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 3b373a8b0473..3323168ee52d 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -241,16 +241,17 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
241 .iif = oif }; 241 .iif = oif };
242 242
243 struct fib_result res; 243 struct fib_result res;
244 int no_addr, rpf; 244 int no_addr, rpf, accept_local;
245 int ret; 245 int ret;
246 struct net *net; 246 struct net *net;
247 247
248 no_addr = rpf = 0; 248 no_addr = rpf = accept_local = 0;
249 rcu_read_lock(); 249 rcu_read_lock();
250 in_dev = __in_dev_get_rcu(dev); 250 in_dev = __in_dev_get_rcu(dev);
251 if (in_dev) { 251 if (in_dev) {
252 no_addr = in_dev->ifa_list == NULL; 252 no_addr = in_dev->ifa_list == NULL;
253 rpf = IN_DEV_RPFILTER(in_dev); 253 rpf = IN_DEV_RPFILTER(in_dev);
254 accept_local = IN_DEV_ACCEPT_LOCAL(in_dev);
254 } 255 }
255 rcu_read_unlock(); 256 rcu_read_unlock();
256 257
@@ -260,8 +261,10 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
260 net = dev_net(dev); 261 net = dev_net(dev);
261 if (fib_lookup(net, &fl, &res)) 262 if (fib_lookup(net, &fl, &res))
262 goto last_resort; 263 goto last_resort;
263 if (res.type != RTN_UNICAST) 264 if (res.type != RTN_UNICAST) {
264 goto e_inval_res; 265 if (res.type != RTN_LOCAL || !accept_local)
266 goto e_inval_res;
267 }
265 *spec_dst = FIB_RES_PREFSRC(res); 268 *spec_dst = FIB_RES_PREFSRC(res);
266 fib_combine_itag(itag, &res); 269 fib_combine_itag(itag, &res);
267#ifdef CONFIG_IP_ROUTE_MULTIPATH 270#ifdef CONFIG_IP_ROUTE_MULTIPATH