|
|
@@ -0,0 +1,164 @@
|
|
|
+From 65f777e7f66b55239d935c1cf81bb5abc0f6c89f Mon Sep 17 00:00:00 2001
|
|
|
+From: Grinch <[email protected]>
|
|
|
+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
|
|
|
+
|