Annotation of embedaddon/igmpproxy/src/config.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: *   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>