diff options
author | Jaehee Park <jhpark1013@gmail.com> | 2022-07-13 16:40:48 -0700 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2022-07-15 18:55:50 -0700 |
commit | aaa5f515b16b6b3e137779ffb4c9558bb58c1e75 (patch) | |
tree | ed38a6a92803ee96890a6e3661450511019d5859 /net/ipv6 | |
parent | e68c5dcf0aacc48a23cedcb3ce81b8c60837f48c (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/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 2 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 29 |
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)) { |