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>