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