diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2013-11-28 10:16:45 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2013-11-28 10:16:45 +0000 |
commit | dd2b8403a85186728d2280050afeae817692a102 (patch) | |
tree | 2be6ccc8bb7e213382b01dd964b542fc91a7a1e9 /sys/netinet/igmp.c | |
parent | cba989db5ef2c262d2eeb2ee6f56d8c75d717d38 (diff) |
Change the way protocol multicast addresses are linked to an interface.
Instead of linking multicast records to the first configured address of
the corresponding protocol, making this address and its position in the
global list special, add them to a new list directly linked to the
interface descriptor.
This new multicast address list is similar to the address list, all its
elements contain a protocol agnostic part. This design allows us to
be able to join a multicast group without necessarily having a configured
address. That means IPv6 multicast kludges are no longer needed.
Another benefit is to be able to add and remove an IP address from an
interface without worrying about multicast records. That means that the
global IPv4 list is no longer needed since the first configured address
of an interface is no longer special.
This new list might also be extended in the future to contain the
link-layer addresses used to configure hardware filters.
Tested by sthen@ and weerd@, ok mikeb@
Diffstat (limited to 'sys/netinet/igmp.c')
-rw-r--r-- | sys/netinet/igmp.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index 977e048b252..51fbb15fc38 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: igmp.c,v 1.35 2013/10/18 09:04:02 mpi Exp $ */ +/* $OpenBSD: igmp.c,v 1.36 2013/11/28 10:16:44 mpi Exp $ */ /* $NetBSD: igmp.c,v 1.15 1996/02/13 23:41:25 christos Exp $ */ /* @@ -83,6 +83,7 @@ #include <sys/sysctl.h> #include <net/if.h> +#include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> @@ -193,6 +194,7 @@ igmp_input(struct mbuf *m, ...) struct igmp *igmp; int igmplen; int minlen; + struct ifmaddr *ifma; struct in_multi *inm; struct router_info *rti; struct in_ifaddr *ia; @@ -266,7 +268,10 @@ igmp_input(struct mbuf *m, ...) * except those that are already running and those * that belong to a "local" group (224.0.0.X). */ - IN_FOREACH_MULTI(ia, ifp, inm) { + TAILQ_FOREACH(ifma, &ifp->if_maddrlist, ifma_list) { + if (ifma->ifma_addr->sa_family != AF_INET) + continue; + inm = ifmatoinm(ifma); if (inm->inm_timer == 0 && !IN_LOCAL_GROUP(inm->inm_addr.s_addr)) { inm->inm_state = IGMP_DELAYING_MEMBER; @@ -294,7 +299,10 @@ igmp_input(struct mbuf *m, ...) * timers already running, check if they need to be * reset. */ - IN_FOREACH_MULTI(ia, ifp, inm) { + TAILQ_FOREACH(ifma, &ifp->if_maddrlist, ifma_list) { + if (ifma->ifma_addr->sa_family != AF_INET) + continue; + inm = ifmatoinm(ifma); if (!IN_LOCAL_GROUP(inm->inm_addr.s_addr) && (ip->ip_dst.s_addr == INADDR_ALLHOSTS_GROUP || ip->ip_dst.s_addr == inm->inm_addr.s_addr)) { @@ -479,6 +487,8 @@ void igmp_leavegroup(struct in_multi *inm) { + int s = splsoftnet(); + switch (inm->inm_state) { case IGMP_DELAYING_MEMBER: case IGMP_IDLE_MEMBER: @@ -494,6 +504,7 @@ igmp_leavegroup(struct in_multi *inm) case IGMP_SLEEPING_MEMBER: break; } + splx(s); } void @@ -521,11 +532,14 @@ void igmp_checktimer(struct ifnet *ifp) { struct in_multi *inm; - struct in_ifaddr *ia; + struct ifmaddr *ifma; splsoftassert(IPL_SOFTNET); - IN_FOREACH_MULTI(ia, ifp, inm) { + TAILQ_FOREACH(ifma, &ifp->if_maddrlist, ifma_list) { + if (ifma->ifma_addr->sa_family != AF_INET) + continue; + inm = ifmatoinm(ifma); if (inm->inm_timer == 0) { /* do nothing */ } else if (--inm->inm_timer == 0) { |