add chaos_calmer branch
[15.05/openwrt.git] / package / network / services / igmpproxy / patches / 003-Restrict-igmp-reports-for-downstream-interfaces-wrt-.patch
1 From 65f777e7f66b55239d935c1cf81bb5abc0f6c89f Mon Sep 17 00:00:00 2001
2 From: Grinch <grinch79@users.sourceforge.net>
3 Date: Sun, 16 Aug 2009 19:58:26 +0500
4 Subject: [PATCH] Restrict igmp reports for downstream interfaces (wrt #2833339)
5
6 atm all igmp membership reports are forwarded to the upstream interface.
7 Unfortunately some ISP Providers restrict some multicast groups (esp. those
8 that are defined as local link groups and that are not supposed to be
9 forwarded to the wan, i.e 224.0.0.0/24). Therefore there should be some
10 kind of black oder whitelisting.
11 As whitelisting can be accomplished quite easy I wrote a litte patch, which
12 is attached to this request.
13 ---
14  doc/igmpproxy.conf.5.in |   19 +++++++++++++++++++
15  src/config.c            |   23 ++++++++++++++++++++++-
16  src/igmpproxy.h         |    1 +
17  src/request.c           |   20 ++++++++++++++++----
18  4 files changed, 58 insertions(+), 5 deletions(-)
19
20 diff --git a/doc/igmpproxy.conf.5.in b/doc/igmpproxy.conf.5.in
21 index a4ea7d0..56efa22 100644
22 --- a/doc/igmpproxy.conf.5.in
23 +++ b/doc/igmpproxy.conf.5.in
24 @@ -116,6 +116,25 @@ This is especially useful for the upstream interface, since the source for multi
25  traffic is often from a remote location. Any number of altnet parameters can be specified.
26  .RE
27  
28 +.B whitelist
29 +.I networkaddr
30 +.RS
31 +Defines a whitelist for multicast groups. The network address must be in the following
32 +format 'a.b.c.d/n'. If you want to allow one single group use a network mask of /32,
33 +i.e. 'a.b.c.d/32'. 
34 +
35 +By default all multicast groups are allowed on any downstream interface. If at least one
36 +whitelist entry is defined, all igmp membership reports for not explicitly whitelisted
37 +multicast groups will be ignored and therefore not be served by igmpproxy. This is especially
38 +useful, if your provider does only allow a predefined set of multicast groups. These whitelists
39 +are only obeyed by igmpproxy itself, they won't prevent any other igmp client running on the
40 +same machine as igmpproxy from requesting 'unallowed' multicast groups.
41 +
42 +You may specify as many whitelist entries as needed. Although you should keep it as simple as
43 +possible, as this list is parsed for every membership report and therefore this increases igmp
44 +response times. Often used or large groups should be defined first, as parsing ends as soon as
45 +a group matches an entry.
46 +.RE
47  
48  .SH EXAMPLE
49  ## Enable quickleave
50 diff --git a/src/config.c b/src/config.c
51 index 5a96ce0..d72619f 100644
52 --- a/src/config.c
53 +++ b/src/config.c
54 @@ -46,6 +46,9 @@ struct vifconfig {
55  
56      // Keep allowed nets for VIF.
57      struct SubnetList*  allowednets;
58 +
59 +    // Allowed Groups
60 +    struct SubnetList*  allowedgroups;
61      
62      // Next config in list...
63      struct vifconfig*   next;
64 @@ -202,6 +205,8 @@ void configureVifs() {
65                      // Insert the configured nets...
66                      vifLast->next = confPtr->allowednets;
67  
68 +                   Dp->allowedgroups = confPtr->allowedgroups;
69 +
70                      break;
71                  }
72              }
73 @@ -215,7 +220,7 @@ void configureVifs() {
74  */
75  struct vifconfig *parsePhyintToken() {
76      struct vifconfig  *tmpPtr;
77 -    struct SubnetList **anetPtr;
78 +    struct SubnetList **anetPtr, **agrpPtr;
79      char *token;
80      short parseError = 0;
81  
82 @@ -239,6 +244,7 @@ struct vifconfig *parsePhyintToken() {
83      tmpPtr->threshold = 1;
84      tmpPtr->state = IF_STATE_DOWNSTREAM;
85      tmpPtr->allowednets = NULL;
86 +    tmpPtr->allowedgroups = NULL;
87  
88      // Make a copy of the token to store the IF name
89      tmpPtr->name = strdup( token );
90 @@ -248,6 +254,7 @@ struct vifconfig *parsePhyintToken() {
91  
92      // Set the altnet pointer to the allowednets pointer.
93      anetPtr = &tmpPtr->allowednets;
94 +    agrpPtr = &tmpPtr->allowedgroups; 
95  
96      // Parse the rest of the config..
97      token = nextConfigToken();
98 @@ -266,6 +273,20 @@ struct vifconfig *parsePhyintToken() {
99                  anetPtr = &(*anetPtr)->next;
100              }
101          }
102 +       else if(strcmp("whitelist", token)==0) {
103 +           // Whitelist
104 +           token = nextConfigToken();
105 +           my_log(LOG_DEBUG, 0, "Config: IF: Got whitelist token %s.", token);
106 +       
107 +           *agrpPtr = parseSubnetAddress(token);
108 +           if(*agrpPtr == NULL) {
109 +               parseError = 1;
110 +               my_log(LOG_WARNING, 0, "Unable to parse subnet address.");
111 +               break;
112 +           } else {
113 +               agrpPtr = &(*agrpPtr)->next;
114 +           }
115 +       }
116          else if(strcmp("upstream", token)==0) {
117              // Upstream
118              my_log(LOG_DEBUG, 0, "Config: IF: Got upstream token.");
119 diff --git a/src/igmpproxy.h b/src/igmpproxy.h
120 index 4dabd1c..0de7791 100644
121 --- a/src/igmpproxy.h
122 +++ b/src/igmpproxy.h
123 @@ -145,6 +145,7 @@ struct IfDesc {
124      short               Flags;
125      short               state;
126      struct SubnetList*  allowednets;
127 +    struct SubnetList*  allowedgroups;
128      unsigned int        robustness;
129      unsigned char       threshold;   /* ttl limit */
130      unsigned int        ratelimit; 
131 diff --git a/src/request.c b/src/request.c
132 index e3589f6..89b91de 100644
133 --- a/src/request.c
134 +++ b/src/request.c
135 @@ -82,10 +82,22 @@ void acceptGroupReport(uint32_t src, uint32_t group, uint8_t type) {
136          my_log(LOG_DEBUG, 0, "Should insert group %s (from: %s) to route table. Vif Ix : %d",
137              inetFmt(group,s1), inetFmt(src,s2), sourceVif->index);
138  
139 -        // The membership report was OK... Insert it into the route table..
140 -        insertRoute(group, sourceVif->index);
141 -
142 -
143 +       // If we don't have a whitelist we insertRoute and done
144 +       if(sourceVif->allowedgroups == NULL)
145 +       {
146 +           insertRoute(group, sourceVif->index);
147 +           return;
148 +       }
149 +       // Check if this Request is legit on this interface
150 +       struct SubnetList *sn;
151 +       for(sn = sourceVif->allowedgroups; sn != NULL; sn = sn->next)
152 +           if((group & sn->subnet_mask) == sn->subnet_addr)
153 +           {
154 +               // The membership report was OK... Insert it into the route table..
155 +               insertRoute(group, sourceVif->index);
156 +               return;
157 +           }
158 +       my_log(LOG_INFO, 0, "The group address %s may not be requested from this interface. Ignoring.", inetFmt(group, s1));
159      } else {
160          // Log the state of the interface the report was recieved on.
161          my_log(LOG_INFO, 0, "Mebership report was recieved on %s. Ignoring.",
162 -- 
163 1.7.2.5
164