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>