don't fail with error in message parser with unknown config option (part 1)
[olsrd.git] / src / olsr_cfg.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #include "olsr_cfg.h"
43
44 #include "olsr.h"
45 #include "ipcalc.h"
46 #include "parser.h"
47 #include "net_olsr.h"
48 #include "ifnet.h"
49
50 #include <unistd.h>
51 #include <string.h>
52 #include <sys/types.h>
53 #include <sys/socket.h>
54 #include <arpa/inet.h>
55 #include <getopt.h>
56 #include <errno.h>
57
58 #ifdef WIN32
59 void ListInterfaces(void);
60 #endif
61
62 #ifdef DEBUG
63 #define PARSER_DEBUG_PRINTF(x, args...)   printf(x, ##args)
64 #else
65 #define PARSER_DEBUG_PRINTF(x, ...)   do { } while (0)
66 #endif
67
68 static char* olsr_strdup(const char *s);
69 static char* olsr_strndup(const char *s, size_t n);
70 static char** olsr_strtok(const char *s, const char **snext);
71 static void olsr_strtok_free(char **s);
72 static int read_config (const char *filename, int *pargc, char ***pargv);
73 static struct if_config_options *olsr_get_default_if_config(void);
74
75 struct olsrd_config *
76 olsr_parse_cnf(int argc, char* argv[], const char *conf_file_name)
77 {
78   int opt;
79   int opt_idx = 0;
80   char *opt_str = 0;
81   int opt_argc = 0;
82   char **opt_argv = olsr_malloc(argc * sizeof(argv[0]), "argv");
83 #ifdef DEBUG
84   struct ipaddr_str buf;
85 #endif
86
87   /*
88    * Original cmd line params
89    *
90    * -bcast                   (removed)
91    * -delgw                   (-> --delgw)
92    * -dispin                  (-> --dispin)
93    * -dispout                 (-> --dispout)
94    * -d (level)               (preserved)
95    * -f (config)              (preserved)
96    * -hemu (queue_if(hcif01)) (-> --hemu)
97    * -hint                    (removed)
98    * -hnaint                  (removed)
99    * -i iface iface iface     (see comment below)
100    * -int (win32)             (preserved)
101    * -ipc (ipc conn = 1)      (-> --ipc)
102    * -ipv6                    (-> -V or --IpVersion)
103    * -lqa (lq aging)          (removed)
104    * -lql (lq lev)            (removed)
105    * -lqnt (lq nat)           (removed)
106    * -midint                  (removed)
107    * -multi (ipv6 mcast)      (removed)
108    * -nofork                  (preserved)
109    * -tcint                   (removed)
110    * -T (pollrate)            (preserved)
111    *
112    * Note: Remaining args are interpreted as list of
113    * interfaces. Because "-i*" lists interfaces, all
114    * following non-minus args are processed as ifaces
115    * under win32 which is compatible with switch.exe
116    */
117
118   static struct option long_options[] = {
119     {"config",                   required_argument, 0, 'f'}, /* (filename) */
120     {"delgw",                    no_argument,       0, 'D'},
121     {"dispin",                   no_argument,       0, 'X'},
122     {"dispout",                  no_argument,       0, 'O'},
123     {"help",                     no_argument,       0, 'h'},
124     {"hemu",                     required_argument, 0, 'H'}, /* (ip4) */
125 #ifdef WIN32
126     {"int",                      no_argument,       0, 'i'},
127 #endif
128     {"ipc",                      no_argument,       0, 'P'},
129     {"nofork",                   no_argument,       0, 'n'},
130     {"version",                  no_argument,       0, 'v'},
131     {"AllowNoInt",               required_argument, 0, 'A'}, /* (yes/no) */
132     {"ClearScreen",              required_argument, 0, 'C'}, /* (yes/no) */
133     {"DebugLevel",               required_argument, 0, 'd'}, /* (i) */
134     {"FIBMetric",                required_argument, 0, 'F'}, /* (str) */
135     {"Hna4",                     required_argument, 0, '4'}, /* (4body) */
136     {"Hna6",                     required_argument, 0, '6'}, /* (6body) */
137     {"Interface",                required_argument, 0, 'I'}, /* (if1 if2 {ifbody}) */
138     {"IpcConnect",               required_argument, 0, 'Q'}, /* (Host,Net,MaxConnections) */
139     {"IpVersion",                required_argument, 0, 'V'}, /* (i) */
140     {"LinkQualityAging",         required_argument, 0, 'a'}, /* (f) */
141     {"LinkQualityAlgorithm",     required_argument, 0, 'l'}, /* (str) */
142     {"LinkQualityDijkstraLimit", required_argument, 0, 'J'}, /* (i,f) */
143     {"LinkQualityFishEye",       required_argument, 0, 'E'}, /* (i) */
144     {"LinkQualityWinSize",       required_argument, 0, 'W'}, /* (i) */
145     {"LoadPlugin",               required_argument, 0, 'p'}, /* (soname {PlParams}) */
146     {"MprCoverage",              required_argument, 0, 'M'}, /* (i) */
147     {"NatThreshold",             required_argument, 0, 'N'}, /* (f) */
148     {"NicChgsPollInt",           required_argument, 0, 'Y'}, /* (f) */
149     {"Pollrate",                 required_argument, 0, 'T'}, /* (f) */
150     {"RtProto",                  required_argument, 0, 'q'}, /* (i) */
151     {"RtTableDefault",           required_argument, 0, 'R'}, /* (i) */
152     {"RtTable",                  required_argument, 0, 'r'}, /* (i) */
153     {"TcRedundancy",             required_argument, 0, 't'}, /* (i) */
154     {"TosValue",                 required_argument, 0, 'Z'}, /* (i) */
155     {"Willingness",              required_argument, 0, 'w'}, /* (i) */
156     {0, 0, 0, 0}
157   }, *popt = long_options;
158
159   /* Copy argv array for safe free'ing later on */
160   while(opt_argc < argc) {
161     const char* p = argv[opt_argc];
162     if (0 == strcmp(p, "-int"))
163       p = "-i";
164     else if (0 == strcmp(p, "-nofork"))
165       p = "-n";
166     opt_argv[opt_argc] = olsr_strdup(p);
167     opt_argc++;
168   }
169
170   /* get option count */
171   for (opt_idx = 0; long_options[opt_idx].name; opt_idx++);
172
173   /* Calculate short option string */
174   opt_str = olsr_malloc(opt_idx * 3, "create short opt_string");
175   opt_idx = 0;
176   while (popt->name != NULL && popt->val != 0)
177   {
178     opt_str[opt_idx++] = popt->val;
179
180     switch (popt->has_arg)
181     {
182       case optional_argument:
183         opt_str[opt_idx++] = ':';
184         /* Fall through */
185       case required_argument:
186         opt_str[opt_idx++] = ':';
187         break;
188     }
189     popt++;
190   }
191
192   /* If no arguments, revert to default behaviour */
193   if (1 == opt_argc) {
194     char* argv0_tmp = opt_argv[0];
195     free(opt_argv);
196     opt_argv = olsr_malloc(3 * sizeof(opt_argv[0]), "default argv");
197     opt_argv[0] = argv0_tmp;
198     opt_argv[1] = olsr_strdup("-f");
199     opt_argv[2] = olsr_strdup(conf_file_name);
200     opt_argc = 3;
201   }
202
203   olsr_cnf = olsr_get_default_cnf();
204
205   while (0 <= (opt = getopt_long (opt_argc, opt_argv, opt_str, long_options, &opt_idx))) {
206     char **tok;
207     const char *optarg_next;
208
209     switch(opt)
210     {
211     case 'f':                  /* config (filename) */
212       PARSER_DEBUG_PRINTF("Read config from %s\n", optarg);
213       if (0 > read_config (optarg, &opt_argc, &opt_argv)) {
214         fprintf(stderr, "Could not find specified config file %s!\n%s\n\n", optarg, strerror(errno));
215         exit(EXIT_FAILURE);
216       }
217       break;
218     case 'D':                  /* delgw */
219       olsr_cnf->del_gws = true;
220       PARSER_DEBUG_PRINTF("del_gws set to %d\n", olsr_cnf->del_gws);
221       break;
222     case 'X':                  /* dispin */
223       PARSER_DEBUG_PRINTF("Calling parser_set_disp_pack_in(true)\n");
224       parser_set_disp_pack_in(true);
225       break;
226     case 'O':                  /* dispout */
227       PARSER_DEBUG_PRINTF("Calling net_set_disp_pack_out(true)\n");
228       net_set_disp_pack_out(true);
229       break;
230     case 'h':                  /* help */
231       popt = long_options;
232       printf ("Usage: olsrd [OPTIONS]... [ifaces]...\n");
233       while (popt->name)
234       {
235         if (popt->val)
236           printf ("-%c or ", popt->val);
237         else
238           printf ("       ");
239         printf ("--%s ", popt->name);
240         switch (popt->has_arg)
241         {
242         case required_argument:
243           printf ("arg");
244           break;
245         case optional_argument:
246           printf ("[arg]");
247           break;
248         }
249         printf ("\n");
250         popt++;
251       }
252       exit(0);
253     case 'H':                  /* hemu (ip4) */
254       {
255         union olsr_ip_addr ipaddr;
256         struct olsr_if *ifa;
257
258         if (inet_pton(AF_INET, optarg, &ipaddr) <= 0) {
259           fprintf(stderr, "Failed converting IP address %s\n", optarg);
260           exit(EXIT_FAILURE);
261         }
262
263         /* Add hemu interface */
264         if (NULL != (ifa = queue_if("hcif01", true))) {
265           ifa->cnf = olsr_get_default_if_config();
266           ifa->host_emul = true;
267           ifa->hemu_ip = ipaddr;
268           olsr_cnf->host_emul = true;
269           PARSER_DEBUG_PRINTF("host_emul with %s\n", olsr_ip_to_string(&buf, &ifa->hemu_ip));
270         }
271         PARSER_DEBUG_PRINTF("host_emul set to %d\n", olsr_cnf->host_emul);
272       }
273       break;
274 #ifdef WIN32
275     case 'i':                  /* int */
276       ListInterfaces();
277       exit(0);
278 #endif
279     case 'P':                  /* ipc */
280       olsr_cnf->ipc_connections = 1;
281       PARSER_DEBUG_PRINTF("IPC connections: %d\n", olsr_cnf->ipc_connections);
282       break;
283     case 'n':                  /* nofork */
284       olsr_cnf->no_fork = true;
285       PARSER_DEBUG_PRINTF("no_fork set to %d\n", olsr_cnf->no_fork);
286       break;
287     case 'v':                  /* version */
288       /* Version string already printed */
289       exit(0);
290     case 'A':                  /* AllowNoInt (yes/no) */
291       olsr_cnf->allow_no_interfaces =  (0 == strcmp("yes", optarg));
292       PARSER_DEBUG_PRINTF("Noint set to %d\n", olsr_cnf->allow_no_interfaces);
293       break;
294     case 'C':                  /* ClearScreen (yes/no) */
295       olsr_cnf->clear_screen = (0 == strcmp("yes", optarg));
296       PARSER_DEBUG_PRINTF("Clear screen %s\n", olsr_cnf->clear_screen ? "enabled" : "disabled");
297       break;
298     case 'd':                  /* DebugLevel (i) */
299       {
300         int arg = -1;
301         sscanf(optarg, "%d", &arg);
302         if (0 <= arg && arg < 128)
303           olsr_cnf->debug_level = arg;
304         PARSER_DEBUG_PRINTF("Debug level: %d\n", olsr_cnf->debug_level);
305       }
306       break;
307     case 'F':                  /* FIBMetric (str) */
308       if (NULL != (tok = olsr_strtok(optarg, NULL)))
309       {
310         if (strcmp(*tok, CFG_FIBM_FLAT) == 0) {
311             olsr_cnf->fib_metric = FIBM_FLAT;
312         } else if (strcmp(*tok, CFG_FIBM_CORRECT) == 0) {
313             olsr_cnf->fib_metric = FIBM_CORRECT;
314         } else if (strcmp(*tok, CFG_FIBM_APPROX) == 0) {
315             olsr_cnf->fib_metric = FIBM_APPROX;
316         } else {
317           fprintf(stderr, "FIBMetric must be \"%s\", \"%s\", or \"%s\"!\n", CFG_FIBM_FLAT, CFG_FIBM_CORRECT, CFG_FIBM_APPROX);
318           exit(EXIT_FAILURE);
319         }
320         olsr_strtok_free(tok);
321       }
322       else {
323         fprintf(stderr, "Error in %s\n", optarg);
324         exit(EXIT_FAILURE);
325       }
326       PARSER_DEBUG_PRINTF("FIBMetric: %d=%s\n", olsr_cnf->fib_metric, optarg);
327       break;
328     case '4':                  /* Hna4 (4body) */
329       if ('{' != *optarg) {
330         fprintf(stderr, "No {}\n");
331         exit(EXIT_FAILURE);
332       }
333       else if (NULL != (tok = olsr_strtok(optarg + 1, NULL))) {
334         char **p = tok;
335         if (AF_INET != olsr_cnf->ip_version) {
336           fprintf(stderr, "IPv4 addresses can only be used if \"IpVersion\" == 4\n");
337           exit(EXIT_FAILURE);
338         }
339         while(p[0]) {
340           union olsr_ip_addr ipaddr, netmask;
341           if (!p[1]) {
342             fprintf(stderr, "Odd args in %s\n", optarg);
343             exit(EXIT_FAILURE);
344           }
345           if (inet_pton(AF_INET, p[0], &ipaddr) <= 0) {
346             fprintf(stderr, "Failed converting IP address %s\n", p[0]);
347             exit(EXIT_FAILURE);
348           }
349           if (inet_pton(AF_INET, p[1], &netmask) <= 0) {
350             fprintf(stderr, "Failed converting IP address %s\n", p[1]);
351             exit(EXIT_FAILURE);
352           }
353           if ((ipaddr.v4.s_addr & ~netmask.v4.s_addr) != 0) {
354             fprintf(stderr, "The IP address %s/%s is not a network address!\n", p[0], p[1]);
355             exit(EXIT_FAILURE);
356           }
357           ip_prefix_list_add(&olsr_cnf->hna_entries, &ipaddr, olsr_netmask_to_prefix(&netmask));
358           PARSER_DEBUG_PRINTF("Hna4 %s/%d\n", olsr_ip_to_string(&buf, &ipaddr), olsr_netmask_to_prefix(&netmask));
359           p += 2;
360         }
361         olsr_strtok_free(tok);
362       }
363       break;
364     case '6':                  /* Hna6 (6body) */
365       if ('{' != *optarg) {
366         fprintf(stderr, "No {}\n");
367         exit(EXIT_FAILURE);
368       }
369       else if (NULL != (tok = olsr_strtok(optarg + 1, NULL))) {
370         char **p = tok;
371         if (AF_INET6 != olsr_cnf->ip_version) {
372           fprintf(stderr, "IPv6 addresses can only be used if \"IpVersion\" == 6\n");
373           exit(EXIT_FAILURE);
374         }
375         while(p[0]) {
376           int prefix = -1;
377           union olsr_ip_addr ipaddr;
378           if (!p[1]) {
379             fprintf(stderr, "Odd args in %s\n", optarg);
380             exit(EXIT_FAILURE);
381           }
382           if (inet_pton(AF_INET6, p[0], &ipaddr) <= 0) {
383             fprintf(stderr, "Failed converting IP address %s\n", p[0]);
384             exit(EXIT_FAILURE);
385           }
386           sscanf('/' == *p[1] ? p[1] + 1 : p[1], "%d", &prefix);
387           if (0 > prefix || 128 < prefix) {
388             fprintf(stderr, "Illegal IPv6 prefix %s\n", p[1]);
389             exit(EXIT_FAILURE);
390           }
391           ip_prefix_list_add(&olsr_cnf->hna_entries, &ipaddr, prefix);
392           PARSER_DEBUG_PRINTF("Hna6 %s/%d\n", olsr_ip_to_string(&buf, &ipaddr), prefix);
393           p += 2;
394         }
395         olsr_strtok_free(tok);
396       }
397       break;
398     case 'I':                  /* Interface if1 if2 { ifbody } */
399       if (NULL != (tok = olsr_strtok(optarg, &optarg_next))) {
400         if ('{' != *optarg_next) {
401           fprintf(stderr, "No {}\n");
402           exit(EXIT_FAILURE);
403         }
404         else {
405           char **tok_next = olsr_strtok(optarg_next + 1, NULL);
406           char **p = tok;
407           while(p[0]) {
408             char **p_next = tok_next;
409             struct olsr_if *ifs = olsr_malloc(sizeof(*ifs), "new if");
410             ifs->cnf = olsr_get_default_if_config();
411             ifs->name = olsr_strdup(p[0]);
412             ifs->next = olsr_cnf->interfaces;
413             olsr_cnf->interfaces = ifs;
414             PARSER_DEBUG_PRINTF("Interface %s\n", ifs->name);
415             while(p_next[0]) {
416               if (!p_next[1]) {
417                 fprintf(stderr, "Odd args in %s\n", optarg_next);
418                 exit(EXIT_FAILURE);
419               }
420               if (0 == strcmp("AutoDetectChanges", p_next[0])) {
421                 ifs->cnf->autodetect_chg =  (0 == strcmp("yes", p_next[1]));
422                 PARSER_DEBUG_PRINTF("\tAutodetect changes: %d\n", ifs->cnf->autodetect_chg);
423               }
424               else if (0 == strcmp("Ip4Broadcast", p_next[0])) {
425                 union olsr_ip_addr ipaddr;
426                 if (inet_pton(AF_INET, p_next[1], &ipaddr) <= 0) {
427                   fprintf(stderr, "Failed converting IP address %s\n", p_next[1]);
428                   exit(EXIT_FAILURE);
429                 }
430                 ifs->cnf->ipv4_broadcast = ipaddr;
431                 PARSER_DEBUG_PRINTF("\tIPv4 broadcast: %s\n", ip4_to_string(&buf, ifs->cnf->ipv4_broadcast.v4));
432               }
433               else if (0 == strcmp("Ip6AddrType", p_next[0])) {
434                 if (0 == strcmp("site-local", p_next[1])) {
435                   ifs->cnf->ipv6_addrtype = OLSR_IP6T_SITELOCAL;
436                 }
437                 else if (0 == strcmp("unique-local", p_next[1])) {
438                   ifs->cnf->ipv6_addrtype = OLSR_IP6T_UNIQUELOCAL;
439                 }
440                 else if (0 == strcmp("global", p_next[1])) {
441                   ifs->cnf->ipv6_addrtype = OLSR_IP6T_GLOBAL;
442                 }
443                 else {
444                   ifs->cnf->ipv6_addrtype = OLSR_IP6T_AUTO;
445                 }
446                 PARSER_DEBUG_PRINTF("\tIPv6 addrtype: %d\n", ifs->cnf->ipv6_addrtype);
447               }
448               else if (0 == strcmp("Ip6MulticastSite", p_next[0])) {
449                 union olsr_ip_addr ipaddr;
450                 if (inet_pton(AF_INET6, p_next[1], &ipaddr) <= 0) {
451                   fprintf(stderr, "Failed converting IP address %s\n", p_next[1]);
452                   exit(EXIT_FAILURE);
453                 }
454                 ifs->cnf->ipv6_multi_site = ipaddr;
455                 PARSER_DEBUG_PRINTF("\tIPv6 site-local multicast: %s\n", ip6_to_string(&buf, &ifs->cnf->ipv6_multi_site.v6));
456               }
457               else if (0 == strcmp("Ip6MulticastGlobal", p_next[0])) {
458                 union olsr_ip_addr ipaddr;
459                 if (inet_pton(AF_INET6, p_next[1], &ipaddr) <= 0) {
460                   fprintf(stderr, "Failed converting IP address %s\n", p_next[1]);
461                   exit(EXIT_FAILURE);
462                 }
463                 ifs->cnf->ipv6_multi_glbl = ipaddr;
464                 PARSER_DEBUG_PRINTF("\tIPv6 global multicast: %s\n", ip6_to_string(&buf, &ifs->cnf->ipv6_multi_glbl.v6));
465               }
466               else if (0 == strcmp("HelloInterval", p_next[0])) {
467                 ifs->cnf->hello_params.emission_interval = 0;
468                 sscanf(p_next[1], "%f", &ifs->cnf->hello_params.emission_interval);
469                 PARSER_DEBUG_PRINTF("\tHELLO interval: %0.2f\n", ifs->cnf->hello_params.emission_interval);
470               }
471               else if (0 == strcmp("HelloValidityTime", p_next[0])) {
472                 ifs->cnf->hello_params.validity_time = 0;
473                 sscanf(p_next[1], "%f", &ifs->cnf->hello_params.validity_time);
474                 PARSER_DEBUG_PRINTF("\tHELLO validity: %0.2f\n", ifs->cnf->hello_params.validity_time);
475               }
476               else if (0 == strcmp("TcInterval", p_next[0])) {
477                 ifs->cnf->tc_params.emission_interval = 0;
478                 sscanf(p_next[1], "%f", &ifs->cnf->tc_params.emission_interval);
479                 PARSER_DEBUG_PRINTF("\tTC interval: %0.2f\n", ifs->cnf->tc_params.emission_interval);
480               }
481               else if (0 == strcmp("TcValidityTime", p_next[0])) {
482                 ifs->cnf->tc_params.validity_time = 0;
483                 sscanf(p_next[1], "%f", &ifs->cnf->tc_params.validity_time);
484                 PARSER_DEBUG_PRINTF("\tTC validity: %0.2f\n", ifs->cnf->tc_params.validity_time);
485               }
486               else if (0 == strcmp("MidInterval", p_next[0])) {
487                 ifs->cnf->mid_params.emission_interval = 0;
488                 sscanf(p_next[1], "%f", &ifs->cnf->mid_params.emission_interval);
489                 PARSER_DEBUG_PRINTF("\tMID interval: %0.2f\n", ifs->cnf->mid_params.emission_interval);
490               }
491               else if (0 == strcmp("MidValidityTime", p_next[0])) {
492                 ifs->cnf->mid_params.validity_time = 0;
493                 sscanf(p_next[1], "%f", &ifs->cnf->mid_params.validity_time);
494                 PARSER_DEBUG_PRINTF("\tMID validity: %0.2f\n", ifs->cnf->mid_params.validity_time);
495               }
496               else if (0 == strcmp("HnaInterval", p_next[0])) {
497                 ifs->cnf->hna_params.emission_interval = 0;
498                 sscanf(p_next[1], "%f", &ifs->cnf->hna_params.emission_interval);
499                 PARSER_DEBUG_PRINTF("\tHNA interval: %0.2f\n", ifs->cnf->hna_params.emission_interval);
500               }
501               else if (0 == strcmp("HnaValidityTime", p_next[0])) {
502                 ifs->cnf->hna_params.validity_time = 0;
503                 sscanf(p_next[1], "%f", &ifs->cnf->hna_params.validity_time);
504                 PARSER_DEBUG_PRINTF("\tHNA validity: %0.2f\n", ifs->cnf->hna_params.validity_time);
505               }
506               else if (0 == strcmp("Weight", p_next[0])) {
507                 ifs->cnf->weight.fixed = true;
508                 PARSER_DEBUG_PRINTF("\tFixed willingness: %d\n", ifs->cnf->weight.value);
509               }
510               else if (0 == strcmp("LinkQualityMult", p_next[0])) {
511                 float f;
512                 struct olsr_lq_mult *mult = olsr_malloc(sizeof(*mult), "lqmult");
513                 if (!p_next[2]) {
514                   fprintf(stderr, "Odd args in %s\n", optarg_next);
515                   exit(EXIT_FAILURE);
516                 }
517                 memset(&mult->addr, 0, sizeof(mult->addr));
518                 if (0 != strcmp("default", p_next[1])) {
519                   if (inet_pton(olsr_cnf->ip_version, p_next[1], &mult->addr) <= 0) {
520                     fprintf(stderr, "Failed converting IP address %s\n", p_next[1]);
521                     exit(EXIT_FAILURE);
522                   }
523                 }
524                 f = 0;
525                 sscanf(p_next[2], "%f", &f);
526                 mult->value = (uint32_t)(f * LINK_LOSS_MULTIPLIER);
527                 mult->next = ifs->cnf->lq_mult;
528                 ifs->cnf->lq_mult = mult;
529                 PARSER_DEBUG_PRINTF("\tLinkQualityMult %s %0.2f\n", olsr_ip_to_string(&buf, &mult->addr), (float)mult->value / LINK_LOSS_MULTIPLIER);
530                 p_next++;
531               }
532               else {
533                 fprintf(stderr, "Unknown arg: %s %s\n", p_next[0], p_next[1]);
534               }
535               p_next += 2;
536             }
537             p++;
538           }
539           if (tok_next) olsr_strtok_free(tok_next);
540         }
541         olsr_strtok_free(tok);
542       }
543       else {
544         fprintf(stderr, "Error in %s\n", optarg);
545         exit(EXIT_FAILURE);
546       }
547       break;
548     case 'Q':                  /* IpcConnect (Host,Net,MaxConnections) */
549       if ('{' != *optarg) {
550         fprintf(stderr, "No {}\n");
551         exit(EXIT_FAILURE);
552       }
553       else if (NULL != (tok = olsr_strtok(optarg + 1, NULL))) {
554         char **p = tok;
555         while(p[0]) {
556           if (!p[1]) {
557             fprintf(stderr, "Odd args in %s\n", optarg);
558             exit(EXIT_FAILURE);
559           }
560           if (0 == strcmp("MaxConnections", p[0])) {
561             int arg = -1;
562             sscanf(optarg, "%d", &arg);
563             if (0 <= arg && arg < 1 << (8 * sizeof(olsr_cnf->ipc_connections)))
564               olsr_cnf->ipc_connections = arg;
565             PARSER_DEBUG_PRINTF("\tIPC connections: %d\n", olsr_cnf->ipc_connections);
566           }
567           else if (0 == strcmp("Host", p[0])) {
568             union olsr_ip_addr ipaddr;
569             if (inet_pton(olsr_cnf->ip_version, p[1], &ipaddr) <= 0) {
570               fprintf(stderr, "Failed converting IP address %s\n", p[0]);
571               exit(EXIT_FAILURE);
572             }
573             ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, olsr_cnf->maxplen);
574             PARSER_DEBUG_PRINTF("\tIPC host: %s\n", olsr_ip_to_string(&buf, &ipaddr));
575           }
576           else if (0 == strcmp("Net", p[0])) {
577             union olsr_ip_addr ipaddr;
578             if (!p[2]) {
579               fprintf(stderr, "Odd args in %s\n", optarg_next);
580               exit(EXIT_FAILURE);
581             }
582             if (inet_pton(olsr_cnf->ip_version, p[1], &ipaddr) <= 0) {
583               fprintf(stderr, "Failed converting IP address %s\n", p[0]);
584               exit(EXIT_FAILURE);
585             }
586             if (AF_INET == olsr_cnf->ip_version) {
587               union olsr_ip_addr netmask;
588               if (inet_pton(AF_INET, p[2], &netmask) <= 0) {
589                 fprintf(stderr, "Failed converting IP address %s\n", p[2]);
590                 exit(EXIT_FAILURE);
591               }
592               if ((ipaddr.v4.s_addr & ~netmask.v4.s_addr) != 0) {
593                 fprintf(stderr, "The IP address %s/%s is not a network address!\n", p[1], p[2]);
594                 exit(EXIT_FAILURE);
595               }
596               ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, olsr_netmask_to_prefix(&netmask));
597               PARSER_DEBUG_PRINTF("\tIPC net: %s/%d\n", olsr_ip_to_string(&buf, &ipaddr), olsr_netmask_to_prefix(&netmask));
598             }
599             else {
600               int prefix = -1;
601               sscanf('/' == *p[2] ? p[2] + 1 : p[2], "%d", &prefix);
602               if (0 > prefix || 128 < prefix) {
603                 fprintf(stderr, "Illegal IPv6 prefix %s\n", p[2]);
604                 exit(EXIT_FAILURE);
605               }
606               ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, prefix);
607               PARSER_DEBUG_PRINTF("\tIPC net: %s/%d\n", olsr_ip_to_string(&buf, &ipaddr), prefix);
608             }
609             p++;
610           }
611           else {
612             fprintf(stderr, "Unknown arg: %s %s\n", p[0], p[1]);
613           }
614           p += 2;
615         }
616         olsr_strtok_free(tok);
617       }
618       break;
619     case 'V':                  /* IpVersion (i) */
620       {
621         int ver = -1;
622         sscanf(optarg, "%d", &ver);
623         if (ver == 4) {
624           olsr_cnf->ip_version = AF_INET;
625           olsr_cnf->ipsize = sizeof(struct in_addr);
626           olsr_cnf->maxplen = 32;
627         } else if (ver == 6) {
628           olsr_cnf->ip_version = AF_INET6;
629           olsr_cnf->ipsize = sizeof(struct in6_addr);
630           olsr_cnf->maxplen = 128;
631         } else {
632           fprintf(stderr, "IpVersion must be 4 or 6!\n");
633           exit(EXIT_FAILURE);
634         }
635       }
636       PARSER_DEBUG_PRINTF("IpVersion: %d\n", olsr_cnf->ip_version);
637       break;
638     case 'a':                  /* LinkQualityAging (f) */
639       sscanf(optarg, "%f", &olsr_cnf->lq_aging);
640       PARSER_DEBUG_PRINTF("Link quality aging factor %f\n", olsr_cnf->lq_aging);
641       break;
642     case 'l':                  /* LinkQualityAlgorithm (str) */
643       if (NULL != (tok = olsr_strtok(optarg, NULL)))
644       {
645         olsr_cnf->lq_algorithm = olsr_strdup(*tok);
646         olsr_strtok_free(tok);
647       }
648       else {
649         fprintf(stderr, "Error in %s\n", optarg);
650         exit(EXIT_FAILURE);
651       }
652       PARSER_DEBUG_PRINTF("LQ Algorithm: %s\n", olsr_cnf->lq_algorithm);
653       break;
654     case 'J':                  /* LinkQualityDijkstraLimit (i,f) */
655       {
656         int arg = -1;
657         sscanf(optarg, "%d %f", &arg, &olsr_cnf->lq_dinter);
658         if (0 <= arg && arg < (1 << (8 * sizeof(olsr_cnf->lq_dlimit))))
659           olsr_cnf->lq_dlimit = arg;
660         PARSER_DEBUG_PRINTF("Link quality dijkstra limit %d, %0.2f\n", olsr_cnf->lq_dlimit, olsr_cnf->lq_dinter);
661       }
662       break;
663     case 'E':                  /* LinkQualityFishEye (i) */
664       {
665         int arg = -1;
666         sscanf(optarg, "%d", &arg);
667         if (0 <= arg && arg < (1 << (8 * sizeof(olsr_cnf->lq_fish))))
668           olsr_cnf->lq_fish = arg;
669         PARSER_DEBUG_PRINTF("Link quality fish eye %d\n", olsr_cnf->lq_fish);
670       }
671       break;
672     case 'W':                  /* LinkQualityWinSize (i) */
673       /* Ignored */
674       break;
675     case 'p':                  /* LoadPlugin (soname {PlParams}) */
676       if (NULL != (tok = olsr_strtok(optarg, &optarg_next))) {
677         if ('{' != *optarg_next) {
678           fprintf(stderr, "No {}\n");
679           exit(EXIT_FAILURE);
680         }
681         else {
682           char **tok_next = olsr_strtok(optarg_next + 1, NULL);
683           struct plugin_entry *pe = olsr_malloc(sizeof(*pe), "plugin");
684           pe->name = olsr_strdup(*tok);
685           pe->params = NULL;
686           pe->next = olsr_cnf->plugins;
687           olsr_cnf->plugins = pe;
688           PARSER_DEBUG_PRINTF("Plugin: %s\n", pe->name);
689           if (tok_next) {
690             char **p_next = tok_next;
691             while(p_next[0]) {
692               struct plugin_param *pp = olsr_malloc(sizeof(*pp), "plparam");
693               if (0 != strcmp("PlParam", p_next[0]) || !p_next[1] || !p_next[2]) {
694                 fprintf(stderr, "Odd args in %s\n", optarg_next);
695                 exit(EXIT_FAILURE);
696               }
697               pp->key = olsr_strdup(p_next[1]);
698               pp->value = olsr_strdup(p_next[2]);
699               pp->next = pe->params;
700               pe->params = pp;
701               PARSER_DEBUG_PRINTF("\tPlParam: %s %s\n", pp->key, pp->value);
702               p_next += 3;
703             }
704             olsr_strtok_free(tok_next);
705           }
706         }
707         olsr_strtok_free(tok);
708       }
709       else {
710         fprintf(stderr, "Error in %s\n", optarg);
711         exit(EXIT_FAILURE);
712       }
713       break;
714     case 'M':                  /* MprCoverage (i) */
715       {
716         int arg = -1;
717         sscanf(optarg, "%d", &arg);
718         if (0 <= arg && arg < (1 << (8 * sizeof(olsr_cnf->mpr_coverage))))
719           olsr_cnf->mpr_coverage = arg;
720         PARSER_DEBUG_PRINTF("MPR coverage %d\n", olsr_cnf->mpr_coverage);
721       }
722       break;
723     case 'N':                  /* NatThreshold (f) */
724       sscanf(optarg, "%f", &olsr_cnf->lq_nat_thresh);
725       PARSER_DEBUG_PRINTF("NAT threshold %0.2f\n", olsr_cnf->lq_nat_thresh);
726       break;
727     case 'Y':                  /* NicChgsPollInt (f) */
728       sscanf(optarg, "%f", &olsr_cnf->nic_chgs_pollrate);
729       PARSER_DEBUG_PRINTF("NIC Changes Pollrate %0.2f\n", olsr_cnf->nic_chgs_pollrate);
730       break;
731     case 'T':                  /* Pollrate (f) */
732       {
733         float arg = -1;
734         sscanf(optarg, "%f", &arg);
735         if (0 <= arg)
736           olsr_cnf->pollrate = conv_pollrate_to_microsecs(arg);
737         PARSER_DEBUG_PRINTF("Pollrate %ud\n", olsr_cnf->pollrate);
738       }
739       break;
740     case 'q':                  /* RtProto (i) */
741       {
742         int arg = -1;
743         sscanf(optarg, "%d", &arg);
744         if (0 <= arg && arg < (1 << (8 * sizeof(olsr_cnf->rtproto))))
745           olsr_cnf->rtproto = arg;
746         PARSER_DEBUG_PRINTF("RtProto: %d\n", olsr_cnf->rtproto);
747       }
748       break;
749     case 'R':                  /* RtTableDefault (i) */
750       {
751         int arg = -1;
752         sscanf(optarg, "%d", &arg);
753         if (0 <= arg && arg < (1 << (8 *sizeof(olsr_cnf->rttable_default))))
754           olsr_cnf->rttable_default = arg;
755         PARSER_DEBUG_PRINTF("RtTableDefault: %d\n", olsr_cnf->rttable_default);
756       }
757       break;
758     case 'r':                  /* RtTable (i) */
759       {
760         int arg = -1;
761         sscanf(optarg, "%d", &arg);
762         if (0 <= arg && arg < (1 << (8*sizeof(olsr_cnf->rttable))))
763           olsr_cnf->rttable = arg;
764         PARSER_DEBUG_PRINTF("RtTable: %d\n", olsr_cnf->rttable);
765       }
766       break;
767     case 't':                  /* TcRedundancy (i) */
768       {
769         int arg = -1;
770         sscanf(optarg, "%d", &arg);
771         if (0 <= arg && arg < (1 << (8 * sizeof(olsr_cnf->tc_redundancy))))
772           olsr_cnf->tc_redundancy = arg;
773         PARSER_DEBUG_PRINTF("TC redundancy %d\n", olsr_cnf->tc_redundancy);
774       }
775       break;
776     case 'Z':                  /* TosValue (i) */
777       {
778         int arg = -1;
779         sscanf(optarg, "%d", &arg);
780         if (0 <= arg && arg < (1 << (8 * sizeof(olsr_cnf->tos))))
781           olsr_cnf->tos = arg;
782         PARSER_DEBUG_PRINTF("TOS: %d\n", olsr_cnf->tos);
783       }
784       break;
785     case 'w':                  /* Willingness (i) */
786       {
787         int arg = -1;
788         sscanf(optarg, "%d", &arg);
789         if (0 <= arg && arg < (1 << (8 * sizeof(olsr_cnf->willingness))))
790           olsr_cnf->willingness = arg;
791         olsr_cnf->willingness_auto = false;
792         PARSER_DEBUG_PRINTF("Willingness: %d (no auto)\n", olsr_cnf->willingness);
793       }
794       break;
795     default:
796       if (opt >= 32 && opt <= 255)
797         fprintf (stderr, "Unknown option '%c' for parsing ??\n", (char)opt);
798       else
799         fprintf (stderr, "?? getopt returned %d ??\n", opt);
800       fprintf(stderr, "Continue to parse the rest of the config file...\n");
801     } /* switch */
802   } /* while getopt_long() */
803
804   while(optind < opt_argc) {
805     struct olsr_if *ifs;
806     PARSER_DEBUG_PRINTF("new iface %s\n", opt_argv[optind]);
807     if (NULL != (ifs = queue_if(opt_argv[optind++], false))) {
808       ifs->cnf = olsr_get_default_if_config();
809     }
810   }
811
812   /* Some cleanup */
813   while(0 < opt_argc) {
814     free(opt_argv[--opt_argc]);
815   }
816   free(opt_argv);
817   free(opt_str);
818
819   return olsr_cnf;
820 }
821
822 int
823 olsr_sanity_check_cnf(struct olsrd_config *cnf)
824 {
825   struct olsr_if *in = cnf->interfaces;
826   struct if_config_options *io;
827
828   /* Debug level */
829   if (cnf->debug_level < MIN_DEBUGLVL || cnf->debug_level > MAX_DEBUGLVL) {
830     fprintf(stderr, "Debuglevel %d is not allowed\n", cnf->debug_level);
831     return -1;
832   }
833
834   /* IP version */
835   if (cnf->ip_version != AF_INET && cnf->ip_version != AF_INET6) {
836     fprintf(stderr, "Ipversion %d not allowed!\n", cnf->ip_version);
837     return -1;
838   }
839
840   /* TOS */
841   if (cnf->tos > MAX_TOS) {
842     fprintf(stderr, "TOS %d is not allowed\n", cnf->tos);
843     return -1;
844   }
845
846   /* Willingness */
847   if (cnf->willingness_auto == false && (cnf->willingness > MAX_WILLINGNESS)) {
848     fprintf(stderr, "Willingness %d is not allowed\n", cnf->willingness);
849     return -1;
850   }
851
852   /* Check Link quality dijkstra limit */
853   if (olsr_cnf->lq_dinter < conv_pollrate_to_secs(cnf->pollrate) && olsr_cnf->lq_dlimit != 255) {
854     fprintf(stderr, "Link quality dijkstra limit must be higher than pollrate\n");
855     return -1;
856   }
857
858   /* NIC Changes Pollrate */
859   if (cnf->nic_chgs_pollrate < MIN_NICCHGPOLLRT || cnf->nic_chgs_pollrate > MAX_NICCHGPOLLRT) {
860     fprintf(stderr, "NIC Changes Pollrate %0.2f is not allowed\n", cnf->nic_chgs_pollrate);
861     return -1;
862   }
863
864   /* TC redundancy */
865   if (cnf->tc_redundancy > MAX_TC_REDUNDANCY) {
866     fprintf(stderr, "TC redundancy %d is not allowed\n", cnf->tc_redundancy);
867     return -1;
868   }
869
870   /* MPR coverage */
871   if (cnf->mpr_coverage < MIN_MPR_COVERAGE || cnf->mpr_coverage > MAX_MPR_COVERAGE) {
872     fprintf(stderr, "MPR coverage %d is not allowed\n", cnf->mpr_coverage);
873     return -1;
874   }
875
876   /* Link quality window size */
877   if (cnf->lq_aging < MIN_LQ_AGING || cnf->lq_aging > MAX_LQ_AGING) {
878     fprintf(stderr, "LQ aging factor %f is not allowed\n", cnf->lq_aging);
879     return -1;
880   }
881
882   /* NAT threshold value */
883   if (cnf->lq_nat_thresh < 0.1 || cnf->lq_nat_thresh > 1.0) {
884     fprintf(stderr, "NAT threshold %f is not allowed\n", cnf->lq_nat_thresh);
885     return -1;
886   }
887
888   if (in == NULL) {
889     fprintf(stderr, "No interfaces configured!\n");
890     return -1;
891   }
892
893   /* Interfaces */
894   while (in) {
895     io = in->cnf;
896
897     if (in->name == NULL || !strlen(in->name)) {
898       fprintf(stderr, "Interface has no name!\n");
899       return -1;
900     }
901
902     if (io == NULL) {
903       fprintf(stderr, "Interface %s has no configuration!\n", in->name);
904       return -1;
905     }
906
907     /* HELLO interval */
908
909     if (io->hello_params.validity_time < 0.0) {
910       io->hello_params.validity_time = (int)(REFRESH_INTERVAL / cnf->lq_aging);
911     }
912
913     if (io->hello_params.emission_interval < conv_pollrate_to_secs(cnf->pollrate) ||
914         io->hello_params.emission_interval > io->hello_params.validity_time) {
915       fprintf(stderr, "Bad HELLO parameters! (em: %0.2f, vt: %0.2f)\n", io->hello_params.emission_interval,
916               io->hello_params.validity_time);
917       return -1;
918     }
919
920     /* TC interval */
921     if (io->tc_params.emission_interval < conv_pollrate_to_secs(cnf->pollrate) ||
922         io->tc_params.emission_interval > io->tc_params.validity_time) {
923       fprintf(stderr, "Bad TC parameters! (em: %0.2f, vt: %0.2f)\n", io->tc_params.emission_interval, io->tc_params.validity_time);
924       return -1;
925     }
926
927     /* MID interval */
928     if (io->mid_params.emission_interval < conv_pollrate_to_secs(cnf->pollrate) ||
929         io->mid_params.emission_interval > io->mid_params.validity_time) {
930       fprintf(stderr, "Bad MID parameters! (em: %0.2f, vt: %0.2f)\n", io->mid_params.emission_interval,
931               io->mid_params.validity_time);
932       return -1;
933     }
934
935     /* HNA interval */
936     if (io->hna_params.emission_interval < conv_pollrate_to_secs(cnf->pollrate) ||
937         io->hna_params.emission_interval > io->hna_params.validity_time) {
938       fprintf(stderr, "Bad HNA parameters! (em: %0.2f, vt: %0.2f)\n", io->hna_params.emission_interval,
939               io->hna_params.validity_time);
940       return -1;
941     }
942
943     in = in->next;
944   }
945
946   return 0;
947 }
948
949 void
950 olsr_free_cnf(struct olsrd_config *cnf)
951 {
952   struct ip_prefix_list *hd, *h = cnf->hna_entries;
953   struct olsr_if *ind, *in = cnf->interfaces;
954   struct plugin_entry *ped, *pe = cnf->plugins;
955   struct olsr_lq_mult *mult, *next_mult;
956
957   /*
958    * HNAs.
959    */
960   while (h) {
961     hd = h;
962     h = h->next;
963     free(hd);
964   }
965
966   /*
967    * Interfaces.
968    */
969   while (in) {
970     for (mult = in->cnf->lq_mult; mult != NULL; mult = next_mult) {
971       next_mult = mult->next;
972       free(mult);
973     }
974
975     remove_interface(in);
976
977     free(in->cnf);
978     ind = in;
979     in = in->next;
980     free(ind->name);
981     free(ind->config);
982     free(ind);
983   }
984
985   /*
986    * Plugins.
987    */
988   while (pe) {
989     ped = pe;
990     pe = pe->next;
991     free(ped->name);
992     free(ped);
993   }
994
995   return;
996 }
997
998 static void
999 set_default_cnf(struct olsrd_config *cnf)
1000 {
1001   memset(cnf, 0, sizeof(*cnf));
1002
1003   cnf->debug_level = DEF_DEBUGLVL;
1004   cnf->no_fork = false;
1005   cnf->host_emul = false;
1006   cnf->ip_version = AF_INET;
1007   cnf->ipsize = sizeof(struct in_addr);
1008   cnf->maxplen = 32;
1009   cnf->allow_no_interfaces = DEF_ALLOW_NO_INTS;
1010   cnf->tos = DEF_TOS;
1011   cnf->rtproto = 3;
1012   cnf->rttable = 254;
1013   cnf->rttable_default = 0;
1014   cnf->willingness_auto = DEF_WILL_AUTO;
1015   cnf->ipc_connections = DEF_IPC_CONNECTIONS;
1016   cnf->fib_metric = DEF_FIB_METRIC;
1017
1018   cnf->pollrate = conv_pollrate_to_microsecs(DEF_POLLRATE);
1019   cnf->nic_chgs_pollrate = DEF_NICCHGPOLLRT;
1020
1021   cnf->tc_redundancy = TC_REDUNDANCY;
1022   cnf->mpr_coverage = MPR_COVERAGE;
1023   cnf->lq_fish = DEF_LQ_FISH;
1024   cnf->lq_dlimit = DEF_LQ_DIJK_LIMIT;
1025   cnf->lq_dinter = DEF_LQ_DIJK_INTER;
1026   cnf->lq_aging = DEF_LQ_AGING;
1027   cnf->lq_algorithm = NULL;
1028   cnf->lq_nat_thresh = DEF_LQ_NAT_THRESH;
1029   cnf->clear_screen = DEF_CLEAR_SCREEN;
1030
1031   cnf->del_gws = false;
1032   cnf->will_int = 10 * HELLO_INTERVAL;
1033   cnf->exit_value = EXIT_SUCCESS;
1034   cnf->max_tc_vtime = 0.0;
1035   cnf->ioctl_s = 0;
1036
1037 #if defined linux
1038   cnf->rts_linux = 0;
1039 #endif
1040 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
1041   cnf->rts_bsd = 0;
1042 #endif
1043 }
1044
1045 struct olsrd_config *
1046 olsr_get_default_cnf(void)
1047 {
1048   struct olsrd_config *c = olsr_malloc(sizeof(struct olsrd_config), "default_cnf");
1049   if (c == NULL) {
1050     fprintf(stderr, "Out of memory %s\n", __func__);
1051     return NULL;
1052   }
1053
1054   set_default_cnf(c);
1055   return c;
1056 }
1057
1058 static void
1059 olsr_init_default_if_config(struct if_config_options *io)
1060 {
1061   struct in6_addr in6;
1062
1063   memset(io, 0, sizeof(*io));
1064
1065   io->ipv6_addrtype = OLSR_IP6T_SITELOCAL;
1066
1067   inet_pton(AF_INET6, OLSR_IPV6_MCAST_SITE_LOCAL, &in6);
1068   io->ipv6_multi_site.v6 = in6;
1069
1070   inet_pton(AF_INET6, OLSR_IPV6_MCAST_GLOBAL, &in6);
1071   io->ipv6_multi_glbl.v6 = in6;
1072
1073   io->lq_mult = NULL;
1074
1075   io->weight.fixed = false;
1076   io->weight.value = 0;
1077
1078   io->ipv6_addrtype = OLSR_IP6T_AUTO;
1079
1080   io->hello_params.emission_interval = HELLO_INTERVAL;
1081   io->hello_params.validity_time = NEIGHB_HOLD_TIME;
1082   io->tc_params.emission_interval = TC_INTERVAL;
1083   io->tc_params.validity_time = TOP_HOLD_TIME;
1084   io->mid_params.emission_interval = MID_INTERVAL;
1085   io->mid_params.validity_time = MID_HOLD_TIME;
1086   io->hna_params.emission_interval = HNA_INTERVAL;
1087   io->hna_params.validity_time = HNA_HOLD_TIME;
1088   io->autodetect_chg = true;
1089 }
1090
1091 static struct if_config_options *
1092 olsr_get_default_if_config(void)
1093 {
1094   struct if_config_options *io = olsr_malloc(sizeof(*io), "default_if_config");
1095
1096   if (io == NULL) {
1097     fprintf(stderr, "Out of memory %s\n", __func__);
1098     return NULL;
1099   }
1100   olsr_init_default_if_config(io);
1101   return io;
1102 }
1103
1104 #if 0
1105 int
1106 olsr_check_pollrate(float *pollrate)
1107 {
1108   if (*pollrate > MAX_POLLRATE) {
1109     fprintf(stderr, "Pollrate %0.2f is too large\n", *pollrate);
1110     return -1;
1111   }
1112 #ifdef WIN32
1113 #define sysconf(_SC_CLK_TCK) 1000L
1114 #endif
1115   if (*pollrate < MIN_POLLRATE || *pollrate < 1.0 / sysconf(_SC_CLK_TCK)) {
1116     fprintf(stderr, "Pollrate %0.2f is too small - setting it to %ld\n", *pollrate, sysconf(_SC_CLK_TCK));
1117     *pollrate = 1.0 / sysconf(_SC_CLK_TCK);
1118   }
1119   return 0;
1120 }
1121 #endif
1122
1123 void
1124 ip_prefix_list_flush(struct ip_prefix_list **list)
1125 {
1126   struct ip_prefix_list *entry, *next_entry;
1127
1128   for (entry = *list; entry; entry = next_entry) {
1129     next_entry = entry->next;
1130
1131     entry->next = NULL;
1132     free(entry);
1133   }
1134   *list = NULL;
1135 }
1136
1137 void
1138 ip_prefix_list_add(struct ip_prefix_list **list, const union olsr_ip_addr *net, uint8_t prefix_len)
1139 {
1140   struct ip_prefix_list *new_entry = olsr_malloc(sizeof(*new_entry), "new ip_prefix");
1141
1142   new_entry->net.prefix = *net;
1143   new_entry->net.prefix_len = prefix_len;
1144
1145   /* Queue */
1146   new_entry->next = *list;
1147   *list = new_entry;
1148 }
1149
1150 int
1151 ip_prefix_list_remove(struct ip_prefix_list **list, const union olsr_ip_addr *net, uint8_t prefix_len)
1152 {
1153   struct ip_prefix_list *h = *list, *prev = NULL;
1154
1155   while (h != NULL) {
1156     if (ipequal(net, &h->net.prefix) && h->net.prefix_len == prefix_len) {
1157       /* Dequeue */
1158       if (prev == NULL) {
1159         *list = h->next;
1160       } else {
1161         prev->next = h->next;
1162       }
1163       free(h);
1164       return 1;
1165     }
1166     prev = h;
1167     h = h->next;
1168   }
1169   return 0;
1170 }
1171
1172 struct ip_prefix_list *
1173 ip_prefix_list_find(struct ip_prefix_list *list, const union olsr_ip_addr *net, uint8_t prefix_len)
1174 {
1175   struct ip_prefix_list *h;
1176   for (h = list; h != NULL; h = h->next) {
1177     if (prefix_len == h->net.prefix_len && ipequal(net, &h->net.prefix)) {
1178       return h;
1179     }
1180   }
1181   return NULL;
1182 }
1183
1184 static char*
1185 olsr_strdup(const char *s)
1186 {
1187   char *ret = olsr_malloc(1 + strlen(s), "olsr_strndup");
1188   strcpy(ret, s);
1189   return ret;
1190 }
1191
1192 static char*
1193 olsr_strndup(const char *s, size_t n)
1194 {
1195   size_t len = n < strlen(s) ? n : strlen(s);
1196   char *ret = olsr_malloc(1 + len, "olsr_strndup");
1197   strncpy(ret, s, len);
1198   ret[len] = 0;
1199   return ret;
1200 }
1201
1202 static inline bool
1203 olsr_strtok_delim(const char *p)
1204 {
1205   switch (*p) {
1206     case 0:
1207     case '{':
1208     case '}':
1209       return true;
1210   }
1211   return false;
1212 }
1213
1214 static char**
1215 olsr_strtok(const char *s, const char **snext)
1216 {
1217   char **tmp, **ret = NULL;
1218   int i, count = 0;
1219   const char *p = s;
1220
1221   while (!olsr_strtok_delim(p)) {
1222     while (!olsr_strtok_delim(p) && ' ' >= *p)
1223       p++;
1224     if (!olsr_strtok_delim(p)) {
1225       char c = 0;
1226       const char *q = p;
1227       if ('"' == *p || '\'' == *p) {
1228         c = *q++;
1229         while(!olsr_strtok_delim(++p) && c != *p);
1230       }
1231       else {
1232         while(!olsr_strtok_delim(p) && ' ' < *p)
1233           p++;
1234       }
1235       tmp = ret;
1236       ret = olsr_malloc((2 + count) * sizeof(ret[0]), "olsr_strtok");
1237       for (i = 0; i < count; i++) {
1238         ret[i] = tmp[i];
1239       }
1240       if (tmp)
1241         free(tmp);
1242       ret[count++] = olsr_strndup(q, p - q);
1243       ret[count] = NULL;
1244       if (c)
1245         p++;
1246     }
1247   }
1248   if (snext)
1249     *snext = p;
1250   return ret;
1251 }
1252
1253 static void olsr_strtok_free(char **s)
1254 {
1255   if (s) {
1256     char **p = s;
1257     while(*p) {
1258       free(*p);
1259       p++;
1260     }
1261     free(s);
1262   }
1263 }
1264
1265 static int
1266 read_config (const char *filename, int *pargc, char ***pargv)
1267 {
1268   FILE *f = fopen (filename, "r");
1269   if (f)
1270   {
1271     int bopen = 0, optind_tmp = optind;
1272     char **argv_lst = 0;
1273     char sbuf[512], nbuf[512] = { 0 }, *p;
1274     while ((p = fgets (sbuf, sizeof (sbuf), f)) || *nbuf)
1275     {
1276       if (!p)
1277       {
1278         *sbuf = 0;
1279         goto eof;
1280       }
1281       while (*p && '#' != *p)
1282       {
1283         if ('"' == *p || '\'' == *p)
1284         {
1285           char sep = *p;
1286           while (*++p && sep != *p);
1287         }
1288         p++;
1289       }
1290       *p = 0;
1291       while (sbuf <= --p && ' ' >= *p);
1292       *(p + 1) = 0;
1293       if (*sbuf)
1294       {
1295         if (bopen)
1296         {
1297           strcat (nbuf, sbuf);
1298           if ('}' == *p)
1299           {
1300             bopen = 0;
1301             strcpy (sbuf, nbuf);
1302           }
1303         }
1304         else if (p == sbuf && '{' == *p)
1305         {
1306           strcat (nbuf, " ");
1307           strcat (nbuf, sbuf);
1308           bopen = 1;
1309         }
1310         else
1311         {
1312           if ('{' == *p)
1313             bopen = 1;
1314         eof:
1315           if (*nbuf)
1316           {
1317             int i;
1318             char **argv_tmp;
1319             int argc_tmp = *pargc + 2;
1320
1321             char *q = nbuf, *n;
1322             while (*q && ' ' >= *q)
1323               q++;
1324             p = q;
1325             while (' ' < *p)
1326               p++;
1327             n = olsr_malloc (p - q + 3, "config arg0");
1328             strcpy (n, "--");
1329             strncat (n, q, p - q);
1330             while (*q && ' ' >= *p)
1331               p++;
1332
1333             argv_tmp = olsr_malloc (argc_tmp * sizeof (argv_tmp[0]), "config arg1");
1334             for (i = 0; i < argc_tmp; i++)
1335             {
1336               if (i < optind_tmp)
1337                 argv_tmp[i] = (*pargv)[i];
1338               else if (i == optind_tmp)
1339                 argv_tmp[i] = n;
1340               else if (i == 1 + optind_tmp)
1341                 argv_tmp[i] = olsr_strdup (p);
1342               else
1343                 argv_tmp[i] = (*pargv)[i - 2];
1344             }
1345             optind_tmp += 2;
1346             *pargc = argc_tmp;
1347             *pargv = argv_tmp;
1348             if (argv_lst)
1349               free (argv_lst);
1350             argv_lst = argv_tmp;
1351           }
1352           strcpy (nbuf, sbuf);
1353         }
1354       }
1355     }
1356     fclose (f);
1357     return 0;
1358   }
1359   return -1;
1360 }
1361
1362 /*
1363  * Local Variables:
1364  * c-basic-offset: 2
1365  * indent-tabs-mode: nil
1366  * End:
1367  */