summaryrefslogtreecommitdiff
path: root/sys/netinet/igmp.c
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2013-11-28 10:16:45 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2013-11-28 10:16:45 +0000
commitdd2b8403a85186728d2280050afeae817692a102 (patch)
tree2be6ccc8bb7e213382b01dd964b542fc91a7a1e9 /sys/netinet/igmp.c
parentcba989db5ef2c262d2eeb2ee6f56d8c75d717d38 (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.c24
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) {