igmpproxy: bump to 0.2.1

The sender domain has a DMARC Reject/Quarantine policy which disallows
sending mailing list messages using the original "From" header.

To mitigate this problem, the original message has been wrapped
automatically by the mailing list software.
Point at github which is new, maintained location for igmpproxy.
Remove all patches as all have been upstreamed.

Closes FS#1456

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
This commit is contained in:
Kevin Darbyshire-Bryant 2018-04-20 19:59:22 +00:00 committed by John Crispin
parent 0b04926433
commit 247055cbfb
10 changed files with 4 additions and 679 deletions

View file

@ -8,12 +8,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=igmpproxy
PKG_VERSION:=0.1
PKG_RELEASE:=11
PKG_VERSION:=0.2.1
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=@SF/igmpproxy
PKG_HASH:=ee18ff3d8c3ae3a29dccb7e5eedf332337330020168bd95a11cece8d7d7ee6ae
PKG_SOURCE_URL:=https://github.com/pali/igmpproxy/releases/download/${PKG_VERSION}/
PKG_HASH:=d351e623037390f575c1203d9cbb7ba33a8bdef85a3c5e1d2901c5a2a38449a1
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
include $(INCLUDE_DIR)/package.mk

View file

@ -1,79 +0,0 @@
From fed8c3db10bc9d3a1e799a774924c00522595d0c Mon Sep 17 00:00:00 2001
From: Evgeny Yurchenko <evg.yurch@rogers.com>
Date: Mon, 4 Jan 2010 05:13:59 +0500
Subject: [PATCH] Send IGMP packets with IP Router Alert option [RFC 2113] included in IP header
---
src/igmp.c | 17 ++++++++++++-----
src/igmpproxy.h | 1 +
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/src/igmp.c b/src/igmp.c
index a0cd27d..b547688 100644
--- a/src/igmp.c
+++ b/src/igmp.c
@@ -67,7 +67,7 @@ void initIgmp() {
* - Checksum (let the kernel fill it in)
*/
ip->ip_v = IPVERSION;
- ip->ip_hl = sizeof(struct ip) >> 2;
+ ip->ip_hl = (sizeof(struct ip) + 4) >> 2; /* +4 for Router Alert option */
ip->ip_tos = 0xc0; /* Internet Control */
ip->ip_ttl = MAXTTL; /* applies to unicasts only */
ip->ip_p = IPPROTO_IGMP;
@@ -213,7 +213,7 @@ void buildIgmp(uint32_t src, uint32_t dst, int type, int code, uint32_t group, i
ip = (struct ip *)send_buf;
ip->ip_src.s_addr = src;
ip->ip_dst.s_addr = dst;
- ip_set_len(ip, MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen);
+ ip_set_len(ip, IP_HEADER_RAOPT_LEN + IGMP_MINLEN + datalen);
if (IN_MULTICAST(ntohl(dst))) {
ip->ip_ttl = curttl;
@@ -221,13 +221,20 @@ void buildIgmp(uint32_t src, uint32_t dst, int type, int code, uint32_t group, i
ip->ip_ttl = MAXTTL;
}
- igmp = (struct igmp *)(send_buf + MIN_IP_HEADER_LEN);
+ /* Add Router Alert option */
+ ((u_char*)send_buf+MIN_IP_HEADER_LEN)[0] = IPOPT_RA;
+ ((u_char*)send_buf+MIN_IP_HEADER_LEN)[1] = 0x04;
+ ((u_char*)send_buf+MIN_IP_HEADER_LEN)[2] = 0x00;
+ ((u_char*)send_buf+MIN_IP_HEADER_LEN)[3] = 0x00;
+
+ igmp = (struct igmp *)(send_buf + IP_HEADER_RAOPT_LEN);
igmp->igmp_type = type;
igmp->igmp_code = code;
igmp->igmp_group.s_addr = group;
igmp->igmp_cksum = 0;
igmp->igmp_cksum = inetChksum((u_short *)igmp,
- IGMP_MINLEN + datalen);
+ IP_HEADER_RAOPT_LEN + datalen);
+
}
/*
@@ -257,7 +264,7 @@ void sendIgmp(uint32_t src, uint32_t dst, int type, int code, uint32_t group, in
#endif
sdst.sin_addr.s_addr = dst;
if (sendto(MRouterFD, send_buf,
- MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen, 0,
+ IP_HEADER_RAOPT_LEN + IGMP_MINLEN + datalen, 0,
(struct sockaddr *)&sdst, sizeof(sdst)) < 0) {
if (errno == ENETDOWN)
my_log(LOG_ERR, errno, "Sender VIF was down.");
diff --git a/src/igmpproxy.h b/src/igmpproxy.h
index 0de7791..4df8a79 100644
--- a/src/igmpproxy.h
+++ b/src/igmpproxy.h
@@ -64,6 +64,7 @@
#define MAX_IP_PACKET_LEN 576
#define MIN_IP_HEADER_LEN 20
#define MAX_IP_HEADER_LEN 60
+#define IP_HEADER_RAOPT_LEN 24
#define MAX_MC_VIFS 32 // !!! check this const in the specific includes
--
1.7.2.5

View file

@ -1,43 +0,0 @@
From 85e240727305b156097ee7aa0f0c4473a136291f Mon Sep 17 00:00:00 2001
From: Constantin Baranov <const@mimas.ru>
Date: Tue, 23 Feb 2010 21:08:02 +0400
Subject: [PATCH] Change default interface state to disabled (wrt #2945877)
---
src/ifvc.c | 2 +-
src/igmpproxy.c | 6 ++++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/ifvc.c b/src/ifvc.c
index 545b3b4..9d7ee97 100644
--- a/src/ifvc.c
+++ b/src/ifvc.c
@@ -139,7 +139,7 @@ void buildIfVc() {
IfDescEp->allowednets->subnet_addr = subnet;
// Set the default params for the IF...
- IfDescEp->state = IF_STATE_DOWNSTREAM;
+ IfDescEp->state = IF_STATE_DISABLED;
IfDescEp->robustness = DEFAULT_ROBUSTNESS;
IfDescEp->threshold = DEFAULT_THRESHOLD; /* ttl limit */
IfDescEp->ratelimit = DEFAULT_RATELIMIT;
diff --git a/src/igmpproxy.c b/src/igmpproxy.c
index 1ece15a..35000c7 100644
--- a/src/igmpproxy.c
+++ b/src/igmpproxy.c
@@ -186,8 +186,10 @@ int igmpProxyInit() {
}
}
- addVIF( Dp );
- vifcount++;
+ if (Dp->state != IF_STATE_DISABLED) {
+ addVIF( Dp );
+ vifcount++;
+ }
}
}
--
1.7.2.5

View file

@ -1,164 +0,0 @@
From 65f777e7f66b55239d935c1cf81bb5abc0f6c89f Mon Sep 17 00:00:00 2001
From: Grinch <grinch79@users.sourceforge.net>
Date: Sun, 16 Aug 2009 19:58:26 +0500
Subject: [PATCH] Restrict igmp reports for downstream interfaces (wrt #2833339)
atm all igmp membership reports are forwarded to the upstream interface.
Unfortunately some ISP Providers restrict some multicast groups (esp. those
that are defined as local link groups and that are not supposed to be
forwarded to the wan, i.e 224.0.0.0/24). Therefore there should be some
kind of black oder whitelisting.
As whitelisting can be accomplished quite easy I wrote a litte patch, which
is attached to this request.
---
doc/igmpproxy.conf.5.in | 19 +++++++++++++++++++
src/config.c | 23 ++++++++++++++++++++++-
src/igmpproxy.h | 1 +
src/request.c | 20 ++++++++++++++++----
4 files changed, 58 insertions(+), 5 deletions(-)
diff --git a/doc/igmpproxy.conf.5.in b/doc/igmpproxy.conf.5.in
index a4ea7d0..56efa22 100644
--- a/doc/igmpproxy.conf.5.in
+++ b/doc/igmpproxy.conf.5.in
@@ -116,6 +116,25 @@ This is especially useful for the upstream interface, since the source for multi
traffic is often from a remote location. Any number of altnet parameters can be specified.
.RE
+.B whitelist
+.I networkaddr
+.RS
+Defines a whitelist for multicast groups. The network address must be in the following
+format 'a.b.c.d/n'. If you want to allow one single group use a network mask of /32,
+i.e. 'a.b.c.d/32'.
+
+By default all multicast groups are allowed on any downstream interface. If at least one
+whitelist entry is defined, all igmp membership reports for not explicitly whitelisted
+multicast groups will be ignored and therefore not be served by igmpproxy. This is especially
+useful, if your provider does only allow a predefined set of multicast groups. These whitelists
+are only obeyed by igmpproxy itself, they won't prevent any other igmp client running on the
+same machine as igmpproxy from requesting 'unallowed' multicast groups.
+
+You may specify as many whitelist entries as needed. Although you should keep it as simple as
+possible, as this list is parsed for every membership report and therefore this increases igmp
+response times. Often used or large groups should be defined first, as parsing ends as soon as
+a group matches an entry.
+.RE
.SH EXAMPLE
## Enable quickleave
diff --git a/src/config.c b/src/config.c
index 5a96ce0..d72619f 100644
--- a/src/config.c
+++ b/src/config.c
@@ -46,6 +46,9 @@ struct vifconfig {
// Keep allowed nets for VIF.
struct SubnetList* allowednets;
+
+ // Allowed Groups
+ struct SubnetList* allowedgroups;
// Next config in list...
struct vifconfig* next;
@@ -202,6 +205,8 @@ void configureVifs() {
// Insert the configured nets...
vifLast->next = confPtr->allowednets;
+ Dp->allowedgroups = confPtr->allowedgroups;
+
break;
}
}
@@ -215,7 +220,7 @@ void configureVifs() {
*/
struct vifconfig *parsePhyintToken() {
struct vifconfig *tmpPtr;
- struct SubnetList **anetPtr;
+ struct SubnetList **anetPtr, **agrpPtr;
char *token;
short parseError = 0;
@@ -239,6 +244,7 @@ struct vifconfig *parsePhyintToken() {
tmpPtr->threshold = 1;
tmpPtr->state = IF_STATE_DOWNSTREAM;
tmpPtr->allowednets = NULL;
+ tmpPtr->allowedgroups = NULL;
// Make a copy of the token to store the IF name
tmpPtr->name = strdup( token );
@@ -248,6 +254,7 @@ struct vifconfig *parsePhyintToken() {
// Set the altnet pointer to the allowednets pointer.
anetPtr = &tmpPtr->allowednets;
+ agrpPtr = &tmpPtr->allowedgroups;
// Parse the rest of the config..
token = nextConfigToken();
@@ -266,6 +273,20 @@ struct vifconfig *parsePhyintToken() {
anetPtr = &(*anetPtr)->next;
}
}
+ else if(strcmp("whitelist", token)==0) {
+ // Whitelist
+ token = nextConfigToken();
+ my_log(LOG_DEBUG, 0, "Config: IF: Got whitelist token %s.", token);
+
+ *agrpPtr = parseSubnetAddress(token);
+ if(*agrpPtr == NULL) {
+ parseError = 1;
+ my_log(LOG_WARNING, 0, "Unable to parse subnet address.");
+ break;
+ } else {
+ agrpPtr = &(*agrpPtr)->next;
+ }
+ }
else if(strcmp("upstream", token)==0) {
// Upstream
my_log(LOG_DEBUG, 0, "Config: IF: Got upstream token.");
diff --git a/src/igmpproxy.h b/src/igmpproxy.h
index 4dabd1c..0de7791 100644
--- a/src/igmpproxy.h
+++ b/src/igmpproxy.h
@@ -145,6 +145,7 @@ struct IfDesc {
short Flags;
short state;
struct SubnetList* allowednets;
+ struct SubnetList* allowedgroups;
unsigned int robustness;
unsigned char threshold; /* ttl limit */
unsigned int ratelimit;
diff --git a/src/request.c b/src/request.c
index e3589f6..89b91de 100644
--- a/src/request.c
+++ b/src/request.c
@@ -82,10 +82,22 @@ void acceptGroupReport(uint32_t src, uint32_t group, uint8_t type) {
my_log(LOG_DEBUG, 0, "Should insert group %s (from: %s) to route table. Vif Ix : %d",
inetFmt(group,s1), inetFmt(src,s2), sourceVif->index);
- // The membership report was OK... Insert it into the route table..
- insertRoute(group, sourceVif->index);
-
-
+ // If we don't have a whitelist we insertRoute and done
+ if(sourceVif->allowedgroups == NULL)
+ {
+ insertRoute(group, sourceVif->index);
+ return;
+ }
+ // Check if this Request is legit on this interface
+ struct SubnetList *sn;
+ for(sn = sourceVif->allowedgroups; sn != NULL; sn = sn->next)
+ if((group & sn->subnet_mask) == sn->subnet_addr)
+ {
+ // The membership report was OK... Insert it into the route table..
+ insertRoute(group, sourceVif->index);
+ return;
+ }
+ my_log(LOG_INFO, 0, "The group address %s may not be requested from this interface. Ignoring.", inetFmt(group, s1));
} else {
// Log the state of the interface the report was recieved on.
my_log(LOG_INFO, 0, "Mebership report was recieved on %s. Ignoring.",
--
1.7.2.5

View file

@ -1,62 +0,0 @@
From bcd7c648e86d97263c931de53a008c9629e7797e Mon Sep 17 00:00:00 2001
From: Stefan Becker <stefan.becker@nokia.com>
Date: Fri, 11 Dec 2009 21:08:57 +0200
Subject: [PATCH] Restrict igmp reports forwarding to upstream interface
Utilize the new "whitelist" keyword also on the upstream interface definition.
If specified then only whitelisted multicast groups will be forwarded upstream.
This can be used to avoid publishing private multicast groups to the world,
e.g. SSDP from a UPnP server on the internal network.
---
doc/igmpproxy.conf.5.in | 5 +++++
src/rttable.c | 17 +++++++++++++++++
2 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/doc/igmpproxy.conf.5.in b/doc/igmpproxy.conf.5.in
index 56efa22..d916f05 100644
--- a/doc/igmpproxy.conf.5.in
+++ b/doc/igmpproxy.conf.5.in
@@ -134,6 +134,11 @@ You may specify as many whitelist entries as needed. Although you should keep it
possible, as this list is parsed for every membership report and therefore this increases igmp
response times. Often used or large groups should be defined first, as parsing ends as soon as
a group matches an entry.
+
+You may also specify whitelist entries for the upstream interface. Only igmp membership reports
+for explicitely whitelisted multicast groups will be sent out on the upstream interface. This
+is useful if you want to use multicast groups only between your downstream interfaces, like SSDP
+from a UPnP server.
.RE
.SH EXAMPLE
diff --git a/src/rttable.c b/src/rttable.c
index f0701a8..77dd791 100644
--- a/src/rttable.c
+++ b/src/rttable.c
@@ -117,6 +117,23 @@ void sendJoinLeaveUpstream(struct RouteTable* route, int join) {
my_log(LOG_ERR, 0 ,"FATAL: Unable to get Upstream IF.");
}
+ // Check if there is a white list for the upstram VIF
+ if (upstrIf->allowedgroups != NULL) {
+ uint32_t group = route->group;
+ struct SubnetList* sn;
+
+ // Check if this Request is legit to be forwarded to upstream
+ for(sn = upstrIf->allowedgroups; sn != NULL; sn = sn->next)
+ if((group & sn->subnet_mask) == sn->subnet_addr)
+ // Forward is OK...
+ break;
+
+ if (sn == NULL) {
+ my_log(LOG_INFO, 0, "The group address %s may not be forwarded upstream. Ignoring.", inetFmt(group, s1));
+ return;
+ }
+ }
+
// Send join or leave request...
if(join) {
--
1.7.2.5

View file

@ -1,10 +0,0 @@
--- a/src/os-linux.h
+++ b/src/os-linux.h
@@ -3,6 +3,7 @@
#include <linux/mroute.h>
#include <netinet/ip.h>
#include <netinet/igmp.h>
+#include <sys/types.h>
static inline u_short ip_data_len(const struct ip *ip)
{

View file

@ -1,19 +0,0 @@
--- a/src/igmp.c
+++ b/src/igmp.c
@@ -139,8 +139,14 @@
return;
}
else if(!isAdressValidForIf(checkVIF, src)) {
- my_log(LOG_WARNING, 0, "The source address %s for group %s, is not in any valid net for upstream VIF.",
- inetFmt(src, s1), inetFmt(dst, s2));
+ struct IfDesc *downVIF = getIfByAddress(src);
+ if (downVIF && downVIF->state & IF_STATE_DOWNSTREAM) {
+ my_log(LOG_NOTICE, 0, "The source address %s for group %s is from downstream VIF. Ignoring.",
+ inetFmt(src, s1), inetFmt(dst, s2));
+ } else {
+ my_log(LOG_WARNING, 0, "The source address %s for group %s, is not in any valid net for upstream VIF.",
+ inetFmt(src, s1), inetFmt(dst, s2));
+ }
return;
}

View file

@ -1,120 +0,0 @@
From d0e66e0719ae8eb549f7cc220fdc66575d3db332 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Thu, 29 Mar 2012 17:01:11 +0200
Subject: [PATCH 4/4] use monotic clock instead of time of day
The time of day might chance e.g. by daylight savings time during the
runtime, which causes timers to fire repeatedly for a long time.
Contributed by T-Labs, Deutsche Telekom Innovation Laboratories
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
configure.ac | 2 ++
src/igmpproxy.c | 26 +++++++++++++-------------
src/igmpproxy.h | 3 ++-
3 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/configure.ac b/configure.ac
index 85beb08..bd84eba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -25,6 +25,8 @@ AC_CHECK_MEMBERS([struct sockaddr_in.sin_len], [], [], [[
#include <netinet/in.h>
]])
+AC_SEARCH_LIBS([clock_gettime],[rt])
+
AC_CONFIG_FILES([
Makefile
doc/Makefile
diff --git a/src/igmpproxy.c b/src/igmpproxy.c
index 35000c7..3a9ccad 100644
--- a/src/igmpproxy.c
+++ b/src/igmpproxy.c
@@ -234,13 +234,13 @@ void igmpProxyRun() {
int MaxFD, Rt, secs;
fd_set ReadFDS;
socklen_t dummy = 0;
- struct timeval curtime, lasttime, difftime, tv;
+ struct timespec curtime, lasttime, difftime, tv;
// The timeout is a pointer in order to set it to NULL if nessecary.
- struct timeval *timeout = &tv;
+ struct timespec *timeout = &tv;
// Initialize timer vars
- difftime.tv_usec = 0;
- gettimeofday(&curtime, NULL);
+ difftime.tv_nsec = 0;
+ clock_gettime(CLOCK_MONOTONIC, &curtime);
lasttime = curtime;
// First thing we send a membership query in downstream VIF's...
@@ -263,7 +263,7 @@ void igmpProxyRun() {
if(secs == -1) {
timeout = NULL;
} else {
- timeout->tv_usec = 0;
+ timeout->tv_nsec = 0;
timeout->tv_sec = secs;
}
@@ -274,7 +274,7 @@ void igmpProxyRun() {
FD_SET( MRouterFD, &ReadFDS );
// wait for input
- Rt = select( MaxFD +1, &ReadFDS, NULL, NULL, timeout );
+ Rt = pselect( MaxFD +1, &ReadFDS, NULL, NULL, timeout, NULL );
// log and ignore failures
if( Rt < 0 ) {
@@ -307,20 +307,20 @@ void igmpProxyRun() {
*/
if (Rt == 0) {
curtime.tv_sec = lasttime.tv_sec + secs;
- curtime.tv_usec = lasttime.tv_usec;
+ curtime.tv_nsec = lasttime.tv_nsec;
Rt = -1; /* don't do this next time through the loop */
} else {
- gettimeofday(&curtime, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &curtime);
}
difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec;
- difftime.tv_usec += curtime.tv_usec - lasttime.tv_usec;
- while (difftime.tv_usec > 1000000) {
+ difftime.tv_nsec += curtime.tv_nsec - lasttime.tv_nsec;
+ while (difftime.tv_nsec > 1000000000) {
difftime.tv_sec++;
- difftime.tv_usec -= 1000000;
+ difftime.tv_nsec -= 1000000000;
}
- if (difftime.tv_usec < 0) {
+ if (difftime.tv_nsec < 0) {
difftime.tv_sec--;
- difftime.tv_usec += 1000000;
+ difftime.tv_nsec += 1000000000;
}
lasttime = curtime;
if (secs == 0 || difftime.tv_sec > 0)
diff --git a/src/igmpproxy.h b/src/igmpproxy.h
index 4df8a79..36a4f04 100644
--- a/src/igmpproxy.h
+++ b/src/igmpproxy.h
@@ -44,12 +44,13 @@
#include <string.h>
#include <fcntl.h>
#include <stdbool.h>
+#include <time.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/param.h>
+#include <sys/select.h>
#include <net/if.h>
#include <netinet/in.h>
--
1.7.2.5

View file

@ -1,24 +0,0 @@
--- a/src/config.c
+++ b/src/config.c
@@ -357,15 +357,18 @@ struct SubnetList *parseSubnetAddress(ch
tmpStr = strtok(NULL, "/");
if(tmpStr != NULL) {
int bitcnt = atoi(tmpStr);
- if(bitcnt <= 0 || bitcnt > 32) {
+ if(bitcnt < 0 || bitcnt > 32) {
my_log(LOG_WARNING, 0, "The bits part of the address is invalid : %d.",tmpStr);
return NULL;
}
- mask <<= (32 - bitcnt);
+ if (bitcnt == 0)
+ mask = 0;
+ else
+ mask <<= (32 - bitcnt);
}
- if(addr == -1 || addr == 0) {
+ if(addr == -1) {
my_log(LOG_WARNING, 0, "Unable to parse address token '%s'.", addrstr);
return NULL;
}

View file

@ -1,154 +0,0 @@
--- a/src/igmpproxy.h
+++ b/src/igmpproxy.h
@@ -251,6 +251,7 @@ int activateRoute(uint32_t group, uint32
void ageActiveRoutes();
void setRouteLastMemberMode(uint32_t group);
int lastMemberGroupAge(uint32_t group);
+int interfaceInRoute(int32_t group, int Ix);
/* request.c
*/
--- a/src/request.c
+++ b/src/request.c
@@ -41,10 +41,10 @@
// Prototypes...
void sendGroupSpecificMemberQuery(void *argument);
-
+
typedef struct {
uint32_t group;
- uint32_t vifAddr;
+ // uint32_t vifAddr;
short started;
} GroupVifDesc;
@@ -142,7 +142,7 @@ void acceptLeaveMessage(uint32_t src, ui
// Call the group spesific membership querier...
gvDesc->group = group;
- gvDesc->vifAddr = sourceVif->InAdr.s_addr;
+ // gvDesc->vifAddr = sourceVif->InAdr.s_addr;
gvDesc->started = 0;
sendGroupSpecificMemberQuery(gvDesc);
@@ -159,6 +159,9 @@ void acceptLeaveMessage(uint32_t src, ui
*/
void sendGroupSpecificMemberQuery(void *argument) {
struct Config *conf = getCommonConfig();
+ struct IfDesc *Dp;
+ struct RouteTable *croute;
+ int Ix;
// Cast argument to correct type...
GroupVifDesc *gvDesc = (GroupVifDesc*) argument;
@@ -166,22 +169,38 @@ void sendGroupSpecificMemberQuery(void *
if(gvDesc->started) {
// If aging returns false, we don't do any further action...
if(!lastMemberGroupAge(gvDesc->group)) {
+ // FIXME: Should we free gvDesc here?
return;
}
} else {
gvDesc->started = 1;
}
- // Send a group specific membership query...
- sendIgmp(gvDesc->vifAddr, gvDesc->group,
- IGMP_MEMBERSHIP_QUERY,
- conf->lastMemberQueryInterval * IGMP_TIMER_SCALE,
- gvDesc->group, 0);
-
- my_log(LOG_DEBUG, 0, "Sent membership query from %s to %s. Delay: %d",
- inetFmt(gvDesc->vifAddr,s1), inetFmt(gvDesc->group,s2),
- conf->lastMemberQueryInterval);
-
+ /**
+ * FIXME: This loops through all interfaces the group is active on an sends queries.
+ * It might be better to send only a query on the interface the leave was accepted on and remove only that interface from the route.
+ */
+
+ // Loop through all downstream interfaces
+ for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
+ if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
+ if(Dp->state == IF_STATE_DOWNSTREAM) {
+ // Is that interface used in the group?
+ if (interfaceInRoute(gvDesc->group ,Dp->index)) {
+
+ // Send a group specific membership query...
+ sendIgmp(Dp->InAdr.s_addr, gvDesc->group,
+ IGMP_MEMBERSHIP_QUERY,
+ conf->lastMemberQueryInterval * IGMP_TIMER_SCALE,
+ gvDesc->group, 0);
+
+ my_log(LOG_DEBUG, 0, "Sent membership query from %s to %s. Delay: %d",
+ inetFmt(Dp->InAdr.s_addr,s1), inetFmt(gvDesc->group,s2),
+ conf->lastMemberQueryInterval);
+ }
+ }
+ }
+ }
// Set timeout for next round...
timer_setTimer(conf->lastMemberQueryInterval, sendGroupSpecificMemberQuery, gvDesc);
--- a/src/rttable.c
+++ b/src/rttable.c
@@ -428,6 +428,25 @@ void ageActiveRoutes() {
}
/**
+* Counts the number of interfaces a given route is active on
+*/
+int numberOfInterfaces(struct RouteTable *croute) {
+ int Ix;
+ struct IfDesc *Dp;
+ int result = 0;
+ // Loop through all interfaces
+ for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
+ // If the interface is used by the route, increase counter
+ if(BIT_TST(croute->vifBits, Dp->index)) {
+ result++;
+ }
+ }
+ my_log(LOG_DEBUG, 0, "counted %d interfaces", result);
+ return result;
+}
+
+
+/**
* Should be called when a leave message is recieved, to
* mark a route for the last member probe state.
*/
@@ -439,8 +458,11 @@ void setRouteLastMemberMode(uint32_t gro
if(croute!=NULL) {
// Check for fast leave mode...
if(croute->upstrState == ROUTESTATE_JOINED && conf->fastUpstreamLeave) {
- // Send a leave message right away..
- sendJoinLeaveUpstream(croute, 0);
+ // Send a leave message right away only when the route has been active on only one interface
+ if (numberOfInterfaces(croute) <= 1) {
+ my_log(LOG_DEBUG, 0, "Leaving group %d now", group);
+ sendJoinLeaveUpstream(croute, 0);
+ }
}
// Set the routingstate to Last member check...
croute->upstrState = ROUTESTATE_CHECK_LAST_MEMBER;
@@ -677,3 +699,18 @@ void logRouteTable(char *header) {
my_log(LOG_DEBUG, 0, "-----------------------------------------------------");
}
+
+/**
+* Returns true when the given group belongs to the given interface
+*/
+int interfaceInRoute(int32_t group, int Ix) {
+ struct RouteTable* croute;
+ croute = findRoute(group);
+ if (croute != NULL) {
+ my_log(LOG_DEBUG, 0, "Interface id %d is in group $d", Ix, group);
+ return BIT_TST(croute->vifBits, Ix);
+ } else {
+ return 0;
+ }
+}
+