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
This commit is contained in:
parent
129230b816
commit
40d8a30241
25
sys/net/if.c
25
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;
|
||||
|
Loading…
Reference in New Issue
Block a user