git: 8036234c72c9 - main - netinet6: fix SIOCSPFXFLUSH_IN6 by skipping manually-configured prefixes

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Wed, 24 Aug 2022 13:59:22 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=8036234c72c9361711e867cc1a0c6a7fe0babd84

commit 8036234c72c9361711e867cc1a0c6a7fe0babd84
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2022-08-23 16:19:50 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2022-08-24 13:59:13 +0000

    netinet6: fix SIOCSPFXFLUSH_IN6 by skipping manually-configured prefixes
    
    Summary:
    Currently netinet6/ code allocates IPv6 prefixes (nd_prefix) for
     both manually-assigned addresses and advertised prefixes. As a result,
     prefixes from manually-assigned prefixes can be seen in `ndp -p` list
     and be cleared via `ndp -P`. The latter relies on the SIOCSPFXFLUSH_IN6
     ioctl to clear to prefix list.
    The original intent of the SIOCSPFXFLUSH_IN6 was to clear prefixes
     originated from the advertising routers:
    
    ```
    1998-09-02  JINMEI, Tatuya  <jinmei@isl.rdc.toshiba.co.jp>
            * nd6.c (nd6_ioctl): added 2 new ioctls; SIOCSRTRFLUSH_IN6 and
            SIOCSPFXFLUSH_IN6. The former is to flush all default routers
            in the default router list, and the latter is to flush all the
            prefixes and the addresses derived from them in the prefix list.
    ```
    
    Restore the intent by marking prefixes derived from the RA messages
    with newly-added ndpr_flags.ra_derived flag and skip prefixes not marked
     with such flag during deletion and listing.
    
    Differential Revision: https://reviews.freebsd.org/D36312
    MFC after:      2 weeks
---
 sys/netinet6/in6_var.h | 4 +++-
 sys/netinet6/nd6.c     | 7 ++++---
 sys/netinet6/nd6.h     | 1 +
 sys/netinet6/nd6_rtr.c | 1 +
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index 92e94e730c33..6af0e54ccb75 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -326,7 +326,8 @@ struct in6_prflags {
 	struct prf_ra {
 		u_char onlink : 1;
 		u_char autonomous : 1;
-		u_char reserved : 6;
+		u_char ra_derived: 1;
+		u_char reserved : 5;
 	} prf_ra;
 	u_char prf_reserved1;
 	u_short prf_reserved2;
@@ -357,6 +358,7 @@ struct  in6_prefixreq {
 
 #define ipr_raf_onlink		ipr_flags.prf_ra.onlink
 #define ipr_raf_auto		ipr_flags.prf_ra.autonomous
+#define ipr_raf_ra_derived	ipr_flags.prf_ra.ra_derived
 
 #define ipr_statef_onlink	ipr_flags.prf_state.onlink
 
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 516906fda5cc..0ab629c7fcd0 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1786,9 +1786,8 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
 
 		ND6_WLOCK();
 		LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, next) {
-			if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
-				continue; /* XXX */
-			nd6_prefix_unlink(pr, &prl);
+			if (pr->ndpr_raf_ra_derived)
+				nd6_prefix_unlink(pr, &prl);
 		}
 		ND6_WUNLOCK();
 
@@ -2662,6 +2661,8 @@ nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS)
 
 	ND6_RLOCK();
 	LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
+		if (!pr->ndpr_raf_ra_derived)
+			continue;
 		p.prefix = pr->ndpr_prefix;
 		if (sa6_recoverscope(&p.prefix)) {
 			log(LOG_ERR, "scope error in prefix list (%s)\n",
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 3f9f8219b018..d653a432dbe4 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -243,6 +243,7 @@ struct nd_prefix {
 #define ndpr_raf		ndpr_flags
 #define ndpr_raf_onlink		ndpr_flags.onlink
 #define ndpr_raf_auto		ndpr_flags.autonomous
+#define ndpr_raf_ra_derived	ndpr_flags.ra_derived
 #define ndpr_raf_router		ndpr_flags.router
 
 struct nd_pfxrouter {
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 4502428e1690..9b33d0ea9b24 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -517,6 +517,7 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
 			    ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
 			pr.ndpr_raf_auto = (pi->nd_opt_pi_flags_reserved &
 			    ND_OPT_PI_FLAG_AUTO) ? 1 : 0;
+			pr.ndpr_raf_ra_derived = 1;
 			pr.ndpr_plen = pi->nd_opt_pi_prefix_len;
 			pr.ndpr_vltime = ntohl(pi->nd_opt_pi_valid_time);
 			pr.ndpr_pltime = ntohl(pi->nd_opt_pi_preferred_time);