Commit f9a2fb73 authored by Arun Ajith S's avatar Arun Ajith S Committed by David S. Miller
Browse files

net/ipv6: Introduce accept_unsolicited_na knob to implement router-side changes for RFC9131



Add a new neighbour cache entry in STALE state for routers on receiving
an unsolicited (gratuitous) neighbour advertisement with
target link-layer-address option specified.
This is similar to the arp_accept configuration for IPv4.
A new sysctl endpoint is created to turn on this behaviour:
/proc/sys/net/ipv6/conf/interface/accept_unsolicited_na.

Signed-off-by: default avatarArun Ajith S <aajith@arista.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0339d25a
Loading
Loading
Loading
Loading
+27 −0
Original line number Original line Diff line number Diff line
@@ -2467,6 +2467,33 @@ drop_unsolicited_na - BOOLEAN


	By default this is turned off.
	By default this is turned off.


accept_unsolicited_na - BOOLEAN
	Add a new neighbour cache entry in STALE state for routers on receiving an
	unsolicited neighbour advertisement with target link-layer address option
	specified. This is as per router-side behavior documented in RFC9131.
	This has lower precedence than drop_unsolicited_na.

	 ====   ======  ======  ==============================================
	 drop   accept  fwding                   behaviour
	 ----   ------  ------  ----------------------------------------------
	    1        X       X  Drop NA packet and don't pass up the stack
	    0        0       X  Pass NA packet up the stack, don't update NC
	    0        1       0  Pass NA packet up the stack, don't update NC
	    0        1       1  Pass NA packet up the stack, and add a STALE
	                        NC entry
	 ====   ======  ======  ==============================================

	This will optimize the return path for the initial off-link communication
	that is initiated by a directly connected host, by ensuring that
	the first-hop router which turns on this setting doesn't have to
	buffer the initial return packets to do neighbour-solicitation.
	The prerequisite is that the host is configured to send
	unsolicited neighbour advertisements on interface bringup.
	This setting should be used in conjunction with the ndisc_notify setting
	on the host to satisfy this prerequisite.

	By default this is turned off.

enhanced_dad - BOOLEAN
enhanced_dad - BOOLEAN
	Include a nonce option in the IPv6 neighbor solicitation messages used for
	Include a nonce option in the IPv6 neighbor solicitation messages used for
	duplicate address detection per RFC7527. A received DAD NS will only signal
	duplicate address detection per RFC7527. A received DAD NS will only signal
+1 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,7 @@ struct ipv6_devconf {
	__s32		suppress_frag_ndisc;
	__s32		suppress_frag_ndisc;
	__s32		accept_ra_mtu;
	__s32		accept_ra_mtu;
	__s32		drop_unsolicited_na;
	__s32		drop_unsolicited_na;
	__s32		accept_unsolicited_na;
	struct ipv6_stable_secret {
	struct ipv6_stable_secret {
		bool initialized;
		bool initialized;
		struct in6_addr secret;
		struct in6_addr secret;
+1 −0
Original line number Original line Diff line number Diff line
@@ -194,6 +194,7 @@ enum {
	DEVCONF_IOAM6_ID,
	DEVCONF_IOAM6_ID,
	DEVCONF_IOAM6_ID_WIDE,
	DEVCONF_IOAM6_ID_WIDE,
	DEVCONF_NDISC_EVICT_NOCARRIER,
	DEVCONF_NDISC_EVICT_NOCARRIER,
	DEVCONF_ACCEPT_UNSOLICITED_NA,
	DEVCONF_MAX
	DEVCONF_MAX
};
};


+10 −0
Original line number Original line Diff line number Diff line
@@ -5587,6 +5587,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
	array[DEVCONF_IOAM6_ID] = cnf->ioam6_id;
	array[DEVCONF_IOAM6_ID] = cnf->ioam6_id;
	array[DEVCONF_IOAM6_ID_WIDE] = cnf->ioam6_id_wide;
	array[DEVCONF_IOAM6_ID_WIDE] = cnf->ioam6_id_wide;
	array[DEVCONF_NDISC_EVICT_NOCARRIER] = cnf->ndisc_evict_nocarrier;
	array[DEVCONF_NDISC_EVICT_NOCARRIER] = cnf->ndisc_evict_nocarrier;
	array[DEVCONF_ACCEPT_UNSOLICITED_NA] = cnf->accept_unsolicited_na;
}
}


static inline size_t inet6_ifla6_size(void)
static inline size_t inet6_ifla6_size(void)
@@ -7037,6 +7038,15 @@ static const struct ctl_table addrconf_sysctl[] = {
		.extra1		= (void *)SYSCTL_ZERO,
		.extra1		= (void *)SYSCTL_ZERO,
		.extra2		= (void *)SYSCTL_ONE,
		.extra2		= (void *)SYSCTL_ONE,
	},
	},
	{
		.procname	= "accept_unsolicited_na",
		.data		= &ipv6_devconf.accept_unsolicited_na,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
		.extra1		= (void *)SYSCTL_ZERO,
		.extra2		= (void *)SYSCTL_ONE,
	},
	{
	{
		/* sentinel */
		/* sentinel */
	}
	}
+19 −1
Original line number Original line Diff line number Diff line
@@ -979,6 +979,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
	struct inet6_dev *idev = __in6_dev_get(dev);
	struct inet6_dev *idev = __in6_dev_get(dev);
	struct inet6_ifaddr *ifp;
	struct inet6_ifaddr *ifp;
	struct neighbour *neigh;
	struct neighbour *neigh;
	bool create_neigh;


	if (skb->len < sizeof(struct nd_msg)) {
	if (skb->len < sizeof(struct nd_msg)) {
		ND_PRINTK(2, warn, "NA: packet too short\n");
		ND_PRINTK(2, warn, "NA: packet too short\n");
@@ -999,6 +1000,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
	/* For some 802.11 wireless deployments (and possibly other networks),
	/* For some 802.11 wireless deployments (and possibly other networks),
	 * there will be a NA proxy and unsolicitd packets are attacks
	 * there will be a NA proxy and unsolicitd packets are attacks
	 * and thus should not be accepted.
	 * and thus should not be accepted.
	 * drop_unsolicited_na takes precedence over accept_unsolicited_na
	 */
	 */
	if (!msg->icmph.icmp6_solicited && idev &&
	if (!msg->icmph.icmp6_solicited && idev &&
	    idev->cnf.drop_unsolicited_na)
	    idev->cnf.drop_unsolicited_na)
@@ -1039,7 +1041,23 @@ static void ndisc_recv_na(struct sk_buff *skb)
		in6_ifa_put(ifp);
		in6_ifa_put(ifp);
		return;
		return;
	}
	}
	neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
	/* RFC 9131 updates original Neighbour Discovery RFC 4861.
	 * An unsolicited NA can now create a neighbour cache entry
	 * on routers if it has Target LL Address option.
	 *
	 * drop   accept  fwding                   behaviour
	 * ----   ------  ------  ----------------------------------------------
	 *    1        X       X  Drop NA packet and don't pass up the stack
	 *    0        0       X  Pass NA packet up the stack, don't update NC
	 *    0        1       0  Pass NA packet up the stack, don't update NC
	 *    0        1       1  Pass NA packet up the stack, and add a STALE
	 *                          NC entry
	 * Note that we don't do a (daddr == all-routers-mcast) check.
	 */
	create_neigh = !msg->icmph.icmp6_solicited && lladdr &&
		       idev && idev->cnf.forwarding &&
		       idev->cnf.accept_unsolicited_na;
	neigh = __neigh_lookup(&nd_tbl, &msg->target, dev, create_neigh);


	if (neigh) {
	if (neigh) {
		u8 old_flags = neigh->flags;
		u8 old_flags = neigh->flags;
Loading