From 40d8a30241dbfbd3bed1d70e12e7df3d0f2c6bed Mon Sep 17 00:00:00 2001 From: Bruce M Simpson Date: Thu, 22 Feb 2007 00:14:02 +0000 Subject: [PATCH] Fix a bug in if_findmulti(), whereby it would not find (and thus delete) a link-layer multicast group membership. Such memberships are needed in order to support protocols such as IS-IS without putting the interface into PROMISC or ALLMULTI modes. sa_equal() is not OK for comparing sockaddr_dl as it has deeper structure than a simple byte array, so add sa_dl_equal() and use that instead. Reviewed by: rwatson Verified with: /usr/sbin/mtest Bug found by: Jouke Witteveen MFC after: 2 weeks --- sys/net/if.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index 6d693df5cc3..04e8310e2a8 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -978,7 +978,21 @@ if_rtdel(struct radix_node *rn, void *arg) return (0); } -#define sa_equal(a1, a2) (bcmp((a1), (a2), ((a1))->sa_len) == 0) +/* + * XXX: Because sockaddr_dl has deeper structure than the sockaddr + * structs used to represent other address families, it is necessary + * to perform a different comparison. + */ + +#define sa_equal(a1, a2) \ + (bcmp((a1), (a2), ((a1))->sa_len) == 0) + +#define sa_dl_equal(a1, a2) \ + ((((struct sockaddr_dl *)(a1))->sdl_len == \ + ((struct sockaddr_dl *)(a2))->sdl_len) && \ + (bcmp(LLADDR((struct sockaddr_dl *)(a1)), \ + LLADDR((struct sockaddr_dl *)(a2)), \ + ((struct sockaddr_dl *)(a1))->sdl_alen) == 0)) /* * Locate an interface based on a complete address. @@ -2123,8 +2137,13 @@ if_findmulti(struct ifnet *ifp, struct sockaddr *sa) IF_ADDR_LOCK_ASSERT(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (sa_equal(ifma->ifma_addr, sa)) - break; + if (sa->sa_family == AF_LINK) { + if (sa_dl_equal(ifma->ifma_addr, sa)) + break; + } else { + if (sa_equal(ifma->ifma_addr, sa)) + break; + } } return ifma;