git: d4803b958cff - releng/13.0 - Fix 'in6_purgeaddr: err=65, destination address delete failed' message.
Alexander V. Chernikov
melifaro at FreeBSD.org
Thu Mar 11 21:45:17 UTC 2021
The branch releng/13.0 has been updated by melifaro:
URL: https://cgit.FreeBSD.org/src/commit/?id=d4803b958cff52dd14856a2a214c21bea1b69af7
commit d4803b958cff52dd14856a2a214c21bea1b69af7
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-11 21:38:01 +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
Approved by: re(gjb)
Differential Revision: https://reviews.freebsd.org/D29121
(cherry picked from commit 83cedad139721c6c150be8c078417cfcb311ee78)
---
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 48fa8dd2efc6..4f0724b7859f 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