From 6c41171ac3f356768bb9a72ef5bbea401d598e94 Mon Sep 17 00:00:00 2001 From: mpi Date: Mon, 20 Apr 2015 09:07:42 +0000 Subject: [PATCH] Do not treat loopback interfaces as p2p interfaces and create only one route to "::1". Due to a clever BSD trick, the `ifa_dstaddr` field of addresses on IFF_LOOPBACK ifps is set to the same value that `ifa_addr`. That's why filtering for broadcast addresses is so complicated, because guess what, `ifa_broadaddr` is the same as `ifa_dstaddr`! Sadly our IPv6 code was "only" checking for `ifa_dstaddr` without looking if the ifa was attached to a IFF_POINTOTPOINT interface. So it always tried to create two routes to "::1" and, with the recent RTF_LOCAL work, succeed. You should now have only one local route to "::1". ::1 ::1 UHl 14 0 32768 1 lo0 -::1 ::1 UH 0 0 32768 4 lo0 ok henning@ --- sys/netinet6/in6.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 85db120fff2..479220748c8 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6.c,v 1.155 2015/04/20 08:53:36 mpi Exp $ */ +/* $OpenBSD: in6.c,v 1.156 2015/04/20 09:07:42 mpi Exp $ */ /* $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $ */ /* @@ -751,7 +751,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, * install the new destination. Note that the interface must be * p2p or loopback (see the check above.) */ - if (dst6.sin6_family == AF_INET6 && + if ((ifp->if_flags & IFF_POINTOPOINT) && dst6.sin6_family == AF_INET6 && !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia6->ia_dstaddr.sin6_addr)) { struct ifaddr *ifa = &ia6->ia_ifa; @@ -1020,7 +1020,8 @@ in6_purgeaddr(struct ifaddr *ifa) * delete route to the destination of the address being purged. * The interface must be p2p or loopback in this case. */ - if ((ia6->ia_flags & IFA_ROUTE) != 0 && ia6->ia_dstaddr.sin6_len != 0) { + if ((ifp->if_flags & IFF_POINTOPOINT) && (ia6->ia_flags & IFA_ROUTE) && + ia6->ia_dstaddr.sin6_len != 0) { int e; if ((e = rt_ifa_del(ifa, RTF_HOST, ifa->ifa_dstaddr)) != 0) { @@ -1364,7 +1365,8 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia6, int newhost) * direct route. */ plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL); /* XXX */ - if (plen == 128 && ia6->ia_dstaddr.sin6_family == AF_INET6) { + if ((ifp->if_flags & IFF_POINTOPOINT) && plen == 128 && + ia6->ia_dstaddr.sin6_family == AF_INET6) { ifa = &ia6->ia_ifa; error = rt_ifa_add(ifa, RTF_UP | RTF_HOST, ifa->ifa_dstaddr); if (error != 0) -- 2.20.1