File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / igmpproxy / src / config.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: *   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>