Annotation of embedaddon/igmpproxy/src/config.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: *   config.c - Contains functions to load and parse config
        !            35: *              file, and functions to configure the daemon.              
        !            36: */
        !            37: 
        !            38: #include "igmpproxy.h"
        !            39:                                       
        !            40: // Structure to keep configuration for VIFs...    
        !            41: struct vifconfig {
        !            42:     char*               name;
        !            43:     short               state;
        !            44:     int                 ratelimit;
        !            45:     int                 threshold;
        !            46: 
        !            47:     // Keep allowed nets for VIF.
        !            48:     struct SubnetList*  allowednets;
        !            49:     
        !            50:     // Next config in list...
        !            51:     struct vifconfig*   next;
        !            52: };
        !            53:                  
        !            54: // Structure to keep vif configuration
        !            55: struct vifconfig*   vifconf;
        !            56: 
        !            57: // Keeps common settings...
        !            58: static struct Config commonConfig;
        !            59: 
        !            60: // Prototypes...
        !            61: struct vifconfig *parsePhyintToken();
        !            62: struct SubnetList *parseSubnetAddress(char *addrstr);
        !            63: 
        !            64: 
        !            65: /**
        !            66: *   Initializes common config..
        !            67: */
        !            68: void initCommonConfig() {
        !            69:     commonConfig.robustnessValue = DEFAULT_ROBUSTNESS;
        !            70:     commonConfig.queryInterval = INTERVAL_QUERY;
        !            71:     commonConfig.queryResponseInterval = INTERVAL_QUERY_RESPONSE;
        !            72: 
        !            73:     // The defaults are calculated from other settings.
        !            74:     commonConfig.startupQueryInterval = (unsigned int)(INTERVAL_QUERY / 4);
        !            75:     commonConfig.startupQueryCount = DEFAULT_ROBUSTNESS;
        !            76: 
        !            77:     // Default values for leave intervals...
        !            78:     commonConfig.lastMemberQueryInterval = INTERVAL_QUERY_RESPONSE;
        !            79:     commonConfig.lastMemberQueryCount    = DEFAULT_ROBUSTNESS;
        !            80: 
        !            81:     // If 1, a leave message is sent upstream on leave messages from downstream.
        !            82:     commonConfig.fastUpstreamLeave = 0;
        !            83: 
        !            84: }
        !            85: 
        !            86: /**
        !            87: *   Returns a pointer to the common config...
        !            88: */
        !            89: struct Config *getCommonConfig() {
        !            90:     return &commonConfig;
        !            91: }
        !            92: 
        !            93: /**
        !            94: *   Loads the configuration from file, and stores the config in 
        !            95: *   respective holders...
        !            96: */                 
        !            97: int loadConfig(char *configFile) {
        !            98:     struct vifconfig  *tmpPtr;
        !            99:     struct vifconfig  **currPtr = &vifconf;
        !           100:     char *token;
        !           101:     
        !           102:     // Initialize common config
        !           103:     initCommonConfig();
        !           104: 
        !           105:     // Test config file reader...
        !           106:     if(!openConfigFile(configFile)) {
        !           107:         my_log(LOG_ERR, 0, "Unable to open configfile from %s", configFile);
        !           108:     }
        !           109: 
        !           110:     // Get first token...
        !           111:     token = nextConfigToken();
        !           112:     if(token == NULL) {
        !           113:         my_log(LOG_ERR, 0, "Config file was empty.");
        !           114:     }
        !           115: 
        !           116:     // Loop until all configuration is read.
        !           117:     while ( token != NULL ) {
        !           118:         // Check token...
        !           119:         if(strcmp("phyint", token)==0) {
        !           120:             // Got a phyint token... Call phyint parser
        !           121:             my_log(LOG_DEBUG, 0, "Config: Got a phyint token.");
        !           122:             tmpPtr = parsePhyintToken();
        !           123:             if(tmpPtr == NULL) {
        !           124:                 // Unparsable token... Exit...
        !           125:                 closeConfigFile();
        !           126:                 my_log(LOG_WARNING, 0, "Unknown token '%s' in configfile", token);
        !           127:                 return 0;
        !           128:             } else {
        !           129: 
        !           130:                 my_log(LOG_DEBUG, 0, "IF name : %s", tmpPtr->name);
        !           131:                 my_log(LOG_DEBUG, 0, "Next ptr : %x", tmpPtr->next);
        !           132:                 my_log(LOG_DEBUG, 0, "Ratelimit : %d", tmpPtr->ratelimit);
        !           133:                 my_log(LOG_DEBUG, 0, "Threshold : %d", tmpPtr->threshold);
        !           134:                 my_log(LOG_DEBUG, 0, "State : %d", tmpPtr->state);
        !           135:                 my_log(LOG_DEBUG, 0, "Allowednet ptr : %x", tmpPtr->allowednets);
        !           136: 
        !           137:                 // Insert config, and move temppointer to next location...
        !           138:                 *currPtr = tmpPtr;
        !           139:                 currPtr = &tmpPtr->next;
        !           140:             }
        !           141:         } 
        !           142:         else if(strcmp("quickleave", token)==0) {
        !           143:             // Got a quickleave token....
        !           144:             my_log(LOG_DEBUG, 0, "Config: Quick leave mode enabled.");
        !           145:             commonConfig.fastUpstreamLeave = 1;
        !           146:             
        !           147:             // Read next token...
        !           148:             token = nextConfigToken();
        !           149:             continue;
        !           150:         } else {
        !           151:             // Unparsable token... Exit...
        !           152:             closeConfigFile();
        !           153:             my_log(LOG_WARNING, 0, "Unknown token '%s' in configfile", token);
        !           154:             return 0;
        !           155:         }
        !           156:         // Get token that was not recognized by phyint parser.
        !           157:         token = getCurrentConfigToken();
        !           158:     }
        !           159: 
        !           160:     // Close the configfile...
        !           161:     closeConfigFile();
        !           162: 
        !           163:     return 1;
        !           164: }
        !           165: 
        !           166: /**
        !           167: *   Appends extra VIF configuration from config file.
        !           168: */
        !           169: void configureVifs() {
        !           170:     unsigned Ix;
        !           171:     struct IfDesc *Dp;
        !           172:     struct vifconfig *confPtr;
        !           173: 
        !           174:     // If no config is availible, just return...
        !           175:     if(vifconf == NULL) {
        !           176:         return;
        !           177:     }
        !           178: 
        !           179:     // Loop through all VIFs...
        !           180:     for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
        !           181:         if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
        !           182: 
        !           183:             // Now try to find a matching config...
        !           184:             for( confPtr = vifconf; confPtr; confPtr = confPtr->next) {
        !           185: 
        !           186:                 // I the VIF names match...
        !           187:                 if(strcmp(Dp->Name, confPtr->name)==0) {
        !           188:                     struct SubnetList *vifLast;
        !           189: 
        !           190:                     my_log(LOG_DEBUG, 0, "Found config for %s", Dp->Name);
        !           191: 
        !           192: 
        !           193:                     // Set the VIF state 
        !           194:                     Dp->state = confPtr->state;
        !           195:                     
        !           196:                     Dp->threshold = confPtr->threshold;
        !           197:                     Dp->ratelimit = confPtr->ratelimit;
        !           198: 
        !           199:                     // Go to last allowed net on VIF...
        !           200:                     for(vifLast = Dp->allowednets; vifLast->next; vifLast = vifLast->next);
        !           201:                         
        !           202:                     // Insert the configured nets...
        !           203:                     vifLast->next = confPtr->allowednets;
        !           204: 
        !           205:                     break;
        !           206:                 }
        !           207:             }
        !           208:         }
        !           209:     }
        !           210: }
        !           211: 
        !           212: 
        !           213: /**
        !           214: *   Internal function to parse phyint config
        !           215: */
        !           216: struct vifconfig *parsePhyintToken() {
        !           217:     struct vifconfig  *tmpPtr;
        !           218:     struct SubnetList **anetPtr;
        !           219:     char *token;
        !           220:     short parseError = 0;
        !           221: 
        !           222:     // First token should be the interface name....
        !           223:     token = nextConfigToken();
        !           224: 
        !           225:     // Sanitycheck the name...
        !           226:     if(token == NULL) return NULL;
        !           227:     if(strlen(token) >= IF_NAMESIZE) return NULL;
        !           228:     my_log(LOG_DEBUG, 0, "Config: IF: Config for interface %s.", token);
        !           229: 
        !           230:     // Allocate memory for configuration...
        !           231:     tmpPtr = (struct vifconfig*)malloc(sizeof(struct vifconfig));
        !           232:     if(tmpPtr == NULL) {
        !           233:         my_log(LOG_ERR, 0, "Out of memory.");
        !           234:     }
        !           235: 
        !           236:     // Set default values...
        !           237:     tmpPtr->next = NULL;    // Important to avoid seg fault...
        !           238:     tmpPtr->ratelimit = 0;
        !           239:     tmpPtr->threshold = 1;
        !           240:     tmpPtr->state = IF_STATE_DOWNSTREAM;
        !           241:     tmpPtr->allowednets = NULL;
        !           242: 
        !           243:     // Make a copy of the token to store the IF name
        !           244:     tmpPtr->name = strdup( token );
        !           245:     if(tmpPtr->name == NULL) {
        !           246:         my_log(LOG_ERR, 0, "Out of memory.");
        !           247:     }
        !           248: 
        !           249:     // Set the altnet pointer to the allowednets pointer.
        !           250:     anetPtr = &tmpPtr->allowednets;
        !           251: 
        !           252:     // Parse the rest of the config..
        !           253:     token = nextConfigToken();
        !           254:     while(token != NULL) {
        !           255:         if(strcmp("altnet", token)==0) {
        !           256:             // Altnet...
        !           257:             token = nextConfigToken();
        !           258:             my_log(LOG_DEBUG, 0, "Config: IF: Got altnet token %s.",token);
        !           259: 
        !           260:             *anetPtr = parseSubnetAddress(token);
        !           261:             if(*anetPtr == NULL) {
        !           262:                 parseError = 1;
        !           263:                 my_log(LOG_WARNING, 0, "Unable to parse subnet address.");
        !           264:                 break;
        !           265:             } else {
        !           266:                 anetPtr = &(*anetPtr)->next;
        !           267:             }
        !           268:         }
        !           269:         else if(strcmp("upstream", token)==0) {
        !           270:             // Upstream
        !           271:             my_log(LOG_DEBUG, 0, "Config: IF: Got upstream token.");
        !           272:             tmpPtr->state = IF_STATE_UPSTREAM;
        !           273:         }
        !           274:         else if(strcmp("downstream", token)==0) {
        !           275:             // Downstream
        !           276:             my_log(LOG_DEBUG, 0, "Config: IF: Got downstream token.");
        !           277:             tmpPtr->state = IF_STATE_DOWNSTREAM;
        !           278:         }
        !           279:         else if(strcmp("disabled", token)==0) {
        !           280:             // Disabled
        !           281:             my_log(LOG_DEBUG, 0, "Config: IF: Got disabled token.");
        !           282:             tmpPtr->state = IF_STATE_DISABLED;
        !           283:         }
        !           284:         else if(strcmp("ratelimit", token)==0) {
        !           285:             // Ratelimit
        !           286:             token = nextConfigToken();
        !           287:             my_log(LOG_DEBUG, 0, "Config: IF: Got ratelimit token '%s'.", token);
        !           288:             tmpPtr->ratelimit = atoi( token );
        !           289:             if(tmpPtr->ratelimit < 0) {
        !           290:                 my_log(LOG_WARNING, 0, "Ratelimit must be 0 or more.");
        !           291:                 parseError = 1;
        !           292:                 break;
        !           293:             }
        !           294:         }
        !           295:         else if(strcmp("threshold", token)==0) {
        !           296:             // Threshold
        !           297:             token = nextConfigToken();
        !           298:             my_log(LOG_DEBUG, 0, "Config: IF: Got threshold token '%s'.", token);
        !           299:             tmpPtr->threshold = atoi( token );
        !           300:             if(tmpPtr->threshold <= 0 || tmpPtr->threshold > 255) {
        !           301:                 my_log(LOG_WARNING, 0, "Threshold must be between 1 and 255.");
        !           302:                 parseError = 1;
        !           303:                 break;
        !           304:             }
        !           305:         }
        !           306:         else {
        !           307:             // Unknown token. Break...
        !           308:             break;
        !           309:         }
        !           310:         token = nextConfigToken();
        !           311:     }
        !           312: 
        !           313:     // Clean up after a parseerror...
        !           314:     if(parseError) {
        !           315:         free(tmpPtr);
        !           316:         tmpPtr = NULL;
        !           317:     }
        !           318: 
        !           319:     return tmpPtr;
        !           320: }
        !           321: 
        !           322: /**
        !           323: *   Parses a subnet address string on the format
        !           324: *   a.b.c.d/n into a SubnetList entry.
        !           325: */
        !           326: struct SubnetList *parseSubnetAddress(char *addrstr) {
        !           327:     struct SubnetList *tmpSubnet;
        !           328:     char        *tmpStr;
        !           329:     uint32_t      addr = 0x00000000;
        !           330:     uint32_t      mask = 0xFFFFFFFF;
        !           331: 
        !           332:     // First get the network part of the address...
        !           333:     tmpStr = strtok(addrstr, "/");
        !           334:     addr = inet_addr(tmpStr);
        !           335: 
        !           336:     tmpStr = strtok(NULL, "/");
        !           337:     if(tmpStr != NULL) {
        !           338:         int bitcnt = atoi(tmpStr);
        !           339:         if(bitcnt <= 0 || bitcnt > 32) {
        !           340:             my_log(LOG_WARNING, 0, "The bits part of the address is invalid : %d.",tmpStr);
        !           341:             return NULL;
        !           342:         }
        !           343: 
        !           344:         mask <<= (32 - bitcnt);
        !           345:     }
        !           346: 
        !           347:     if(addr == -1 || addr == 0) {
        !           348:         my_log(LOG_WARNING, 0, "Unable to parse address token '%s'.", addrstr);
        !           349:         return NULL;
        !           350:     }
        !           351: 
        !           352:     tmpSubnet = (struct SubnetList*) malloc(sizeof(struct SubnetList));
        !           353:     tmpSubnet->subnet_addr = addr;
        !           354:     tmpSubnet->subnet_mask = ntohl(mask);
        !           355:     tmpSubnet->next = NULL;
        !           356: 
        !           357:     my_log(LOG_DEBUG, 0, "Config: IF: Altnet: Parsed altnet to %s.",
        !           358:            inetFmts(tmpSubnet->subnet_addr, tmpSubnet->subnet_mask,s1));
        !           359: 
        !           360:     return tmpSubnet;
        !           361: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>