3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 * Visit http://www.olsr.org for more information.
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.
43 #include "olsr_cfg_data.h"
50 #include "olsr_ip_prefix_list.h"
51 #include "olsr_protocol.h"
52 #include "common/string.h"
53 #include "olsr_time.h"
57 #include <sys/types.h>
58 #include <sys/socket.h>
59 #include <arpa/inet.h>
65 #define PARSER_DEBUG_PRINTF(x, args...) printf(x, ##args)
67 #define PARSER_DEBUG_PRINTF(x, ...) do { } while (0)
70 /* options that have no short command line variant */
71 enum cfg_long_options {
89 /* remember which log severities have been explicitly set */
90 static bool cfg_has_log[LOG_SEVERITY_COUNT];
93 * Special strcat for reading the config file and
94 * joining a longer section { ... } to one string
97 read_cfg_cat(char **pdest, const char *src)
101 size_t size = 1 + (tmp ? strlen(tmp) : 0) + strlen(src);
102 *pdest = olsr_malloc(size, "read_cfg_cat");
103 assert(0 == **pdest);
105 strscpy(*pdest, tmp, size);
108 strscat(*pdest, src, size);
113 * Read the olsrd.conf file and replace/insert found
114 * options into the argv[] array at the position of
115 * the original -f filename parameters. Note, that
116 * longer sections { ... } are joined to one string
119 read_cfg(const char *filename, int *pargc, char ***pargv, int **pline)
121 FILE *f = fopen(filename, "r");
123 int bopen = 0, optind_tmp = optind, line_lst = 0, line = 0;
124 char sbuf[512], *pbuf = NULL, *p;
126 while ((p = fgets(sbuf, sizeof(sbuf), f)) || pbuf) {
132 while (*p && '#' != *p) {
133 if ('"' == *p || '\'' == *p) {
135 while (*++p && sep != *p);
140 while (sbuf <= --p && ' ' >= *p);
144 read_cfg_cat(&pbuf, sbuf);
148 } else if (p == sbuf && '{' == *p) {
149 read_cfg_cat(&pbuf, " ");
150 read_cfg_cat(&pbuf, sbuf);
160 int argc_tmp = *pargc + 2;
164 while (*q && ' ' >= *q)
170 n = olsr_malloc(size, "config arg0");
171 strscpy(n, "--", size);
173 while (*q && ' ' >= *p)
176 line_tmp = olsr_malloc(argc_tmp * sizeof(line_tmp[0]), "config line");
177 argv_tmp = olsr_malloc(argc_tmp * sizeof(argv_tmp[0]), "config args");
178 for (i = 0; i < argc_tmp; i++) {
179 if (i < optind_tmp) {
180 line_tmp[i] = (*pline)[i];
181 argv_tmp[i] = (*pargv)[i];
182 } else if (i == optind_tmp) {
183 line_tmp[i] = line_lst;
185 } else if (i == 1 + optind_tmp) {
186 line_tmp[i] = line_lst;
187 argv_tmp[i] = olsr_strdup(p);
189 line_tmp[i] = (*pline)[i - 2];
190 argv_tmp[i] = (*pargv)[i - 2];
203 read_cfg_cat(&pbuf, sbuf);
214 * Free an array of string tokens
217 parse_tok_free(char **s)
230 * Test for end-of-string or { ... } section
233 parse_tok_delim(const char *p)
245 * Slit the src string into tokens and return
246 * an array of token strings. May return NULL
247 * if no token found, otherwise you need to
248 * free the strings using parse_tok_free()
251 parse_tok(const char *s, const char **snext)
253 char **tmp, **ret = NULL;
257 while (!parse_tok_delim(p)) {
258 while (!parse_tok_delim(p) && ' ' >= *p)
260 if (!parse_tok_delim(p)) {
263 if ('"' == *p || '\'' == *p) {
265 while (!parse_tok_delim(++p) && c != *p);
267 while (!parse_tok_delim(p) && ' ' < *p)
271 ret = olsr_malloc((2 + count) * sizeof(ret[0]), "parse_tok");
272 for (i = 0; i < count; i++) {
277 ret[count++] = olsr_strndup(q, p - q);
289 * Returns default interface options
291 struct olsr_if_options *
292 olsr_get_default_if_options(void)
294 struct olsr_if_options *new_io = olsr_malloc(sizeof(*new_io), "default_if_config");
296 /* No memset because olsr_malloc uses calloc() */
297 /* memset(&new_io->ipv4_broadcast, 0, sizeof(new_io->ipv4_broadcast)); */
298 new_io->ipv6_addrtype = OLSR_IP6T_AUTO;
299 inet_pton(AF_INET6, OLSR_IPV6_MCAST_SITE_LOCAL, &new_io->ipv6_multi_site.v6);
300 inet_pton(AF_INET6, OLSR_IPV6_MCAST_GLOBAL, &new_io->ipv6_multi_glbl.v6);
301 /* new_io->weight.fixed = false; */
302 /* new_io->weight.value = 0; */
303 new_io->hello_params.emission_interval = HELLO_INTERVAL;
304 new_io->hello_params.validity_time = NEIGHB_HOLD_TIME;
305 new_io->tc_params.emission_interval = TC_INTERVAL;
306 new_io->tc_params.validity_time = TOP_HOLD_TIME;
307 new_io->mid_params.emission_interval = MID_INTERVAL;
308 new_io->mid_params.validity_time = MID_HOLD_TIME;
309 new_io->hna_params.emission_interval = HNA_INTERVAL;
310 new_io->hna_params.validity_time = HNA_HOLD_TIME;
311 /* new_io->lq_mult = NULL; */
312 new_io->autodetect_chg = true;
313 new_io->mode = IF_MODE_MESH;
318 * Create a new interf_name struct using a given
319 * name and insert it into the interface list.
321 static struct olsr_if_config *
322 queue_if(const char *name, struct olsr_config *cfg)
324 struct olsr_if_config *new_if;
326 /* check if the interface already exists */
327 for (new_if = cfg->if_configs; new_if != NULL; new_if = new_if->next) {
328 if (0 == strcasecmp(new_if->name, name)) {
329 fprintf(stderr, "Duplicate interfaces defined... not adding %s\n", name);
334 new_if = olsr_malloc(sizeof(*new_if), "queue interface");
335 new_if->name = olsr_strdup(name);
336 /* new_if->config = NULL; */
337 /* memset(&new_if->hemu_ip, 0, sizeof(new_if->hemu_ip)); */
338 /* new_if->interf = NULL; */
339 new_if->cnf = olsr_get_default_if_options();
340 new_if->next = cfg->if_configs;
341 cfg->if_configs = new_if;
347 * Parses a single hna option block
348 * @argstr: arguments string
349 * @ip_version: AF_INET of AF_INET6
350 * @rcfg: config struct to write/change values into
351 * @rmsg: a buf[FILENAME_MAX + 256] to sprint err msgs
352 * @returns configuration status as defined in olsr_parse_cfg_result
354 static olsr_parse_cfg_result
355 parse_cfg_hna(char *argstr, const int ip_version, struct olsr_config *rcfg, char *rmsg)
359 struct ipaddr_str buf;
361 if ('{' != *argstr) {
362 sprintf(rmsg, "No {}\n");
365 if (NULL != (tok = parse_tok(argstr + 1, NULL))) {
367 if (ip_version != rcfg->ip_version) {
368 sprintf(rmsg, "IPv%d addresses can only be used if \"IpVersion\" == %d\n",
369 AF_INET == ip_version ? 4 : 6, AF_INET == ip_version ? 4 : 6);
374 union olsr_ip_addr ipaddr;
376 sprintf(rmsg, "Odd args in %s\n", argstr);
380 if (inet_pton(ip_version, p[0], &ipaddr) <= 0) {
381 sprintf(rmsg, "Failed converting IP address %s\n", p[0]);
385 if (AF_INET == ip_version) {
386 union olsr_ip_addr netmask;
387 if (inet_pton(AF_INET, p[1], &netmask) <= 0) {
388 sprintf(rmsg, "Failed converting IP address %s\n", p[1]);
392 if ((ipaddr.v4.s_addr & ~netmask.v4.s_addr) != 0) {
393 sprintf(rmsg, "The IP address %s/%s is not a network address!\n", p[0], p[1]);
397 ip_prefix_list_add(&rcfg->hna_entries, &ipaddr, netmask_to_prefix((uint8_t *) & netmask, rcfg->ipsize));
398 PARSER_DEBUG_PRINTF("Hna4 %s/%d\n", ip_to_string(rcfg->ip_version, &buf, &ipaddr),
399 netmask_to_prefix((uint8_t *) & netmask, rcfg->ipsize));
402 sscanf('/' == *p[1] ? p[1] + 1 : p[1], "%d", &prefix);
403 if (0 > prefix || 128 < prefix) {
404 sprintf(rmsg, "Illegal IPv6 prefix %s\n", p[1]);
408 ip_prefix_list_add(&rcfg->hna_entries, &ipaddr, prefix);
409 PARSER_DEBUG_PRINTF("Hna6 %s/%d\n", ip_to_string(rcfg->ip_version, &buf, &ipaddr), prefix);
419 * Parses a single interface option block
420 * @argstr: arguments string
421 * @rcfg: config struct to write/change values into
422 * @rmsg: a buf[FILENAME_MAX + 256] to sprint err msgs
423 * @returns configuration status as defined in olsr_parse_cfg_result
425 static olsr_parse_cfg_result
426 parse_cfg_interface(char *argstr, struct olsr_config *rcfg, char *rmsg)
431 struct ipaddr_str buf;
433 if (NULL != (tok = parse_tok(argstr, &nxt))) {
435 sprintf(rmsg, "No {}\n");
439 char **tok_next = parse_tok(nxt + 1, NULL);
442 char **p_next = tok_next;
443 struct olsr_if_config *new_if = queue_if(p[0], rcfg);
444 PARSER_DEBUG_PRINTF("Interface %s\n", p[0]);
445 while (new_if && p_next[0]) {
447 sprintf(rmsg, "Odd args in %s\n", nxt);
448 parse_tok_free(tok_next);
452 if (0 == strcasecmp("Mode", p_next[0])) {
453 if (0 == strcasecmp("Ether", p_next[1])) {
454 new_if->cnf->mode = IF_MODE_ETHER;
456 new_if->cnf->mode = IF_MODE_MESH;
458 PARSER_DEBUG_PRINTF("\tMode: %s\n", INTERFACE_MODE_NAMES[new_if->cnf->mode]);
459 } else if (0 == strcasecmp("AutoDetectChanges", p_next[0])) {
460 new_if->cnf->autodetect_chg = (0 == strcasecmp("yes", p_next[1]));
461 PARSER_DEBUG_PRINTF("\tAutodetect changes: %d\n", new_if->cnf->autodetect_chg);
462 } else if (0 == strcasecmp("Ip4Broadcast", p_next[0])) {
463 union olsr_ip_addr ipaddr;
464 if (inet_pton(AF_INET, p_next[1], &ipaddr) <= 0) {
465 sprintf(rmsg, "Failed converting IP address %s\n", p_next[1]);
466 parse_tok_free(tok_next);
470 new_if->cnf->ipv4_broadcast = ipaddr;
471 PARSER_DEBUG_PRINTF("\tIPv4 broadcast: %s\n", ip4_to_string(&buf, new_if->cnf->ipv4_broadcast.v4));
472 } else if (0 == strcasecmp("Ip6AddrType", p_next[0])) {
473 if (0 == strcasecmp("site-local", p_next[1])) {
474 new_if->cnf->ipv6_addrtype = OLSR_IP6T_SITELOCAL;
475 } else if (0 == strcasecmp("unique-local", p_next[1])) {
476 new_if->cnf->ipv6_addrtype = OLSR_IP6T_UNIQUELOCAL;
477 } else if (0 == strcasecmp("global", p_next[1])) {
478 new_if->cnf->ipv6_addrtype = OLSR_IP6T_GLOBAL;
480 new_if->cnf->ipv6_addrtype = OLSR_IP6T_AUTO;
482 PARSER_DEBUG_PRINTF("\tIPv6 addrtype: %d\n", new_if->cnf->ipv6_addrtype);
483 } else if (0 == strcasecmp("Ip6MulticastSite", p_next[0])) {
484 union olsr_ip_addr ipaddr;
485 if (inet_pton(AF_INET6, p_next[1], &ipaddr) <= 0) {
486 sprintf(rmsg, "Failed converting IP address %s\n", p_next[1]);
487 parse_tok_free(tok_next);
491 new_if->cnf->ipv6_multi_site = ipaddr;
492 PARSER_DEBUG_PRINTF("\tIPv6 site-local multicast: %s\n", ip6_to_string(&buf, &new_if->cnf->ipv6_multi_site.v6));
493 } else if (0 == strcasecmp("Ip6MulticastGlobal", p_next[0])) {
494 union olsr_ip_addr ipaddr;
495 if (inet_pton(AF_INET6, p_next[1], &ipaddr) <= 0) {
496 sprintf(rmsg, "Failed converting IP address %s\n", p_next[1]);
497 parse_tok_free(tok_next);
501 new_if->cnf->ipv6_multi_glbl = ipaddr;
502 PARSER_DEBUG_PRINTF("\tIPv6 global multicast: %s\n", ip6_to_string(&buf, &new_if->cnf->ipv6_multi_glbl.v6));
503 } else if (0 == strcasecmp("HelloInterval", p_next[0])) {
504 new_if->cnf->hello_params.emission_interval = olsr_txt_to_milli(p_next[1]);
505 PARSER_DEBUG_PRINTF("\tHELLO interval1: %u ms\n", new_if->cnf->hello_params.emission_interval);
506 } else if (0 == strcasecmp("HelloValidityTime", p_next[0])) {
507 new_if->cnf->hello_params.validity_time = olsr_txt_to_milli(p_next[1]);
508 PARSER_DEBUG_PRINTF("\tHELLO validity: %u ms\n", new_if->cnf->hello_params.validity_time);
509 } else if (0 == strcasecmp("Tcinterval", p_next[0])) {
510 new_if->cnf->tc_params.emission_interval = olsr_txt_to_milli(p_next[1]);
511 PARSER_DEBUG_PRINTF("\tTC interval1: %u ms\n", new_if->cnf->tc_params.emission_interval);
512 } else if (0 == strcasecmp("TcValidityTime", p_next[0])) {
513 new_if->cnf->tc_params.validity_time = olsr_txt_to_milli(p_next[1]);
514 PARSER_DEBUG_PRINTF("\tTC validity: %u ms\n", new_if->cnf->tc_params.validity_time);
515 } else if (0 == strcasecmp("Midinterval", p_next[0])) {
516 new_if->cnf->mid_params.emission_interval = olsr_txt_to_milli(p_next[1]);
517 PARSER_DEBUG_PRINTF("\tMID interval1: %u ms\n", new_if->cnf->mid_params.emission_interval);
518 } else if (0 == strcasecmp("MidValidityTime", p_next[0])) {
519 new_if->cnf->mid_params.validity_time = olsr_txt_to_milli(p_next[1]);
520 PARSER_DEBUG_PRINTF("\tMID validity: %u ms\n", new_if->cnf->mid_params.validity_time);
521 } else if (0 == strcasecmp("Hnainterval", p_next[0])) {
522 new_if->cnf->hna_params.emission_interval = olsr_txt_to_milli(p_next[1]);
523 PARSER_DEBUG_PRINTF("\tHNA interval1: %u ms\n", new_if->cnf->hna_params.emission_interval);
524 } else if (0 == strcasecmp("HnaValidityTime", p_next[0])) {
525 new_if->cnf->hna_params.validity_time = olsr_txt_to_milli(p_next[1]);
526 PARSER_DEBUG_PRINTF("\tHNA validity: %u ms\n", new_if->cnf->hna_params.validity_time);
527 } else if (0 == strcasecmp("Weight", p_next[0])) {
528 new_if->cnf->weight.fixed = true;
529 PARSER_DEBUG_PRINTF("\tFixed willingness: %d\n", new_if->cnf->weight.value);
530 } else if (0 == strcasecmp("LinkQualityMult", p_next[0])) {
532 struct olsr_lq_mult *mult = olsr_malloc(sizeof(*mult), "lqmult");
534 sprintf(rmsg, "Odd args in %s\n", nxt);
535 parse_tok_free(tok_next);
539 memset(&mult->addr, 0, sizeof(mult->addr));
540 if (0 != strcasecmp("default", p_next[1])) {
541 if (inet_pton(rcfg->ip_version, p_next[1], &mult->addr) <= 0) {
542 sprintf(rmsg, "Failed converting IP address %s\n", p_next[1]);
543 parse_tok_free(tok_next);
549 sscanf(p_next[2], "%f", &f);
550 mult->value = (uint32_t) (f * LINK_LOSS_MULTIPLIER);
551 mult->next = new_if->cnf->lq_mult;
552 new_if->cnf->lq_mult = mult;
553 PARSER_DEBUG_PRINTF("\tLinkQualityMult %s %0.2f\n", ip_to_string(rcfg->ip_version, &buf, &mult->addr),
554 (float)mult->value / LINK_LOSS_MULTIPLIER);
557 sprintf(rmsg, "Unknown arg: %s %s\n", p_next[0], p_next[1]);
558 parse_tok_free(tok_next);
566 parse_tok_free(tok_next);
570 sprintf(rmsg, "Error in %s\n", argstr);
577 * Parses a single ipc option block
578 * @argstr: arguments string
579 * @rcfg: config struct to write/change values into
580 * @rmsg: a buf[FILENAME_MAX + 256] to sprint err msgs
581 * @returns configuration status as defined in olsr_parse_cfg_result
583 static olsr_parse_cfg_result
584 parse_cfg_ipc(char *argstr, struct olsr_config *rcfg, char *rmsg)
589 struct ipaddr_str buf;
591 if ('{' != *argstr) {
592 sprintf(rmsg, "No {}\n");
595 if (NULL != (tok = parse_tok(argstr + 1, &nxt))) {
599 sprintf(rmsg, "Odd args in %s\n", argstr);
603 if (0 == strcasecmp("Host", p[0])) {
604 union olsr_ip_addr ipaddr;
605 if (inet_pton(rcfg->ip_version, p[1], &ipaddr) <= 0) {
606 sprintf(rmsg, "Failed converting IP address %s\n", p[0]);
611 ip_acl_add(&rcfg->ipc_nets, &ipaddr, 8 * rcfg->ipsize, false);
612 PARSER_DEBUG_PRINTF("\tIPC host: %s\n", ip_to_string(rcfg->ip_version, &buf, &ipaddr));
613 } else if (0 == strcasecmp("Net", p[0])) {
614 union olsr_ip_addr ipaddr;
616 sprintf(rmsg, "Odd args in %s\n", nxt);
620 if (inet_pton(rcfg->ip_version, p[1], &ipaddr) <= 0) {
621 sprintf(rmsg, "Failed converting IP address %s\n", p[0]);
625 if (AF_INET == rcfg->ip_version) {
626 union olsr_ip_addr netmask;
627 if (inet_pton(AF_INET, p[2], &netmask) <= 0) {
628 sprintf(rmsg, "Failed converting IP address %s\n", p[2]);
632 if ((ipaddr.v4.s_addr & ~netmask.v4.s_addr) != 0) {
633 sprintf(rmsg, "The IP address %s/%s is not a network address!\n", p[1], p[2]);
637 ip_acl_add(&rcfg->ipc_nets, &ipaddr, netmask_to_prefix(netmask.v6.s6_addr, rcfg->ipsize), false);
638 PARSER_DEBUG_PRINTF("\tIPC net: %s/%d\n", ip_to_string(rcfg->ip_version, &buf, &ipaddr),
639 netmask_to_prefix(netmask.v6.s6_addr, rcfg->ipsize));
642 sscanf('/' == *p[2] ? p[2] + 1 : p[2], "%d", &prefix);
643 if (0 > prefix || 128 < prefix) {
644 sprintf(rmsg, "Illegal IPv6 prefix %s\n", p[2]);
648 ip_acl_add(&rcfg->ipc_nets, &ipaddr, prefix, false);
649 PARSER_DEBUG_PRINTF("\tIPC net: %s/%d\n", ip_to_string(rcfg->ip_version, &buf, &ipaddr), prefix);
653 sprintf(rmsg, "Unknown arg: %s %s\n", p[0], p[1]);
665 * Parses a single loadplugin option block
666 * @argstr: arguments string
667 * @rcfg: config struct to write/change values into
668 * @rmsg: a buf[FILENAME_MAX + 256] to sprint err msgs
669 * @returns configuration status as defined in olsr_parse_cfg_result
671 static olsr_parse_cfg_result
672 parse_cfg_loadplugin(char *argstr, struct olsr_config *rcfg, char *rmsg)
676 if (NULL != (tok = parse_tok(argstr, &nxt))) {
678 sprintf(rmsg, "No {}\n");
682 char **tok_next = parse_tok(nxt + 1, NULL);
683 struct plugin_entry *pe = olsr_malloc(sizeof(*pe), "plugin");
684 pe->name = olsr_strdup(*tok);
686 pe->next = rcfg->plugins;
688 PARSER_DEBUG_PRINTF("Plugin: %s\n", pe->name);
690 char **p_next = tok_next;
692 struct plugin_param *pp = olsr_malloc(sizeof(*pp), "plparam");
693 if (0 != strcasecmp("PlParam", p_next[0]) || !p_next[1] || !p_next[2]) {
694 sprintf(rmsg, "Odd args in %s\n", nxt);
695 parse_tok_free(tok_next);
699 pp->key = olsr_strdup(p_next[1]);
700 pp->value = olsr_strdup(p_next[2]);
701 pp->next = pe->params;
703 PARSER_DEBUG_PRINTF("\tPlParam: %s %s\n", pp->key, pp->value);
706 parse_tok_free(tok_next);
711 sprintf(rmsg, "Error in %s\n", argstr);
718 * Parses a the parameter string of --log(debug|info|warn|error)
719 * @argstr: arguments string
720 * @rcfg: config struct to write/change values into
721 * @rmsg: a buf[FILENAME_MAX + 256] to sprint err msgs
722 * @returns configuration status as defined in olsr_parse_cfg_result
724 static olsr_parse_cfg_result
725 parse_cfg_debug(char *argstr, struct olsr_config *rcfg, char *rmsg)
728 dlevel = atoi(argstr);
730 if (dlevel < MIN_DEBUGLVL || dlevel > MAX_DEBUGLVL) {
731 sprintf(rmsg, "Error, debug level must be between -2 and 3\n");
738 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
739 rcfg->log_event[SEVERITY_DEBUG][i] = true;
742 /* all info, warnings and errors */
743 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
744 rcfg->log_event[SEVERITY_INFO][i] = true;
747 /* some INFO level output, plus all warnings and errors */
748 rcfg->log_event[SEVERITY_INFO][LOG_2NEIGH] = true;
749 rcfg->log_event[SEVERITY_INFO][LOG_LINKS] = true;
750 rcfg->log_event[SEVERITY_INFO][LOG_MAIN] = true;
751 rcfg->log_event[SEVERITY_INFO][LOG_NEIGHTABLE] = true;
752 rcfg->log_event[SEVERITY_INFO][LOG_PLUGINS] = true;
753 rcfg->log_event[SEVERITY_INFO][LOG_ROUTING] = true;
754 rcfg->log_event[SEVERITY_INFO][LOG_TC] = true;
756 /* errors and warnings */
757 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
758 rcfg->log_event[SEVERITY_WARN][i] = true;
761 /* only error messages */
762 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
763 rcfg->log_event[SEVERITY_ERR][i] = true;
765 default: /* no logging at all ! */
769 PARSER_DEBUG_PRINTF("Debug level: %d\n", dlevel);
775 /* prevent fallback to default 0 */
776 cfg_has_log[SEVERITY_ERR] = true;
781 * Parses a the parameter string of --log(debug|info|warn|error)
782 * @argstr: arguments string
783 * @rcfg: config struct to write/change values into
784 * @rmsg: a buf[FILENAME_MAX + 256] to sprint err msgs
785 * @returns configuration status as defined in olsr_parse_cfg_result
787 static olsr_parse_cfg_result
788 parse_cfg_log(char *argstr, struct olsr_config *rcfg, char *rmsg, enum log_severity sev)
790 char *p = (char *)argstr, *next;
796 next = strchr(p, ',');
801 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
802 if (strcasecmp(p, LOG_SOURCE_NAMES[i]) == 0) {
807 if (i == LOG_SOURCE_COUNT) {
808 sprintf(rmsg, "Error, unknown logging source: %s\n", p);
812 /* handle "all" keyword */
814 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
815 rcfg->log_event[sev][i] = true;
819 rcfg->log_event[sev][i] = true;
825 PARSER_DEBUG_PRINTF("Log_%s:", LOG_SEVERITY_NAMES[sev]);
826 for (i = 0, first = true; i < LOG_SOURCE_COUNT; i++) {
827 if (rcfg->log_event[sev][i]) {
828 PARSER_DEBUG_PRINTF("%c%s", first ? ' ' : ',', LOG_SOURCE_NAMES[i]);
832 PARSER_DEBUG_PRINTF("\n");
833 cfg_has_log[sev] = true;
838 * Parses a single option found on the command line.
839 * @optint: return value of previous getopt_long()
840 * @argstr: argument string provided by getopt_long()
841 * @line: line number (if option is read from file)
842 * @rcfg: config struct to write/change values into
843 * @rmsg: a buf[FILENAME_MAX + 256] to sprint err msgs
844 * @returns configuration status as defined in olsr_parse_cfg_result
846 static olsr_parse_cfg_result
847 parse_cfg_option(const int optint, char *argstr, const int line, struct olsr_config *rcfg, char *rmsg)
850 case 'D': /* delgw */
851 rcfg->del_gws = true;
852 PARSER_DEBUG_PRINTF("del_gws set to %d\n", rcfg->del_gws);
854 case 'i': /* iface */
857 case 'n': /* nofork */
858 rcfg->no_fork = true;
859 PARSER_DEBUG_PRINTF("no_fork set to %d\n", rcfg->no_fork);
861 case 'A': /* AllowNoInt (yes/no) */
862 rcfg->allow_no_interfaces = (0 == strcasecmp("yes", argstr));
863 PARSER_DEBUG_PRINTF("Noint set to %d\n", rcfg->allow_no_interfaces);
865 case 'C': /* ClearScreen (yes/no) */
866 rcfg->clear_screen = (0 == strcasecmp("yes", argstr));
867 PARSER_DEBUG_PRINTF("Clear screen %s\n", rcfg->clear_screen ? "enabled" : "disabled");
869 case 'd': /* DebugLevel (i) */
870 return parse_cfg_debug(argstr, rcfg, rmsg);
872 case 'F': /* FIBMetric (str) */
875 if (NULL != (tok = parse_tok(argstr, NULL))) {
876 if (strcasecmp(*tok, CFG_FIBM_FLAT) == 0) {
877 rcfg->fib_metric = FIBM_FLAT;
878 } else if (strcasecmp(*tok, CFG_FIBM_CORRECT) == 0) {
879 rcfg->fib_metric = FIBM_CORRECT;
880 } else if (strcasecmp(*tok, CFG_FIBM_APPROX) == 0) {
881 rcfg->fib_metric = FIBM_APPROX;
883 sprintf(rmsg, "FIBMetric must be \"%s\", \"%s\", or \"%s\"!\n", CFG_FIBM_FLAT, CFG_FIBM_CORRECT, CFG_FIBM_APPROX);
888 sprintf(rmsg, "Error in %s\n", argstr);
891 PARSER_DEBUG_PRINTF("FIBMetric: %d=%s\n", rcfg->fib_metric, argstr);
894 case '4': /* Hna4 (4body) */
895 return parse_cfg_hna(argstr, AF_INET, rcfg, rmsg);
897 case '6': /* Hna6 (6body) */
898 return parse_cfg_hna(argstr, AF_INET6, rcfg, rmsg);
900 case 'I': /* Interface if1 if2 { ifbody } */
901 return parse_cfg_interface(argstr, rcfg, rmsg);
903 case 'Q': /* IpcConnect (Host,Net,MaxConnections) */
904 return parse_cfg_ipc(argstr, rcfg, rmsg);
906 case 'V': /* IpVersion (i) */
909 sscanf(argstr, "%d", &ver);
911 rcfg->ip_version = AF_INET;
912 rcfg->ipsize = sizeof(struct in_addr);
913 } else if (ver == 6) {
914 rcfg->ip_version = AF_INET6;
915 rcfg->ipsize = sizeof(struct in6_addr);
917 sprintf(rmsg, "IpVersion must be 4 or 6!\n");
921 PARSER_DEBUG_PRINTF("IpVersion: %d\n", rcfg->ip_version);
923 case 'J': /* LinkQualityDijkstraLimit (i,f) */
927 sscanf(argstr, "%d %10s", &limit, t);
928 if (0 <= limit && limit < (1 << (8 * sizeof(rcfg->lq_dlimit))))
929 rcfg->lq_dlimit = limit;
930 rcfg->lq_dinter = olsr_txt_to_milli(t);
931 PARSER_DEBUG_PRINTF("Link quality dijkstra limit %d, %u ms\n", rcfg->lq_dlimit, rcfg->lq_dinter);
934 case 'E': /* LinkQualityFishEye (i) */
937 sscanf(argstr, "%d", &arg);
938 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->lq_fish))))
940 PARSER_DEBUG_PRINTF("Link quality fish eye %d\n", rcfg->lq_fish);
943 case 'p': /* LoadPlugin (soname {PlParams}) */
944 return parse_cfg_loadplugin(argstr, rcfg, rmsg);
946 case 'M': /* MprCoverage (i) */
949 sscanf(argstr, "%d", &arg);
950 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->mpr_coverage))))
951 rcfg->mpr_coverage = arg;
952 PARSER_DEBUG_PRINTF("MPR coverage %d\n", rcfg->mpr_coverage);
955 case 'N': /* NatThreshold (f) */
957 struct millitxt_buf tbuf;
959 rcfg->lq_nat_thresh = olsr_txt_to_milli(argstr);
960 PARSER_DEBUG_PRINTF("NAT threshold %s\n", olsr_milli_to_txt(&tbuf, rcfg->lq_nat_thresh));
963 case 'Y': /* NicChgsPollInt (f) */
964 rcfg->nic_chgs_pollrate = olsr_txt_to_milli(argstr);
965 PARSER_DEBUG_PRINTF("NIC Changes Pollrate %u ms\n", rcfg->nic_chgs_pollrate);
967 case 'T': /* Pollrate (f) */
969 rcfg->pollrate = olsr_txt_to_milli(argstr);
970 PARSER_DEBUG_PRINTF("Pollrate %u ms\n", rcfg->pollrate);
973 case 'q': /* RtProto (i) */
976 sscanf(argstr, "%d", &arg);
977 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->rtproto))))
979 PARSER_DEBUG_PRINTF("RtProto: %d\n", rcfg->rtproto);
982 case 'R': /* RtTableDefault (i) */
985 sscanf(argstr, "%d", &arg);
986 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->rttable_default))))
987 rcfg->rttable_default = arg;
988 PARSER_DEBUG_PRINTF("RtTableDefault: %d\n", rcfg->rttable_default);
991 case 'r': /* RtTable (i) */
994 sscanf(argstr, "%d", &arg);
995 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->rttable))))
997 PARSER_DEBUG_PRINTF("RtTable: %d\n", rcfg->rttable);
1000 case 't': /* TcRedundancy (i) */
1003 sscanf(argstr, "%d", &arg);
1004 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->tc_redundancy))))
1005 rcfg->tc_redundancy = arg;
1006 PARSER_DEBUG_PRINTF("TC redundancy %d\n", rcfg->tc_redundancy);
1009 case 'Z': /* TosValue (i) */
1012 sscanf(argstr, "%d", &arg);
1013 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->tos))))
1015 PARSER_DEBUG_PRINTF("TOS: %d\n", rcfg->tos);
1018 case 'w': /* Willingness (i) */
1021 sscanf(argstr, "%d", &arg);
1022 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->willingness))))
1023 rcfg->willingness = arg;
1024 rcfg->willingness_auto = false;
1025 PARSER_DEBUG_PRINTF("Willingness: %d (no auto)\n", rcfg->willingness);
1028 case CFG_LOG_DEBUG: /* Log (string) */
1029 return parse_cfg_log(argstr, rcfg, rmsg, SEVERITY_DEBUG);
1031 case CFG_LOG_INFO: /* Log (string) */
1032 return parse_cfg_log(argstr, rcfg, rmsg, SEVERITY_INFO);
1034 case CFG_LOG_WARN: /* Log (string) */
1035 return parse_cfg_log(argstr, rcfg, rmsg, SEVERITY_WARN);
1037 case CFG_LOG_ERROR: /* Log (string) */
1038 return parse_cfg_log(argstr, rcfg, rmsg, SEVERITY_ERR);
1040 case CFG_LOG_STDERR:
1041 rcfg->log_target_stderr = true;
1043 case CFG_LOG_SYSLOG:
1044 rcfg->log_target_syslog = true;
1047 rcfg->log_target_file = strdup(argstr);
1050 case 's': /* SourceIpMode (string) */
1051 rcfg->source_ip_mode = (0 == strcasecmp("yes", argstr)) ? 1 : 0;
1052 PARSER_DEBUG_PRINTF("Source IP mode %s\n", rcfg->source_ip_mode ? "enabled" : "disabled");
1054 case 'o': /* Originator Address (ip) */
1055 if (inet_pton(AF_INET, argstr, &rcfg->router_id) <= 0) {
1056 sprintf(rmsg, "Failed converting IP address %s for originator address\n", argstr);
1059 rcfg->fixed_origaddr = true;
1061 case CFG_OLSRPORT: /* port (i) */
1064 sscanf(argstr, "%d", &arg);
1065 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->olsr_port))))
1066 rcfg->olsr_port = arg;
1067 PARSER_DEBUG_PRINTF("OLSR port: %d\n", rcfg->olsr_port);
1071 rcfg->dlPath = strdup(argstr);
1072 PARSER_DEBUG_PRINTF("Dynamic library path: %s\n", rcfg->dlPath);
1077 sscanf(argstr, "%d", &arg);
1078 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->comport_http))))
1079 rcfg->comport_http = arg;
1080 PARSER_DEBUG_PRINTF("HTTP port: %d\n", rcfg->comport_http);
1086 sscanf(argstr, "%d", &arg);
1087 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->comport_http_limit))))
1088 rcfg->comport_http_limit = arg;
1089 PARSER_DEBUG_PRINTF("HTTP connection limit: %d\n", rcfg->comport_http_limit);
1095 sscanf(argstr, "%d", &arg);
1096 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->comport_txt))))
1097 rcfg->comport_txt = arg;
1098 PARSER_DEBUG_PRINTF("TXT port: %d\n", rcfg->comport_txt);
1104 sscanf(argstr, "%d", &arg);
1105 if (0 <= arg && arg < (1 << (8 * sizeof(rcfg->comport_txt_limit))))
1106 rcfg->comport_txt_limit = arg;
1107 PARSER_DEBUG_PRINTF("TXT connection limit: %d\n", rcfg->comport_txt_limit);
1111 sprintf(rmsg, "Unknown arg in line %d.\n", line);
1118 * Parses command line options using the getopt() runtime
1119 * function. May also replace a "-f filename" combination
1120 * with options read in from a config file.
1122 * @argc: the argv count from main() - or zero if no argv
1123 * @argv: the array of strings provided from the enviroment
1124 * @file: the default config file name (used if argc <= 1)
1125 * @rmsg: to provide buf[FILENAME_MAX + 256] to sprint err msgs
1126 * @rcfg: returns a valid config pointer, clean with olsr_free_cfg()
1127 * @returns a parsing status result code
1129 olsr_parse_cfg_result
1130 olsr_parse_cfg(int argc, char *argv[], const char *file, char *rmsg, struct olsr_config ** rcfg)
1136 char **opt_argv = olsr_malloc(argc * sizeof(opt_argv[0]), "opt_argv");
1137 int *opt_line = olsr_malloc(argc * sizeof(opt_line[0]), "opt_line");
1138 olsr_parse_cfg_result rslt = CFG_OK;
1141 * Original cmd line params
1144 * -delgw (-> --delgw)
1145 * -dispin (-> --dispin)
1146 * -dispout (-> --dispout)
1147 * -d (level) (preserved)
1148 * -f (config) (preserved)
1149 * -hemu (queue_if(hcif01)) (-> --hemu)
1152 * -i if0 if1... (see comment below)
1153 * -int (WIN32) (preserved)
1154 * -ipc (ipc conn = 1) (-> --ipc)
1155 * -ipv6 (-> -V or --IpVersion)
1156 * -lqa (lq aging) (removed)
1157 * -lql (lq lev) (removed)
1158 * -lqnt (lq nat) (removed)
1160 * -multi (ipv6 mcast) (removed)
1161 * -nofork (preserved)
1163 * -T (pollrate) (preserved)
1165 * Note: Remaining args are interpreted as list of
1166 * interfaces. For this reason, '-i' is ignored which
1167 * adds the following non-minus args to the list.
1171 static struct option long_options[] = {
1172 {"config", required_argument, 0, 'f'}, /* (filename) */
1173 {"delgw", no_argument, 0, 'D'},
1174 {"help", optional_argument, 0, 'h'},
1175 {"iface", no_argument, 0, 'i'}, /* if0 if1... */
1177 {"int", no_argument, 0, 'l'},
1179 {"ipc", no_argument, 0, 'P'},
1180 {"log_debug", required_argument, 0, CFG_LOG_DEBUG}, /* src1,src2,... */
1181 {"log_info", required_argument, 0, CFG_LOG_INFO}, /* src1,src2,... */
1182 {"log_warn", required_argument, 0, CFG_LOG_WARN}, /* src1,src2,... */
1183 {"log_error", required_argument, 0, CFG_LOG_ERROR}, /* src1,src2,... */
1184 {"log_stderr", no_argument, 0, CFG_LOG_STDERR},
1185 {"log_syslog", no_argument, 0, CFG_LOG_SYSLOG},
1186 {"log_file", required_argument, 0, CFG_LOG_FILE}, /* (filename) */
1187 {"nofork", no_argument, 0, 'n'},
1188 {"version", no_argument, 0, 'v'},
1189 {"AllowNoInt", required_argument, 0, 'A'}, /* (yes/no) */
1190 {"ClearScreen", required_argument, 0, 'C'}, /* (yes/no) */
1191 {"DebugLevel", required_argument, 0, 'd'}, /* (i) */
1192 {"FIBMetric", required_argument, 0, 'F'}, /* (str) */
1193 {"Hna4", required_argument, 0, '4'}, /* (4body) */
1194 {"Hna6", required_argument, 0, '6'}, /* (6body) */
1195 {"Interface", required_argument, 0, 'I'}, /* (if1 if2 {ifbody}) */
1196 {"IpVersion", required_argument, 0, 'V'}, /* (i) */
1197 {"LinkQualityDijkstraLimit", required_argument, 0, 'J'}, /* (i,f) */
1198 {"LinkQualityFishEye", required_argument, 0, 'E'}, /* (i) */
1199 {"LoadPlugin", required_argument, 0, 'p'}, /* (soname {PlParams}) */
1200 {"MprCoverage", required_argument, 0, 'M'}, /* (i) */
1201 {"NatThreshold", required_argument, 0, 'N'}, /* (f) */
1202 {"NicChgsPollInt", required_argument, 0, 'Y'}, /* (f) */
1203 {"Pollrate", required_argument, 0, 'T'}, /* (f) */
1204 {"RtProto", required_argument, 0, 'q'}, /* (i) */
1205 {"RtTableDefault", required_argument, 0, 'R'}, /* (i) */
1206 {"RtTable", required_argument, 0, 'r'}, /* (i) */
1207 {"TcRedundancy", required_argument, 0, 't'}, /* (i) */
1208 {"TosValue", required_argument, 0, 'Z'}, /* (i) */
1209 {"Willingness", required_argument, 0, 'w'}, /* (i) */
1210 {"RouterId", required_argument, 0, 'o'}, /* (ip) */
1211 {"SourceIpMode", required_argument, 0, 's'}, /* (yes/no) */
1212 {"OlsrPort", required_argument, 0, CFG_OLSRPORT}, /* (i) */
1213 {"dlPath", required_argument, 0, CFG_DLPATH}, /* (path) */
1214 {"HttpPort", required_argument, 0, CFG_HTTPPORT}, /* (i) */
1215 {"HttpLimit", required_argument, 0, CFG_HTTPLIMIT}, /* (i) */
1216 {"TxtPort", required_argument, 0, CFG_TXTPORT}, /* (i) */
1217 {"TxtLimit", required_argument, 0, CFG_TXTLIMIT}, /* (i) */
1219 {"IpcConnect", required_argument, 0, 0 }, /* ignored */
1220 {"UseHysteresis", required_argument, 0, 0 }, /* ignored */
1221 {"HystScaling", required_argument, 0, 0 }, /* ignored */
1222 {"HystThrHigh", required_argument, 0, 0 }, /* ignored */
1223 {"HystThrLow", required_argument, 0, 0 }, /* ignored */
1224 {"LinkQualityLevel", required_argument, 0, 0 }, /* ignored */
1225 {"LinkQualityWinsize", required_argument, 0, 0 }, /* ignored */
1226 {"LinkQualityAlgorithm", required_argument, 0, 0 }, /* ignored */
1227 {"LinkQualityAging", required_argument, 0, 0 }, /* ignored */
1228 {"dispout", no_argument, 0, 0 }, /* ignored */
1229 {"dispin", no_argument, 0, 0 }, /* ignored */
1231 }, *popt = long_options;
1235 * olsr_malloc() uses calloc, so opt_line is already filled
1236 * memset(opt_line, 0, argc * sizeof(opt_line[0]));
1239 /* cleanup static logsource flags */
1240 cfg_has_log[SEVERITY_DEBUG] = false;
1241 cfg_has_log[SEVERITY_INFO] = false;
1242 cfg_has_log[SEVERITY_WARN] = false;
1243 cfg_has_log[SEVERITY_ERR] = false;
1245 /* Copy argv array for safe free'ing later on */
1246 while (opt_argc < argc) {
1247 const char *p = argv[opt_argc];
1248 if (0 == strcasecmp(p, "-nofork"))
1251 else if (0 == strcasecmp(p, "-int"))
1254 opt_argv[opt_argc] = olsr_strdup(p);
1258 /* get option count */
1259 for (opt_idx = 0; long_options[opt_idx].name; opt_idx++);
1261 /* Calculate short option string */
1262 opt_str = olsr_malloc(opt_idx * 3, "create short opt_string");
1264 while (popt->name) {
1265 if (popt->val > 0 && popt->val < 128) {
1266 opt_str[opt_idx++] = popt->val;
1268 switch (popt->has_arg) {
1269 case optional_argument:
1270 opt_str[opt_idx++] = ':';
1272 case required_argument:
1273 opt_str[opt_idx++] = ':';
1281 * If no arguments, revert to default behaviour
1284 if (1 >= opt_argc) {
1285 char *argv0_tmp = opt_argv[0];
1287 opt_argv = olsr_malloc(3 * sizeof(opt_argv[0]), "default argv");
1288 opt_argv[0] = argv0_tmp;
1289 opt_argv[1] = olsr_strdup("-f");
1290 opt_argv[2] = olsr_strdup(file);
1295 *rcfg = olsr_get_default_cfg();
1297 while (0 <= (opt = getopt_long(opt_argc, opt_argv, opt_str, long_options, &opt_idx))) {
1300 sprintf(rmsg, "Ignored deprecated %s\n", long_options[opt_idx].name);
1303 case 'f': /* config (filename) */
1304 PARSER_DEBUG_PRINTF("Read config from %s\n", optarg);
1305 if (0 > read_cfg(optarg, &opt_argc, &opt_argv, &opt_line)) {
1306 sprintf(rmsg, "Could not read specified config file %s!\n%s", optarg, strerror(errno));
1311 case 'l': /* win32: list ifaces */
1316 case 'v': /* version */
1317 fprintf(stderr, "*** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", olsrd_version, build_date, build_host);
1320 case 'h': /* help */
1321 popt = long_options;
1322 printf("Usage: olsrd [OPTIONS]... [interfaces]...\n");
1323 while (popt->name) {
1325 if (popt->val > 0 && popt->val < 128) {
1326 printf("-%c or --%s ", popt->val, popt->name);
1328 printf(" --%s ", popt->name);
1330 switch (popt->has_arg) {
1331 case required_argument:
1334 case optional_argument:
1342 if (optarg == NULL) {
1343 printf("Use '--help=log'for help about the available logging sources\n");
1344 } else if (strcasecmp(optarg, "log") == 0) {
1347 printf("Log sources for --log_debug, --log_info, --log_warn and --log_error:\n");
1348 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
1349 printf("\t%s\n", LOG_SOURCE_NAMES[i]);
1355 rslt = parse_cfg_option(opt, optarg, opt_line[optind], *rcfg, rmsg);
1356 if (rslt != CFG_OK) {
1360 } /* while getopt_long() */
1362 while (optind < opt_argc) {
1363 PARSER_DEBUG_PRINTF("new interface %s\n", opt_argv[optind]);
1364 queue_if(opt_argv[optind++], *rcfg);
1368 while (0 < opt_argc) {
1369 free(opt_argv[--opt_argc]);
1375 /* logging option post processing */
1376 if (rslt != CFG_ERROR && rslt != CFG_EXIT) {
1377 if (!((*rcfg)->log_target_syslog || (*rcfg)->log_target_syslog || (*rcfg)->log_target_file != NULL)) {
1378 (*rcfg)->log_target_stderr = true;
1379 PARSER_DEBUG_PRINTF("Log: activate default logging target stderr\n");
1381 for (opt = SEVERITY_INFO; opt < LOG_SEVERITY_COUNT; opt++) {
1382 if (!cfg_has_log[opt] && cfg_has_log[opt - 1]) {
1385 PARSER_DEBUG_PRINTF("Log: copy log level %s to %s\n", LOG_SEVERITY_NAMES[opt - 1], LOG_SEVERITY_NAMES[opt]);
1387 /* copy debug to info, info to warning, warning to error (if neccessary) */
1388 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
1389 (*rcfg)->log_event[opt][i] = (*rcfg)->log_event[opt - 1][i];
1391 cfg_has_log[opt] = true;
1394 if (!cfg_has_log[SEVERITY_ERR]) {
1395 /* no logging at all defined ? fall back to default */
1396 char def[10] = DEF_DEBUGLVL;
1397 parse_cfg_debug(def, *rcfg, rmsg);
1404 * Checks a given config for illegal values
1407 olsr_sanity_check_cfg(struct olsr_config *cfg)
1409 struct olsr_if_config *in = cfg->if_configs;
1410 struct olsr_if_options *io;
1411 struct millitxt_buf tbuf;
1414 if (cfg->ip_version != AF_INET && cfg->ip_version != AF_INET6) {
1415 fprintf(stderr, "Ipversion %d not allowed!\n", cfg->ip_version);
1420 if (cfg->tos > MAX_TOS) {
1421 fprintf(stderr, "TOS %d is not allowed\n", cfg->tos);
1426 if (cfg->willingness_auto == false && (cfg->willingness > MAX_WILLINGNESS)) {
1427 fprintf(stderr, "Willingness %d is not allowed\n", cfg->willingness);
1431 /* Check Link quality dijkstra limit */
1432 if (cfg->lq_dinter < cfg->pollrate && cfg->lq_dlimit != 255) {
1433 fprintf(stderr, "Link quality dijkstra limit must be higher than pollrate\n");
1437 /* NIC Changes Pollrate */
1438 if (cfg->nic_chgs_pollrate < MIN_NICCHGPOLLRT || cfg->nic_chgs_pollrate > MAX_NICCHGPOLLRT) {
1439 fprintf(stderr, "NIC Changes Pollrate %u ms is not allowed\n", cfg->nic_chgs_pollrate);
1444 if (cfg->tc_redundancy > MAX_TC_REDUNDANCY) {
1445 fprintf(stderr, "TC redundancy %d is not allowed\n", cfg->tc_redundancy);
1450 if (cfg->mpr_coverage < MIN_MPR_COVERAGE || cfg->mpr_coverage > MAX_MPR_COVERAGE) {
1451 fprintf(stderr, "MPR coverage %d is not allowed\n", cfg->mpr_coverage);
1455 /* NAT threshold value */
1456 if (cfg->lq_nat_thresh < 100 || cfg->lq_nat_thresh > 1000) {
1457 fprintf(stderr, "NAT threshold %s is not allowed\n", olsr_milli_to_txt(&tbuf, cfg->lq_nat_thresh));
1461 /* Source ip mode need fixed router id */
1462 if (0 == memcmp(&all_zero, &cfg->router_id, sizeof(cfg->router_id)) && cfg->source_ip_mode) {
1463 fprintf(stderr, "You cannot use source ip routing without setting a fixed router id\n");
1467 /* check OLSR port */
1468 if (cfg->olsr_port == 0) {
1469 fprintf(stderr, "0 is not a valid UDP port\n");
1474 fprintf(stderr, "No interfaces configured!\n");
1482 if (in->name == NULL || !strlen(in->name)) {
1483 fprintf(stderr, "Interface has no name!\n");
1488 fprintf(stderr, "Interface %s has no configuration!\n", in->name);
1492 /* HELLO interval */
1494 if (io->hello_params.emission_interval < cfg->pollrate ||
1495 io->hello_params.emission_interval > io->hello_params.validity_time) {
1496 fprintf(stderr, "Bad HELLO parameters! (em: %u ms, vt: %u ms)\n",
1497 io->hello_params.emission_interval,
1498 io->hello_params.validity_time);
1503 if (io->tc_params.emission_interval < cfg->pollrate ||
1504 io->tc_params.emission_interval > io->tc_params.validity_time) {
1505 fprintf(stderr, "Bad TC parameters! (em: %u ms, vt: %u ms)\n",
1506 io->tc_params.emission_interval,
1507 io->tc_params.validity_time);
1512 if (io->mid_params.emission_interval < cfg->pollrate ||
1513 io->mid_params.emission_interval > io->mid_params.validity_time) {
1514 fprintf(stderr, "Bad MID parameters! (em: %u ms, vt: %u ms)\n",
1515 io->mid_params.emission_interval,
1516 io->mid_params.validity_time);
1521 if (io->hna_params.emission_interval < cfg->pollrate ||
1522 io->hna_params.emission_interval > io->hna_params.validity_time) {
1523 fprintf(stderr, "Bad HNA parameters! (em: %u ms, vt: %u ms)\n",
1524 io->hna_params.emission_interval,
1525 io->hna_params.validity_time);
1536 * Free resources occupied by a configuration
1539 olsr_free_cfg(struct olsr_config *cfg)
1541 struct olsr_if_config *ind, *in = cfg->if_configs;
1542 struct plugin_entry *ped, *pe = cfg->plugins;
1543 struct olsr_lq_mult *mult, *next_mult;
1545 /* free logfile string if necessary */
1546 if (cfg->log_target_file) {
1547 free(cfg->log_target_file);
1550 /* free dynamic library path */
1558 ip_prefix_list_flush(&cfg->hna_entries);
1563 ip_acl_flush(&cfg->ipc_nets);
1566 * Free Interfaces - remove_interface() already called
1569 for (mult = in->cnf->lq_mult; mult != NULL; mult = next_mult) {
1570 next_mult = mult->next;
1584 * Free Plugins - olsr_close_plugins() allready called
1587 struct plugin_param *pard, *par = pe->params;
1607 * Get a default config
1609 struct olsr_config *
1610 olsr_get_default_cfg(void)
1613 struct olsr_config *cfg = olsr_malloc(sizeof(struct olsr_config), "default config");
1615 cfg->ip_version = AF_INET;
1616 cfg->ipsize = sizeof(struct in_addr);
1618 assert(cfg->no_fork == false);
1619 cfg->allow_no_interfaces = DEF_ALLOW_NO_INTS;
1620 cfg->willingness_auto = DEF_WILL_AUTO;
1621 cfg->clear_screen = DEF_CLEAR_SCREEN;
1622 assert(cfg->del_gws == false);
1623 assert(cfg->fixed_origaddr == false);
1626 assert(cfg->rtproto == 0);
1628 assert(cfg->rttable_default == 0);
1629 cfg->fib_metric = DEF_FIB_METRIC;
1631 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
1632 assert(cfg->log_event[SEVERITY_DEBUG][i] == false);
1633 assert(cfg->log_event[SEVERITY_INFO][i] == false);
1634 assert(cfg->log_event[SEVERITY_WARN][i] == false);
1635 assert(cfg->log_event[SEVERITY_ERR][i] == false);
1637 cfg->log_target_stderr = true;
1638 assert(cfg->log_target_file == NULL);
1639 assert(cfg->log_target_syslog == false);
1641 assert(cfg->plugins == NULL);
1642 list_head_init(&cfg->hna_entries);
1643 ip_acl_init(&cfg->ipc_nets);
1644 assert(cfg->if_configs == NULL);
1646 cfg->pollrate = DEF_POLLRATE;
1647 cfg->nic_chgs_pollrate = DEF_NICCHGPOLLRT;
1648 cfg->lq_nat_thresh = DEF_LQ_NAT_THRESH;
1649 cfg->tc_redundancy = TC_REDUNDANCY;
1650 cfg->mpr_coverage = MPR_COVERAGE;
1651 cfg->lq_fish = DEF_LQ_FISH;
1652 cfg->lq_dinter = DEF_LQ_DIJK_INTER;
1653 cfg->lq_dlimit = DEF_LQ_DIJK_LIMIT;
1654 assert(cfg->willingness == 0);
1656 cfg->olsr_port = OLSRPORT;
1657 assert(cfg->dlPath == NULL);
1659 cfg->comport_http = DEF_HTTPPORT;
1660 cfg->comport_http_limit = DEF_HTTPLIMIT;
1661 cfg->comport_txt = DEF_TXTPORT;
1662 cfg->comport_txt_limit = DEF_TXTLIMIT;
1664 assert(0 == memcmp(&all_zero, &cfg->router_id, sizeof(cfg->router_id)));
1665 assert(0 == cfg->source_ip_mode);
1666 cfg->will_int = 10 * HELLO_INTERVAL;
1667 cfg->exit_value = EXIT_SUCCESS;
1669 assert(cfg->ioctl_s == 0);
1671 assert(cfg->rts_linux == 0);
1673 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
1674 assert(cfg->rts_bsd == 0);
1683 * indent-tabs-mode: nil