Annotation of embedaddon/igmpproxy/src/request.c, revision 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>