Annotation of embedaddon/igmpproxy/src/request.c, revision 1.1.1.1
1.1 misho 1: /*
2: ** igmpproxy - IGMP proxy based multicast router
3: ** Copyright (C) 2005 Johnny Egeland <johnny@rlo.org>
4: **
5: ** This program is free software; you can redistribute it and/or modify
6: ** it under the terms of the GNU General Public License as published by
7: ** the Free Software Foundation; either version 2 of the License, or
8: ** (at your option) any later version.
9: **
10: ** This program is distributed in the hope that it will be useful,
11: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: ** GNU General Public License for more details.
14: **
15: ** You should have received a copy of the GNU General Public License
16: ** along with this program; if not, write to the Free Software
17: ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18: **
19: **----------------------------------------------------------------------------
20: **
21: ** This software is derived work from the following software. The original
22: ** source code has been modified from it's original state by the author
23: ** of igmpproxy.
24: **
25: ** smcroute 0.92 - Copyright (C) 2001 Carsten Schill <carsten@cschill.de>
26: ** - Licensed under the GNU General Public License, version 2
27: **
28: ** mrouted 3.9-beta3 - COPYRIGHT 1989 by The Board of Trustees of
29: ** Leland Stanford Junior University.
30: ** - Original license can be found in the Stanford.txt file.
31: **
32: */
33: /**
34: * request.c
35: *
36: * Functions for recieveing and processing IGMP requests.
37: *
38: */
39:
40: #include "igmpproxy.h"
41:
42: // Prototypes...
43: void sendGroupSpecificMemberQuery(void *argument);
44:
45: typedef struct {
46: uint32_t group;
47: uint32_t vifAddr;
48: short started;
49: } GroupVifDesc;
50:
51:
52: /**
53: * Handles incoming membership reports, and
54: * appends them to the routing table.
55: */
56: void acceptGroupReport(uint32_t src, uint32_t group, uint8_t type) {
57: struct IfDesc *sourceVif;
58:
59: // Sanitycheck the group adress...
60: if(!IN_MULTICAST( ntohl(group) )) {
61: my_log(LOG_WARNING, 0, "The group address %s is not a valid Multicast group.",
62: inetFmt(group, s1));
63: return;
64: }
65:
66: // Find the interface on which the report was recieved.
67: sourceVif = getIfByAddress( src );
68: if(sourceVif == NULL) {
69: my_log(LOG_WARNING, 0, "No interfaces found for source %s",
70: inetFmt(src,s1));
71: return;
72: }
73:
74: if(sourceVif->InAdr.s_addr == src) {
75: my_log(LOG_NOTICE, 0, "The IGMP message was from myself. Ignoring.");
76: return;
77: }
78:
79: // We have a IF so check that it's an downstream IF.
80: if(sourceVif->state == IF_STATE_DOWNSTREAM) {
81:
82: my_log(LOG_DEBUG, 0, "Should insert group %s (from: %s) to route table. Vif Ix : %d",
83: inetFmt(group,s1), inetFmt(src,s2), sourceVif->index);
84:
85: // The membership report was OK... Insert it into the route table..
86: insertRoute(group, sourceVif->index);
87:
88:
89: } else {
90: // Log the state of the interface the report was recieved on.
91: my_log(LOG_INFO, 0, "Mebership report was recieved on %s. Ignoring.",
92: sourceVif->state==IF_STATE_UPSTREAM?"the upstream interface":"a disabled interface");
93: }
94:
95: }
96:
97: /**
98: * Recieves and handles a group leave message.
99: */
100: void acceptLeaveMessage(uint32_t src, uint32_t group) {
101: struct IfDesc *sourceVif;
102:
103: my_log(LOG_DEBUG, 0,
104: "Got leave message from %s to %s. Starting last member detection.",
105: inetFmt(src, s1), inetFmt(group, s2));
106:
107: // Sanitycheck the group adress...
108: if(!IN_MULTICAST( ntohl(group) )) {
109: my_log(LOG_WARNING, 0, "The group address %s is not a valid Multicast group.",
110: inetFmt(group, s1));
111: return;
112: }
113:
114: // Find the interface on which the report was recieved.
115: sourceVif = getIfByAddress( src );
116: if(sourceVif == NULL) {
117: my_log(LOG_WARNING, 0, "No interfaces found for source %s",
118: inetFmt(src,s1));
119: return;
120: }
121:
122: // We have a IF so check that it's an downstream IF.
123: if(sourceVif->state == IF_STATE_DOWNSTREAM) {
124:
125: GroupVifDesc *gvDesc;
126: gvDesc = (GroupVifDesc*) malloc(sizeof(GroupVifDesc));
127:
128: // Tell the route table that we are checking for remaining members...
129: setRouteLastMemberMode(group);
130:
131: // Call the group spesific membership querier...
132: gvDesc->group = group;
133: gvDesc->vifAddr = sourceVif->InAdr.s_addr;
134: gvDesc->started = 0;
135:
136: sendGroupSpecificMemberQuery(gvDesc);
137:
138: } else {
139: // just ignore the leave request...
140: my_log(LOG_DEBUG, 0, "The found if for %s was not downstream. Ignoring leave request.", inetFmt(src, s1));
141: }
142: }
143:
144: /**
145: * Sends a group specific member report query until the
146: * group times out...
147: */
148: void sendGroupSpecificMemberQuery(void *argument) {
149: struct Config *conf = getCommonConfig();
150:
151: // Cast argument to correct type...
152: GroupVifDesc *gvDesc = (GroupVifDesc*) argument;
153:
154: if(gvDesc->started) {
155: // If aging returns false, we don't do any further action...
156: if(!lastMemberGroupAge(gvDesc->group)) {
157: return;
158: }
159: } else {
160: gvDesc->started = 1;
161: }
162:
163: // Send a group specific membership query...
164: sendIgmp(gvDesc->vifAddr, gvDesc->group,
165: IGMP_MEMBERSHIP_QUERY,
166: conf->lastMemberQueryInterval * IGMP_TIMER_SCALE,
167: gvDesc->group, 0);
168:
169: my_log(LOG_DEBUG, 0, "Sent membership query from %s to %s. Delay: %d",
170: inetFmt(gvDesc->vifAddr,s1), inetFmt(gvDesc->group,s2),
171: conf->lastMemberQueryInterval);
172:
173: // Set timeout for next round...
174: timer_setTimer(conf->lastMemberQueryInterval, sendGroupSpecificMemberQuery, gvDesc);
175:
176: }
177:
178:
179: /**
180: * Sends a general membership query on downstream VIFs
181: */
182: void sendGeneralMembershipQuery() {
183: struct Config *conf = getCommonConfig();
184: struct IfDesc *Dp;
185: int Ix;
186:
187: // Loop through all downstream vifs...
188: for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
189: if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
190: if(Dp->state == IF_STATE_DOWNSTREAM) {
191: // Send the membership query...
192: sendIgmp(Dp->InAdr.s_addr, allhosts_group,
193: IGMP_MEMBERSHIP_QUERY,
194: conf->queryResponseInterval * IGMP_TIMER_SCALE, 0, 0);
195:
196: my_log(LOG_DEBUG, 0,
197: "Sent membership query from %s to %s. Delay: %d",
198: inetFmt(Dp->InAdr.s_addr,s1),
199: inetFmt(allhosts_group,s2),
200: conf->queryResponseInterval);
201: }
202: }
203: }
204:
205: // Install timer for aging active routes.
206: timer_setTimer(conf->queryResponseInterval, ageActiveRoutes, NULL);
207:
208: // Install timer for next general query...
209: if(conf->startupQueryCount>0) {
210: // Use quick timer...
211: timer_setTimer(conf->startupQueryInterval, sendGeneralMembershipQuery, NULL);
212: // Decrease startup counter...
213: conf->startupQueryCount--;
214: }
215: else {
216: // Use slow timer...
217: timer_setTimer(conf->queryInterval, sendGeneralMembershipQuery, NULL);
218: }
219:
220:
221: }
222:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>