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>