summaryrefslogtreecommitdiffstats
path: root/sys/net/if.c
diff options
context:
space:
mode:
authorbms <bms@FreeBSD.org>2007-02-22 00:14:02 +0000
committerbms <bms@FreeBSD.org>2007-02-22 00:14:02 +0000
commitaaa1e7fb11616f5de7f0c38babdc747796dd4beb (patch)
treef1e60ea7c59d0d49c1a3c9215dcc8aade062d410 /sys/net/if.c
parentbcf58d1f0e5fd75bcefa5835bd46faef25395bfe (diff)
downloadFreeBSD-src-aaa1e7fb11616f5de7f0c38babdc747796dd4beb.zip
FreeBSD-src-aaa1e7fb11616f5de7f0c38babdc747796dd4beb.tar.gz
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
Diffstat (limited to 'sys/net/if.c')
-rw-r--r--sys/net/if.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 6d693df..04e8310 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;
OpenPOWER on IntegriCloud