aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt12
-rw-r--r--include/linux/ipv6.h1
-rw-r--r--include/uapi/linux/ipv6.h1
-rw-r--r--include/uapi/linux/sysctl.h1
-rw-r--r--kernel/sysctl_binary.c1
-rw-r--r--net/ipv6/addrconf.c10
-rw-r--r--net/ipv6/ndisc.c21
7 files changed, 39 insertions, 8 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index ab42c95f9985..10e216c6e05e 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1210,6 +1210,18 @@ accept_ra_defrtr - BOOLEAN
1210 Functional default: enabled if accept_ra is enabled. 1210 Functional default: enabled if accept_ra is enabled.
1211 disabled if accept_ra is disabled. 1211 disabled if accept_ra is disabled.
1212 1212
1213accept_ra_from_local - BOOLEAN
1214 Accept RA with source-address that is found on local machine
1215 if the RA is otherwise proper and able to be accepted.
1216 Default is to NOT accept these as it may be an un-intended
1217 network loop.
1218
1219 Functional default:
1220 enabled if accept_ra_from_local is enabled
1221 on a specific interface.
1222 disabled if accept_ra_from_local is disabled
1223 on a specific interface.
1224
1213accept_ra_pinfo - BOOLEAN 1225accept_ra_pinfo - BOOLEAN
1214 Learn Prefix Information in Router Advertisement. 1226 Learn Prefix Information in Router Advertisement.
1215 1227
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index c811300b0b0c..b0f2452f1d58 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -39,6 +39,7 @@ struct ipv6_devconf {
39#endif 39#endif
40 __s32 proxy_ndp; 40 __s32 proxy_ndp;
41 __s32 accept_source_route; 41 __s32 accept_source_route;
42 __s32 accept_ra_from_local;
42#ifdef CONFIG_IPV6_OPTIMISTIC_DAD 43#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
43 __s32 optimistic_dad; 44 __s32 optimistic_dad;
44#endif 45#endif
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index 593b0e32d956..efa2666f4b8a 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -163,6 +163,7 @@ enum {
163 DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL, 163 DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL,
164 DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL, 164 DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
165 DEVCONF_SUPPRESS_FRAG_NDISC, 165 DEVCONF_SUPPRESS_FRAG_NDISC,
166 DEVCONF_ACCEPT_RA_FROM_LOCAL,
166 DEVCONF_MAX 167 DEVCONF_MAX
167}; 168};
168 169
diff --git a/include/uapi/linux/sysctl.h b/include/uapi/linux/sysctl.h
index 6d6721341f49..43aaba1cc037 100644
--- a/include/uapi/linux/sysctl.h
+++ b/include/uapi/linux/sysctl.h
@@ -568,6 +568,7 @@ enum {
568 NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22, 568 NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22,
569 NET_IPV6_PROXY_NDP=23, 569 NET_IPV6_PROXY_NDP=23,
570 NET_IPV6_ACCEPT_SOURCE_ROUTE=25, 570 NET_IPV6_ACCEPT_SOURCE_ROUTE=25,
571 NET_IPV6_ACCEPT_RA_FROM_LOCAL=26,
571 __NET_IPV6_MAX 572 __NET_IPV6_MAX
572}; 573};
573 574
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index 653cbbd9e7ad..e4ba9a5a5ccb 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -522,6 +522,7 @@ static const struct bin_table bin_net_ipv6_conf_var_table[] = {
522 { CTL_INT, NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN, "accept_ra_rt_info_max_plen" }, 522 { CTL_INT, NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN, "accept_ra_rt_info_max_plen" },
523 { CTL_INT, NET_IPV6_PROXY_NDP, "proxy_ndp" }, 523 { CTL_INT, NET_IPV6_PROXY_NDP, "proxy_ndp" },
524 { CTL_INT, NET_IPV6_ACCEPT_SOURCE_ROUTE, "accept_source_route" }, 524 { CTL_INT, NET_IPV6_ACCEPT_SOURCE_ROUTE, "accept_source_route" },
525 { CTL_INT, NET_IPV6_ACCEPT_RA_FROM_LOCAL, "accept_ra_from_local" },
525 {} 526 {}
526}; 527};
527 528
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 5667b3003af9..358edd2272ac 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -186,6 +186,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
186 .max_desync_factor = MAX_DESYNC_FACTOR, 186 .max_desync_factor = MAX_DESYNC_FACTOR,
187 .max_addresses = IPV6_MAX_ADDRESSES, 187 .max_addresses = IPV6_MAX_ADDRESSES,
188 .accept_ra_defrtr = 1, 188 .accept_ra_defrtr = 1,
189 .accept_ra_from_local = 0,
189 .accept_ra_pinfo = 1, 190 .accept_ra_pinfo = 1,
190#ifdef CONFIG_IPV6_ROUTER_PREF 191#ifdef CONFIG_IPV6_ROUTER_PREF
191 .accept_ra_rtr_pref = 1, 192 .accept_ra_rtr_pref = 1,
@@ -222,6 +223,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
222 .max_desync_factor = MAX_DESYNC_FACTOR, 223 .max_desync_factor = MAX_DESYNC_FACTOR,
223 .max_addresses = IPV6_MAX_ADDRESSES, 224 .max_addresses = IPV6_MAX_ADDRESSES,
224 .accept_ra_defrtr = 1, 225 .accept_ra_defrtr = 1,
226 .accept_ra_from_local = 0,
225 .accept_ra_pinfo = 1, 227 .accept_ra_pinfo = 1,
226#ifdef CONFIG_IPV6_ROUTER_PREF 228#ifdef CONFIG_IPV6_ROUTER_PREF
227 .accept_ra_rtr_pref = 1, 229 .accept_ra_rtr_pref = 1,
@@ -4321,6 +4323,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
4321 array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; 4323 array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
4322 array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify; 4324 array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
4323 array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc; 4325 array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
4326 array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local;
4324} 4327}
4325 4328
4326static inline size_t inet6_ifla6_size(void) 4329static inline size_t inet6_ifla6_size(void)
@@ -5168,6 +5171,13 @@ static struct addrconf_sysctl_table
5168 .proc_handler = proc_dointvec 5171 .proc_handler = proc_dointvec
5169 }, 5172 },
5170 { 5173 {
5174 .procname = "accept_ra_from_local",
5175 .data = &ipv6_devconf.accept_ra_from_local,
5176 .maxlen = sizeof(int),
5177 .mode = 0644,
5178 .proc_handler = proc_dointvec,
5179 },
5180 {
5171 /* sentinel */ 5181 /* sentinel */
5172 } 5182 }
5173 }, 5183 },
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 736c11c6d266..a845e3d2057e 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1148,11 +1148,15 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1148 goto skip_defrtr; 1148 goto skip_defrtr;
1149 } 1149 }
1150 1150
1151 if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, 1151 /* Do not accept RA with source-addr found on local machine unless
1152 NULL, 0)) { 1152 * accept_ra_from_local is set to true.
1153 */
1154 if (!(in6_dev->cnf.accept_ra_from_local ||
1155 ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
1156 NULL, 0))) {
1153 ND_PRINTK(2, info, 1157 ND_PRINTK(2, info,
1154 "RA: %s, chk_addr failed for dev: %s\n", 1158 "RA from local address detected on dev: %s: default router ignored\n",
1155 __func__, skb->dev->name); 1159 skb->dev->name);
1156 goto skip_defrtr; 1160 goto skip_defrtr;
1157 } 1161 }
1158 1162
@@ -1290,11 +1294,12 @@ skip_linkparms:
1290 } 1294 }
1291 1295
1292#ifdef CONFIG_IPV6_ROUTE_INFO 1296#ifdef CONFIG_IPV6_ROUTE_INFO
1293 if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, 1297 if (!(in6_dev->cnf.accept_ra_from_local ||
1294 NULL, 0)) { 1298 ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
1299 NULL, 0))) {
1295 ND_PRINTK(2, info, 1300 ND_PRINTK(2, info,
1296 "RA: %s, chk-addr (route info) is false for dev: %s\n", 1301 "RA from local address detected on dev: %s: router info ignored.\n",
1297 __func__, skb->dev->name); 1302 skb->dev->name);
1298 goto skip_routeinfo; 1303 goto skip_routeinfo;
1299 } 1304 }
1300 1305