summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJaehee Park <jhpark1013@gmail.com>2022-07-13 16:40:48 -0700
committerJakub Kicinski <kuba@kernel.org>2022-07-15 18:55:50 -0700
commitaaa5f515b16b6b3e137779ffb4c9558bb58c1e75 (patch)
treeed38a6a92803ee96890a6e3661450511019d5859 /net
parente68c5dcf0aacc48a23cedcb3ce81b8c60837f48c (diff)
net: ipv6: new accept_untracked_na option to accept na only if in-network
This patch adds a third knob, '2', which extends the accept_untracked_na option to learn a neighbor only if the src ip is in the same subnet as an address configured on the interface that received the neighbor advertisement. This is similar to the arp_accept configuration for ipv4. Signed-off-by: Jaehee Park <jhpark1013@gmail.com> Suggested-by: Roopa Prabhu <roopa@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/ndisc.c29
2 files changed, 25 insertions, 6 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 88becb037eb6..6ed807b6c647 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -7042,7 +7042,7 @@ static const struct ctl_table addrconf_sysctl[] = {
.data = &ipv6_devconf.accept_untracked_na,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec_minmax,
+ .proc_handler = proc_dointvec,
.extra1 = (void *)SYSCTL_ZERO,
.extra2 = (void *)SYSCTL_ONE,
},
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index cd84cbdac0a2..98453693e400 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -967,6 +967,25 @@ out:
in6_dev_put(idev);
}
+static int accept_untracked_na(struct net_device *dev, struct in6_addr *saddr)
+{
+ struct inet6_dev *idev = __in6_dev_get(dev);
+
+ switch (idev->cnf.accept_untracked_na) {
+ case 0: /* Don't accept untracked na (absent in neighbor cache) */
+ return 0;
+ case 1: /* Create new entries from na if currently untracked */
+ return 1;
+ case 2: /* Create new entries from untracked na only if saddr is in the
+ * same subnet as an address configured on the interface that
+ * received the na
+ */
+ return !!ipv6_chk_prefix(saddr, dev);
+ default:
+ return 0;
+ }
+}
+
static void ndisc_recv_na(struct sk_buff *skb)
{
struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
@@ -1061,11 +1080,11 @@ static void ndisc_recv_na(struct sk_buff *skb)
* Note that we don't do a (daddr == all-routers-mcast) check.
*/
new_state = msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE;
- if (!neigh && lladdr &&
- idev && idev->cnf.forwarding &&
- idev->cnf.accept_untracked_na) {
- neigh = neigh_create(&nd_tbl, &msg->target, dev);
- new_state = NUD_STALE;
+ if (!neigh && lladdr && idev && idev->cnf.forwarding) {
+ if (accept_untracked_na(dev, saddr)) {
+ neigh = neigh_create(&nd_tbl, &msg->target, dev);
+ new_state = NUD_STALE;
+ }
}
if (neigh && !IS_ERR(neigh)) {