Module Name:    src
Committed By:   martin
Date:           Wed Apr 15 14:58:41 UTC 2020

Modified Files:
        src/sys/netinet6 [netbsd-7-1]: nd6_rtr.c

Log Message:
Pull up following revision(s) (requested by kim in ticket #1727):

        sys/netinet6/nd6_rtr.c: revision 1.148 (via patch)

Fix default route selection

The primary issue was that in revision 1.79 a check was added in the
nd6_defrouter_select() search loop to ignore the entry if RA processing
is enabled on its interface.  In practice this results in all entries
being ignored.

This fix reverses the condition, so that an entry is ignored when RA
processing is NOT enabled on its interface.  Further, the entry is
only ignored for being selected as the default router.  The currently
installed router must be identified regardless of the (current) status
of its interface, so that we can delete the route before installing a
new one.

I also added error logging when adding or deleting a route fails. This
should help the administrator (or kernel developer) in noticing possible
problems.

Finally, if deleting a route fails, the corresponding default route
entry no longer has its "installed" flag cleared, so that deletion will
be retried.  At a minimum, this will cause repeated messages about the
failed deletion as opposed to only getting repeated messages about the
installation of a new default route failing.

Fixes PR kern/55091 and also PR bin/54997 as far as the behaviour
observed with ndp(8).


To generate a diff of this commit:
cvs rdiff -u -r1.93.2.3 -r1.93.2.3.6.1 src/sys/netinet6/nd6_rtr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet6/nd6_rtr.c
diff -u src/sys/netinet6/nd6_rtr.c:1.93.2.3 src/sys/netinet6/nd6_rtr.c:1.93.2.3.6.1
--- src/sys/netinet6/nd6_rtr.c:1.93.2.3	Sat May  2 18:23:25 2015
+++ src/sys/netinet6/nd6_rtr.c	Wed Apr 15 14:58:41 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6_rtr.c,v 1.93.2.3 2015/05/02 18:23:25 martin Exp $	*/
+/*	$NetBSD: nd6_rtr.c,v 1.93.2.3.6.1 2020/04/15 14:58:41 martin Exp $	*/
 /*	$KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.93.2.3 2015/05/02 18:23:25 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.93.2.3.6.1 2020/04/15 14:58:41 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -472,6 +472,10 @@ defrouter_addreq(struct nd_defrouter *ne
 	}
 	if (error == 0)
 		new->installed = 1;
+	else
+		log(LOG_ERR, "defrouter_addreq: "
+		    "error %d adding default router %s on %s\n",
+		    error, ip6_sprintf(&new->rtaddr), new->ifp->if_xname);
 	splx(s);
 	return;
 }
@@ -559,6 +563,7 @@ defrouter_delreq(struct nd_defrouter *dr
 		struct sockaddr sa;
 	} def, mask, gw;
 	struct rtentry *oldrt = NULL;
+	int error;
 
 #ifdef DIAGNOSTIC
 	if (dr == NULL)
@@ -577,7 +582,7 @@ defrouter_delreq(struct nd_defrouter *dr
 	gw.sin6.sin6_scope_id = 0;	/* XXX */
 #endif
 
-	rtrequest(RTM_DELETE, &def.sa, &gw.sa, &mask.sa, RTF_GATEWAY, &oldrt);
+	error = rtrequest(RTM_DELETE, &def.sa, &gw.sa, &mask.sa, RTF_GATEWAY, &oldrt);
 	if (oldrt) {
 		nd6_rtmsg(RTM_DELETE, oldrt);
 		if (oldrt->rt_refcnt <= 0) {
@@ -591,7 +596,12 @@ defrouter_delreq(struct nd_defrouter *dr
 		}
 	}
 
-	dr->installed = 0;
+	if (error == 0)
+		dr->installed = 0;
+	else
+		log(LOG_ERR, "defrouter_delreq: "
+		    "error %d deleting default router %s on %s\n",
+		    error, ip6_sprintf(&dr->rtaddr), dr->ifp->if_xname);
 }
 
 /*
@@ -672,8 +682,16 @@ defrouter_select(void)
 	 */
 	for (dr = TAILQ_FIRST(&nd_defrouter); dr;
 	     dr = TAILQ_NEXT(dr, dr_entry)) {
+		if (dr->installed && !installed_dr)
+			installed_dr = dr;
+		else if (dr->installed && installed_dr) {
+			/* this should not happen.  warn for diagnosis. */
+			log(LOG_ERR, "defrouter_select: more than one router"
+			    " is installed\n");
+		}
+
 		ndi = ND_IFINFO(dr->ifp);
-		if (nd6_accepts_rtadv(ndi))
+		if (!nd6_accepts_rtadv(ndi))
 			continue;
 
 		if (selected_dr == NULL &&
@@ -682,14 +700,6 @@ defrouter_select(void)
 		    ND6_IS_LLINFO_PROBREACH(ln)) {
 			selected_dr = dr;
 		}
-
-		if (dr->installed && !installed_dr)
-			installed_dr = dr;
-		else if (dr->installed && installed_dr) {
-			/* this should not happen.  warn for diagnosis. */
-			log(LOG_ERR, "defrouter_select: more than one router"
-			    " is installed\n");
-		}
 	}
 	/*
 	 * If none of the default routers was found to be reachable,

Reply via email to