Original linux-igd sources from CVS repo:
[igd2-for-linux:wanipconnection2.git] / linuxigd2 / config.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <regex.h>
5 #include <sys/stat.h>
6 #include "globals.h"
7
8 #define NMATCH 3
9
10 int getConfigOptionArgument(char var[],int varlen, char line[], regmatch_t *submatch) 
11 {
12     /* limit buffer operations to varlen - 1 */
13     int match_length = min(submatch[1].rm_eo-submatch[1].rm_so, varlen - 1);
14
15     strncpy(var,&line[submatch[1].rm_so],match_length);
16     // Make sure var[] is null terminated
17     var[match_length] = '\0';
18     return 0;
19 }
20
21 int getConfigOptionDuration(long int *duration,char line[], regmatch_t *submatch) 
22 {
23   long int dur;
24   int absolute_time = submatch[1].rm_eo-submatch[1].rm_so; // >0 if @ was present
25   char num[NUM_LEN];
26   char *p;
27
28   /* limit buffer operations to NUM_LEN - 1 */
29   unsigned int len = min(submatch[2].rm_eo-submatch[2].rm_so, NUM_LEN - 1);
30
31   strncpy(num, &line[submatch[2].rm_so], len);
32   num[len] = '\0';
33   if ((p=index(num,':'))==NULL) {
34     dur = atol(num);
35   }
36   else {
37     *p++ = '\0';
38     dur = atol(num)*3600 + atol(p)*60;
39   }
40   if (absolute_time)
41     dur *= -1;
42   *duration = dur;
43   return 0;
44 }
45
46 int parseConfigFile(globals_p vars)
47 {
48     FILE *conf_file;
49     regmatch_t submatch[NMATCH]; // Stores the regex submatch start and end index
50     
51     regex_t re_comment;
52     regex_t re_empty_row;
53     regex_t re_iptables_location;
54     regex_t re_debug_mode;
55     regex_t re_create_forward_rules;
56     regex_t re_forward_rules_append;
57     regex_t re_forward_chain_name;
58     regex_t re_prerouting_chain_name;
59     regex_t re_upstream_bitrate;
60     regex_t re_downstream_bitrate;
61     regex_t re_duration;
62     regex_t re_desc_doc;
63     regex_t re_xml_path;
64     regex_t re_listenport;
65
66     // Make sure all vars are 0 or \0 terminated
67     vars->debug = 0;
68     vars->createForwardRules = 0;
69     vars->forwardRulesAppend = 0;
70     strcpy(vars->iptables,"");
71     strcpy(vars->forwardChainName,"");
72     strcpy(vars->preroutingChainName,"");
73     strcpy(vars->upstreamBitrate,"");
74     strcpy(vars->downstreamBitrate,"");
75     vars->duration = DEFAULT_DURATION;
76     strcpy(vars->descDocName,"");
77     strcpy(vars->xmlPath,"");
78     vars->listenport = 0;
79
80     // Regexp to match a comment line
81     regcomp(&re_comment,"^[[:blank:]]*#",0);
82     regcomp(&re_empty_row,"^[[:blank:]]*\r?\n$",REG_EXTENDED);
83
84     // Regexps to match configuration file settings
85     regcomp(&re_iptables_location,"iptables_location[[:blank:]]*=[[:blank:]]*\"([^\"]+)\"",REG_EXTENDED);
86     regcomp(&re_debug_mode,"debug_mode[[:blank:]]*=[[:blank:]]*([[:digit:]])",REG_EXTENDED);
87     regcomp(&re_forward_chain_name,"forward_chain_name[[:blank:]]*=[[:blank:]]*([[:alpha:]_-]+)",REG_EXTENDED);
88     regcomp(&re_prerouting_chain_name,"prerouting_chain_name[[:blank:]]*=[[:blank:]]([[:alpha:]_-]+)",REG_EXTENDED);
89     regcomp(&re_create_forward_rules,"create_forward_rules[[:blank:]]*=[[:blank:]]*(yes|no)",REG_EXTENDED);
90     regcomp(&re_forward_rules_append,"forward_rules_append[[:blank:]]*=[[:blank:]]*(yes|no)",REG_EXTENDED);
91     regcomp(&re_upstream_bitrate,"upstream_bitrate[[:blank:]]*=[[:blank:]]*([[:digit:]]+)",REG_EXTENDED);
92     regcomp(&re_downstream_bitrate,"downstream_bitrate[[:blank:]]*=[[:blank:]]*([[:digit:]]+)",REG_EXTENDED);
93     regcomp(&re_duration,"duration[[:blank:]]*=[[:blank:]]*(@?)([[:digit:]]+|[[:digit:]]{2,}:[[:digit:]]{2})",REG_EXTENDED);
94     regcomp(&re_desc_doc,"description_document_name[[:blank:]]*=[[:blank:]]*([[:alpha:].]{1,20})",REG_EXTENDED);
95     regcomp(&re_xml_path,"xml_document_path[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
96     regcomp(&re_listenport,"listenport[[:blank:]]*=[[:blank:]]*([[:digit:]]+)",REG_EXTENDED);
97
98     if ((conf_file=fopen(CONF_FILE,"r")) != NULL)
99     {
100         char line[MAX_CONFIG_LINE];
101         // Walk through the config file line by line
102         while(fgets(line,MAX_CONFIG_LINE,conf_file) != NULL)
103         {
104             // Check if a comment line or an empty one
105             if ( (0 != regexec(&re_comment,line,0,NULL,0)  )  && 
106                  (0 != regexec(&re_empty_row,line,0,NULL,0))  )
107             {
108                 // Chec if iptables_location
109                 if (regexec(&re_iptables_location,line,NMATCH,submatch,0) == 0)
110                 {
111                   getConfigOptionArgument(vars->iptables, PATH_LEN, line, submatch);
112                 }
113                 // Check if create_forward_rules
114                 else if (regexec(&re_create_forward_rules,line,NMATCH,submatch,0) == 0)
115                 {
116                   char tmp[4];
117                   getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
118                   vars->createForwardRules = strcmp(tmp,"yes")==0 ? 1 : 0;
119                 }
120                 // Check if forward_rules_append
121                 else if (regexec(&re_forward_rules_append,line,NMATCH,submatch,0) == 0)
122                 {
123                   char tmp[4];
124                   getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
125                   vars->forwardRulesAppend = strcmp(tmp,"yes")==0 ? 1 : 0;
126                 }
127                 // Check forward_chain_name
128                 else if (regexec(&re_forward_chain_name,line,NMATCH,submatch,0) == 0)
129                 {
130                   getConfigOptionArgument(vars->forwardChainName, CHAIN_NAME_LEN, line, submatch);
131                 }
132                 else if (regexec(&re_debug_mode,line,NMATCH,submatch,0) == 0)
133                 {
134                   char tmp[2];
135                   getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
136                   vars->debug = atoi(tmp);
137                 }
138                 else if (regexec(&re_prerouting_chain_name,line,NMATCH,submatch,0) == 0)
139                 {
140                   getConfigOptionArgument(vars->preroutingChainName, CHAIN_NAME_LEN, line, submatch);
141                 }
142                 else if (regexec(&re_upstream_bitrate,line,NMATCH,submatch,0) == 0)
143                 {
144                   getConfigOptionArgument(vars->upstreamBitrate, BITRATE_LEN, line, submatch);
145                 }
146                 else if (regexec(&re_downstream_bitrate,line,NMATCH,submatch,0) == 0)
147                 {
148                   getConfigOptionArgument(vars->downstreamBitrate, BITRATE_LEN, line, submatch);
149                 }
150                 else if (regexec(&re_duration,line,NMATCH,submatch,0) == 0)
151                 {
152                   getConfigOptionDuration(&vars->duration,line,submatch);
153                 }
154                 else if (regexec(&re_desc_doc,line,NMATCH,submatch,0) == 0)
155                 {
156                   getConfigOptionArgument(vars->descDocName, PATH_LEN, line, submatch);
157                 }
158                 else if (regexec(&re_xml_path,line,NMATCH,submatch,0) == 0)
159                 {
160                   getConfigOptionArgument(vars->xmlPath, PATH_LEN, line, submatch);
161                 }
162                 else if (regexec(&re_listenport,line,NMATCH,submatch,0) == 0)
163                 {
164                   char tmp[6];
165                   getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
166                   vars->listenport = atoi(tmp);
167                 }
168                 else
169                 {
170                     // We end up here if ther is an unknown config directive
171                     printf("Unknown config line: %s",line);
172                 }
173             }
174         }
175         fclose(conf_file);
176     }
177     regfree(&re_comment);
178     regfree(&re_empty_row);
179     regfree(&re_iptables_location);
180     regfree(&re_debug_mode);    
181     regfree(&re_create_forward_rules);  
182     regfree(&re_forward_rules_append);  
183     regfree(&re_forward_chain_name);
184     regfree(&re_prerouting_chain_name);
185     regfree(&re_upstream_bitrate);
186     regfree(&re_downstream_bitrate);
187     regfree(&re_duration);
188     regfree(&re_desc_doc);
189     regfree(&re_xml_path);
190     regfree(&re_listenport);
191     // Set default values for options not found in config file
192     if (strnlen(vars->forwardChainName, CHAIN_NAME_LEN) == 0)
193     {
194         // No forward chain name was set in conf file, set it to default
195         snprintf(vars->forwardChainName, CHAIN_NAME_LEN, IPTABLES_DEFAULT_FORWARD_CHAIN);
196     }
197     if (strnlen(vars->preroutingChainName, CHAIN_NAME_LEN) == 0)
198     {
199         // No prerouting chain name was set in conf file, set it to default
200         snprintf(vars->preroutingChainName, CHAIN_NAME_LEN, IPTABLES_DEFAULT_PREROUTING_CHAIN);
201     }
202     if (strnlen(vars->upstreamBitrate, BITRATE_LEN) == 0)
203     {
204         // No upstream_bitrate was found in the conf file, set it to default
205         snprintf(vars->upstreamBitrate, BITRATE_LEN, DEFAULT_UPSTREAM_BITRATE);
206     }
207     if (strnlen(vars->downstreamBitrate, BITRATE_LEN) == 0)
208     {
209         // No downstream bitrate was found in the conf file, set it to default
210         snprintf(vars->downstreamBitrate, BITRATE_LEN, DEFAULT_DOWNSTREAM_BITRATE);
211     }
212     if (strnlen(vars->descDocName, PATH_LEN) == 0)
213     {
214         snprintf(vars->descDocName, PATH_LEN, DESC_DOC_DEFAULT);
215     }
216     if (strnlen(vars->xmlPath, PATH_LEN) == 0)
217     {
218         snprintf(vars->xmlPath, PATH_LEN, XML_PATH_DEFAULT);
219     }
220     if (strnlen(vars->iptables, PATH_LEN) == 0) {
221         // Can't find the iptables executable, return -1 to 
222         // indicate en error
223         return -1;
224     }
225     else
226     {
227         return 0;
228     }
229 }