File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / igmpproxy / src / request.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:00:29 2012 UTC (12 years, 4 months ago) by misho
Branches: igmpproxy, MAIN
CVS tags: v0_1p0, v0_1, HEAD
igmpproxy

    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>