git: 7634919e15f1 - main - Fix 'in6_purgeaddr: err=65, destination address delete failed' message.

Alexander V. Chernikov melifaro at FreeBSD.org
Mon Mar 8 21:28:45 UTC 2021


The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=7634919e15f1147b6f26d55354be375bc9b198db

commit 7634919e15f1147b6f26d55354be375bc9b198db
Author:     Alexander V. Chernikov <melifaro at FreeBSD.org>
AuthorDate: 2021-03-08 20:27:29 +0000
Commit:     Alexander V. Chernikov <melifaro at FreeBSD.org>
CommitDate: 2021-03-08 21:28:35 +0000

    Fix 'in6_purgeaddr: err=65, destination address delete failed' message.
    
    P2P ifa may require 2 routes: one is the loopback route, another is
     the "prefix" route towards its destination.
    
    Current code marks loopback routes existence with IFA_RTSELF and
     "prefix" p2p routes with IFA_ROUTE.
    
    For historic reasons, we fill in ifa_dstaddr for loopback interfaces.
    To avoid installing the same route twice, we preemptively set
     IFA_RTSELF when adding "prefix" route for loopback.
    However, the teardown part doesn't have this hack, so we try to
     remove the same route twice.
    
    Fix this by checking if ifa_dstaddr is different from the ifa_addr
     and moving this logic into a separate function.
    
    Reviewed By: kp
    Differential Revision: https://reviews.freebsd.org/D29121
    MFC after:      3 days
---
 sys/netinet6/in6.c | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 4665a21c28fd..02cb9df7da3a 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1294,13 +1294,27 @@ in6_handle_dstaddr_rtrequest(int cmd, struct in6_ifaddr *ia)
 	return (error);
 }
 
+static bool
+ifa_is_p2p(struct in6_ifaddr *ia)
+{
+	int plen;
+
+	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
+
+	if ((plen == 128) && (ia->ia_dstaddr.sin6_family == AF_INET6) &&
+	    !IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &ia->ia_dstaddr.sin6_addr))
+		return (true);
+
+	return (false);
+}
+
 void
 in6_purgeaddr(struct ifaddr *ifa)
 {
 	struct ifnet *ifp = ifa->ifa_ifp;
 	struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
 	struct in6_multi_mship *imm;
-	int plen, error;
+	int error;
 
 	if (ifa->ifa_carp)
 		(*carp_detach_p)(ifa, false);
@@ -1328,10 +1342,7 @@ in6_purgeaddr(struct ifaddr *ifa)
 		free(imm, M_IP6MADDR);
 	}
 	/* Check if we need to remove p2p route */
-	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
-	if (ia->ia_dstaddr.sin6_family != AF_INET6)
-		plen = 0;
-	if ((ia->ia_flags & IFA_ROUTE) && plen == 128) {
+	if ((ia->ia_flags & IFA_ROUTE) && ifa_is_p2p(ia)) {
 		error = in6_handle_dstaddr_rtrequest(RTM_DELETE, ia);
 		if (error != 0)
 			log(LOG_INFO, "%s: err=%d, destination address delete "
@@ -1434,7 +1445,7 @@ static int
 in6_notify_ifa(struct ifnet *ifp, struct in6_ifaddr *ia,
     struct in6_aliasreq *ifra, int hostIsNew)
 {
-	int	error = 0, plen, ifacount = 0;
+	int	error = 0, ifacount = 0;
 	struct ifaddr *ifa;
 	struct sockaddr_in6 *pdst;
 	char ip6buf[INET6_ADDRSTRLEN];
@@ -1487,14 +1498,7 @@ in6_notify_ifa(struct ifnet *ifp, struct in6_ifaddr *ia,
 	 * XXX: the logic below rejects assigning multiple addresses on a p2p
 	 * interface that share the same destination.
 	 */
-	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
-	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
-	    ia->ia_dstaddr.sin6_family == AF_INET6) {
-		/*
-		 * Handle the case for ::1 .
-		 */
-		if (ifp->if_flags & IFF_LOOPBACK)
-			ia->ia_flags |= IFA_RTSELF;
+	if (!(ia->ia_flags & IFA_ROUTE) && ifa_is_p2p(ia)) {
 		error = in6_handle_dstaddr_rtrequest(RTM_ADD, ia);
 		if (error)
 			goto done;


More information about the dev-commits-src-all mailing list