fixes for the rt-policy settings, lot's of sanity check changes, new defaults
[olsrd.git] / src / cfgparser / olsrd_conf.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 "olsrd_conf.h"
43 #include "ipcalc.h"
44 #include "olsr_cfg.h"
45 #include "defs.h"
46 #include "net_olsr.h"
47 #include "olsr.h"
48
49 #include <assert.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <errno.h>
53 #include <stdlib.h>
54 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <netinet/in.h>
57 #include <arpa/inet.h>
58 #ifdef linux
59 #include <linux/types.h>
60 #include <linux/rtnetlink.h>
61 #include <linux/version.h>
62 #endif
63
64 extern FILE *yyin;
65 extern int yyparse(void);
66
67 static char interface_defaults_name[] = "[InterfaceDefaults]";
68
69 const char *FIB_METRIC_TXT[] = {
70   "flat",
71   "correct",
72   "approx",
73 };
74
75 const char *GW_UPLINK_TXT[] = {
76   "none",
77   "ipv4",
78   "ipv6",
79   "both"
80 };
81
82 const char *OLSR_IF_MODE[] = {
83   "mesh",
84   "ether"
85 };
86
87 static char copyright_string[] __attribute__ ((unused)) =
88   "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
89
90 int current_line;
91
92 /* Global stuff externed in defs.h */
93 FILE *debug_handle;                    /* Where to send debug(defaults to stdout) */
94 struct olsrd_config *olsr_cnf;         /* The global configuration */
95
96 #ifdef MAKEBIN
97
98 /* Build as standalone binary */
99 int
100 main(int argc, char *argv[])
101 {
102   struct olsrd_config *cnf;
103
104   if (argc == 1) {
105     fprintf(stderr, "Usage: olsrd_cfgparser [filename] -print\n\n");
106     exit(EXIT_FAILURE);
107   }
108
109   if ((cnf = olsrd_parse_cnf(argv[1])) != NULL) {
110     if ((argc > 2) && (!strcmp(argv[2], "-print"))) {
111       olsrd_print_cnf(cnf);
112       olsrd_write_cnf(cnf, "./out.conf");
113     } else
114       printf("Use -print to view parsed values\n");
115     printf("Configfile parsed OK\n");
116   } else {
117     printf("Failed parsing \"%s\"\n", argv[1]);
118   }
119
120   return 0;
121 }
122
123 #else
124
125 /* Build as part of olsrd */
126
127 #endif
128
129 int
130 olsrd_parse_cnf(const char *filename)
131 {
132   struct olsr_if *in, *new_ifqueue;
133   int rc;
134
135   fprintf(stderr, "Parsing file: \"%s\"\n", filename);
136
137   yyin = fopen(filename, "r");
138   if (yyin == NULL) {
139     fprintf(stderr, "Cannot open configuration file '%s': %s.\n", filename, strerror(errno));
140     return -1;
141   }
142
143   current_line = 1;
144   rc = yyparse();
145   fclose(yyin);
146   if (rc != 0) {
147     return -1;
148   }
149
150   /* Reverse the queue (added by user request) */
151   in = olsr_cnf->interfaces;
152   new_ifqueue = NULL;
153
154   while (in) {
155     struct olsr_if *in_tmp = in;
156     in = in->next;
157
158     in_tmp->next = new_ifqueue;
159     new_ifqueue = in_tmp;
160   }
161
162   olsr_cnf->interfaces = new_ifqueue;
163
164   for (in = olsr_cnf->interfaces; in != NULL; in = in->next) {
165     /* set various stuff */
166     in->configured = false;
167     in->interf = NULL;
168     in->host_emul = false;
169   }
170   return 0;
171 }
172
173 /* prints an interface (and checks it againt the default config) and the inverted config */
174 static void
175 olsrd_print_interface_cnf(struct if_config_options *cnf, struct if_config_options *cnfi, bool defcnf)
176 {
177   struct olsr_lq_mult *mult;
178   int lq_mult_cnt = 0;
179   char ipv6_buf[INET6_ADDRSTRLEN];                  /* buffer for IPv6 inet_htop */
180
181   if (cnf->ipv4_multicast.v4.s_addr) {
182     printf("\tIPv4 broadcast/multicast : %s%s\n", inet_ntoa(cnf->ipv4_multicast.v4),DEFAULT_STR(ipv4_multicast.v4.s_addr));
183   } else {
184     printf("\tIPv4 broadcast/multicast : AUTO%s\n",DEFAULT_STR(ipv4_multicast.v4.s_addr));
185   }
186
187   if (cnf->mode==IF_MODE_ETHER){
188     printf("\tMode           : ether%s\n",DEFAULT_STR(mode));
189   } else {
190     printf("\tMode           : mesh%s\n",DEFAULT_STR(mode));
191   }
192
193   printf("\tIPv6 multicast           : %s%s\n", inet_ntop(AF_INET6, &cnf->ipv6_multicast.v6, ipv6_buf, sizeof(ipv6_buf)),DEFAULT_STR(ipv6_multicast.v6));
194
195   printf("\tHELLO emission/validity  : %0.2f%s/%0.2f%s\n", cnf->hello_params.emission_interval, DEFAULT_STR(hello_params.emission_interval),
196          cnf->hello_params.validity_time,DEFAULT_STR(hello_params.validity_time));
197   printf("\tTC emission/validity     : %0.2f%s/%0.2f%s\n", cnf->tc_params.emission_interval, DEFAULT_STR(tc_params.emission_interval),
198          cnf->tc_params.validity_time,DEFAULT_STR(tc_params.validity_time));
199   printf("\tMID emission/validity    : %0.2f%s/%0.2f%s\n", cnf->mid_params.emission_interval, DEFAULT_STR(mid_params.emission_interval),
200          cnf->mid_params.validity_time,DEFAULT_STR(mid_params.validity_time));
201   printf("\tHNA emission/validity    : %0.2f%s/%0.2f%s\n", cnf->hna_params.emission_interval, DEFAULT_STR(hna_params.emission_interval),
202          cnf->hna_params.validity_time,DEFAULT_STR(hna_params.validity_time));
203
204   for (mult = cnf->lq_mult; mult != NULL; mult = mult->next) {
205     lq_mult_cnt++;
206     printf("\tLinkQualityMult          : %s %0.2f %s\n", inet_ntop(olsr_cnf->ip_version, &mult->addr, ipv6_buf, sizeof(ipv6_buf)),
207       (float)(mult->value) / 65536.0, ((lq_mult_cnt > cnf->orig_lq_mult_cnt)?" (d)":""));
208   }
209
210   printf("\tAutodetect changes       : %s%s\n", cnf->autodetect_chg ? "yes" : "no",DEFAULT_STR(autodetect_chg));
211 }
212
213 static int olsrd_sanity_check_rtpolicy(struct olsrd_config *cnf) {
214   int prio;
215
216 #ifdef linux
217   /* calculate rt_policy defaults if necessary */
218   if (!cnf->smart_gw_active) {
219     /* default is "no policy rules" and "everything into the main table" */
220     if (cnf->rt_table == DEF_RT_AUTO) {
221       cnf->rt_table = 254;
222     }
223     if (cnf->rt_table_default == DEF_RT_AUTO) {
224       cnf->rt_table_default = cnf->rt_table;
225     }
226     if (cnf->rt_table_tunnel != DEF_RT_AUTO) {
227       fprintf(stderr, "Warning, setting a table for tunnels without SmartGW does not make sense.\n");
228     }
229     cnf->rt_table_tunnel = cnf->rt_table_default;
230
231     /* priority rules default is "none" */
232     if (cnf->rt_table_pri == DEF_RT_AUTO) {
233       cnf->rt_table_pri = DEF_RT_NONE;
234     }
235     if (cnf->rt_table_defaultolsr_pri == DEF_RT_AUTO) {
236       cnf->rt_table_defaultolsr_pri = DEF_RT_NONE;
237     }
238     if (cnf->rt_table_tunnel_pri == DEF_RT_AUTO) {
239       cnf->rt_table_tunnel_pri = DEF_RT_NONE;
240     }
241     if (cnf->rt_table_default_pri == DEF_RT_AUTO) {
242       cnf->rt_table_default_pri = DEF_RT_NONE;
243     }
244   }
245   else {
246     /* default is "policy rules" and "everything into separate tables (254, 223, 224)" */
247     if (cnf->rt_table == DEF_RT_AUTO) {
248       cnf->rt_table = 254;
249     }
250     if (cnf->rt_table_default == DEF_RT_AUTO) {
251       cnf->rt_table_default = 223;
252     }
253     if (cnf->rt_table_tunnel == DEF_RT_AUTO) {
254       cnf->rt_table_tunnel = 224;
255     }
256
257     /* default for "rt_table_pri" is none (main table already has a policy rule */
258     prio = 32766;
259     if (cnf->rt_table_pri > 0) {
260       prio = cnf->rt_table_pri;
261     }
262     else if (cnf->rt_table_pri == DEF_RT_AUTO) {
263       /* choose default */
264       olsr_cnf->rt_table_pri = 0;
265       fprintf(stderr, "No policy rule for rt_table_pri\n");
266     }
267
268     /* default for "rt_table_defaultolsr_pri" is +10 */
269     prio += 10;
270     if (cnf->rt_table_defaultolsr_pri > 0) {
271       prio = cnf->rt_table_defaultolsr_pri;
272     }
273     else if (cnf->rt_table_defaultolsr_pri == DEF_RT_AUTO) {
274       olsr_cnf->rt_table_defaultolsr_pri = prio;
275       fprintf(stderr, "Choose priority %u for rt_table_defaultolsr_pri\n", prio);
276     }
277
278     prio += 10;
279     if (cnf->rt_table_tunnel_pri > 0) {
280       prio = cnf->rt_table_tunnel_pri;
281     }
282     else if (cnf->rt_table_tunnel_pri == DEF_RT_AUTO) {
283       olsr_cnf->rt_table_tunnel_pri = prio;
284       fprintf(stderr, "Choose priority %u for rt_table_tunnel_pri\n", prio);
285     }
286
287     prio += 10;
288     if (cnf->rt_table_default_pri == DEF_RT_AUTO) {
289       olsr_cnf->rt_table_default_pri = prio;
290       fprintf(stderr, "Choose priority %u for rt_table_default_pri\n", prio);
291     }
292   }
293
294   /* check rule priorities */
295   if (cnf->rt_table_pri > 0) {
296     if (cnf->rt_table >= 253) {
297       fprintf(stderr, "rttable %d does not need policy rules from OLSRd\n", cnf->rt_table);
298       return -1;
299     }
300   }
301
302   prio = cnf->rt_table_pri;
303   if (cnf->rt_table_defaultolsr_pri > 0) {
304     if (prio >= cnf->rt_table_defaultolsr_pri) {
305       fprintf(stderr, "rttable_defaultolsr priority must be greater than %d\n", prio);
306       return -1;
307     }
308     if (cnf->rt_table_default >= 253) {
309       fprintf(stderr, "rttable %d does not need policy rules from OLSRd\n", cnf->rt_table_default);
310       return -1;
311     }
312     prio = olsr_cnf->rt_table_defaultolsr_pri;
313   }
314
315   if (cnf->rt_table_tunnel_pri > 0 ) {
316     if (prio >= cnf->rt_table_tunnel_pri) {
317       fprintf(stderr, "rttable_tunnel priority must be greater than %d\n", prio);
318       return -1;
319     }
320     if (cnf->rt_table_tunnel >= 253) {
321       fprintf(stderr, "rttable %d does not need policy rules from OLSRd\n", cnf->rt_table_tunnel);
322       return -1;
323     }
324     prio = cnf->rt_table_tunnel_pri;
325   }
326
327   if (cnf->rt_table_default_pri > 0) {
328     if (prio >= cnf->rt_table_default_pri) {
329       fprintf(stderr, "rttable_default priority must be greater than %d\n", prio);
330       return -1;
331     }
332     if (cnf->rt_table_default >= 253) {
333       fprintf(stderr, "rttable %d does not need policy rules from OLSRd\n", cnf->rt_table_default);
334       return -1;
335     }
336   }
337
338   /* filter rt_proto entry */
339   if (cnf->rt_proto == 1) {
340     /* protocol 1 is reserved, so better use 0 */
341     cnf->rt_proto = 0;
342   }
343   else if (cnf->rt_proto == 0) {
344     cnf->rt_proto = RTPROT_BOOT;
345   }
346 #endif
347   return 0;
348 }
349
350 static 
351 int olsrd_sanity_check_interface_cnf(struct if_config_options * io, struct olsrd_config * cnf, char* name) {
352   struct olsr_lq_mult *mult;
353
354   /* HELLO interval */
355
356   if (io->hello_params.validity_time < 0.0) {
357     if (cnf->lq_level == 0)
358       io->hello_params.validity_time = NEIGHB_HOLD_TIME;
359
360     else
361       io->hello_params.validity_time = (int)(REFRESH_INTERVAL / cnf->lq_aging);
362   }
363
364   if (io->hello_params.emission_interval < cnf->pollrate || io->hello_params.emission_interval > io->hello_params.validity_time) {
365     fprintf(stderr, "Bad HELLO parameters! (em: %0.2f, vt: %0.2f) for dev %s\n", io->hello_params.emission_interval,
366             io->hello_params.validity_time, name);
367     return -1;
368   }
369
370   /* TC interval */
371   if (io->tc_params.emission_interval < cnf->pollrate || io->tc_params.emission_interval > io->tc_params.validity_time) {
372     fprintf(stderr, "Bad TC parameters! (em: %0.2f, vt: %0.2f) for dev %s\n", io->tc_params.emission_interval,
373         io->tc_params.validity_time, name);
374     return -1;
375   }
376
377   if (cnf->min_tc_vtime > 0.0 && (io->tc_params.validity_time / io->tc_params.emission_interval) < 128) {
378     fprintf(stderr, "Please use a tc vtime at least 128 times the emission interval while using the min_tc_vtime hack.\n");
379     return -1;
380   }
381   /* MID interval */
382   if (io->mid_params.emission_interval < cnf->pollrate || io->mid_params.emission_interval > io->mid_params.validity_time) {
383     fprintf(stderr, "Bad MID parameters! (em: %0.2f, vt: %0.2f) for dev %s\n", io->mid_params.emission_interval,
384             io->mid_params.validity_time, name);
385     return -1;
386   }
387
388   /* HNA interval */
389   if (io->hna_params.emission_interval < cnf->pollrate || io->hna_params.emission_interval > io->hna_params.validity_time) {
390     fprintf(stderr, "Bad HNA parameters! (em: %0.2f, vt: %0.2f) for dev %s\n", io->hna_params.emission_interval,
391             io->hna_params.validity_time, name);
392     return -1;
393   }
394
395   for (mult = io->lq_mult; mult; mult=mult->next) {
396     if (mult->value > LINK_LOSS_MULTIPLIER) {
397       struct ipaddr_str buf;
398
399       fprintf(stderr, "Bad Linkquality multiplier ('%s' on IP %s: %0.2f)\n",
400           name, olsr_ip_to_string(&buf, &mult->addr), (float)mult->value / (float)LINK_LOSS_MULTIPLIER);
401       return -1;
402     }
403   }
404   return 0;
405 }
406
407
408 int
409 olsrd_sanity_check_cnf(struct olsrd_config *cnf)
410 {
411   struct olsr_if *in = cnf->interfaces;
412   struct if_config_options *io;
413
414   /* Debug level */
415   if (cnf->debug_level < MIN_DEBUGLVL || cnf->debug_level > MAX_DEBUGLVL) {
416     fprintf(stderr, "Debuglevel %d is not allowed\n", cnf->debug_level);
417     return -1;
418   }
419
420   /* IP version */
421   if (cnf->ip_version != AF_INET && cnf->ip_version != AF_INET6) {
422     fprintf(stderr, "Ipversion %d not allowed!\n", cnf->ip_version);
423     return -1;
424   }
425
426   /* TOS */
427   if (cnf->tos > MAX_TOS) {
428     fprintf(stderr, "TOS %d is not allowed\n", cnf->tos);
429     return -1;
430   }
431
432   if (cnf->willingness_auto == false && (cnf->willingness > MAX_WILLINGNESS)) {
433     fprintf(stderr, "Willingness %d is not allowed\n", cnf->willingness);
434     return -1;
435   }
436
437   /* Hysteresis */
438   if (cnf->use_hysteresis == true) {
439     if (cnf->hysteresis_param.scaling < MIN_HYST_PARAM || cnf->hysteresis_param.scaling > MAX_HYST_PARAM) {
440       fprintf(stderr, "Hyst scaling %0.2f is not allowed\n", cnf->hysteresis_param.scaling);
441       return -1;
442     }
443
444     if (cnf->hysteresis_param.thr_high <= cnf->hysteresis_param.thr_low) {
445       fprintf(stderr, "Hyst upper(%0.2f) thr must be bigger than lower(%0.2f) threshold!\n", cnf->hysteresis_param.thr_high,
446               cnf->hysteresis_param.thr_low);
447       return -1;
448     }
449
450     if (cnf->hysteresis_param.thr_high < MIN_HYST_PARAM || cnf->hysteresis_param.thr_high > MAX_HYST_PARAM) {
451       fprintf(stderr, "Hyst upper thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_high);
452       return -1;
453     }
454
455     if (cnf->hysteresis_param.thr_low < MIN_HYST_PARAM || cnf->hysteresis_param.thr_low > MAX_HYST_PARAM) {
456       fprintf(stderr, "Hyst lower thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_low);
457       return -1;
458     }
459   }
460
461   /* Pollrate */
462   if (cnf->pollrate < MIN_POLLRATE || cnf->pollrate > MAX_POLLRATE) {
463     fprintf(stderr, "Pollrate %0.2f is not allowed\n", cnf->pollrate);
464     return -1;
465   }
466
467   /* NIC Changes Pollrate */
468
469   if (cnf->nic_chgs_pollrate < MIN_NICCHGPOLLRT || cnf->nic_chgs_pollrate > MAX_NICCHGPOLLRT) {
470     fprintf(stderr, "NIC Changes Pollrate %0.2f is not allowed\n", cnf->nic_chgs_pollrate);
471     return -1;
472   }
473
474   /* TC redundancy */
475   if (cnf->tc_redundancy != 2) {
476     fprintf(stderr, "Sorry, tc-redundancy 0/1 are not working on 0.5.6. "
477         "It was discovered late in the stable tree development and cannot "
478         "be solved without a difficult change in the dijkstra code. "
479         "Feel free to contact the olsr-user mailinglist "
480         "(http://www.olsr.org/?q=mailing-lists) to learn more "
481         "about the problem. The next version of OLSR will have working "
482         "tc-redundancy again.\n");
483     return -1;
484   }
485
486   /* MPR coverage */
487   if (cnf->mpr_coverage < MIN_MPR_COVERAGE || cnf->mpr_coverage > MAX_MPR_COVERAGE) {
488     fprintf(stderr, "MPR coverage %d is not allowed\n", cnf->mpr_coverage);
489     return -1;
490   }
491
492   /* Link Q and hysteresis cannot be activated at the same time */
493   if (cnf->use_hysteresis == true && cnf->lq_level) {
494     fprintf(stderr, "Hysteresis and LinkQuality cannot both be active! Deactivate one of them.\n");
495     return -1;
496   }
497
498   /* Link quality level */
499   if (cnf->lq_level != 0 && cnf->lq_level != 2) {
500     fprintf(stderr, "LQ level %d is not allowed\n", cnf->lq_level);
501     return -1;
502   }
503
504   /* Link quality window size */
505   if (cnf->lq_level && (cnf->lq_aging < MIN_LQ_AGING || cnf->lq_aging > MAX_LQ_AGING)) {
506     fprintf(stderr, "LQ aging factor %f is not allowed\n", cnf->lq_aging);
507     return -1;
508   }
509
510   /* NAT threshold value */
511   if (cnf->lq_level && (cnf->lq_nat_thresh < 0.1 || cnf->lq_nat_thresh > 1.0)) {
512     fprintf(stderr, "NAT threshold %f is not allowed\n", cnf->lq_nat_thresh);
513     return -1;
514   }
515
516 #if defined linux
517 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
518   if (cnf->ip_version == AF_INET6 && cnf->smart_gw_active) {
519     fprintf(stderr, "Smart gateways are not supported for linux kernel 2.4 and ipv6\n");
520     return -1;
521   }
522 #endif
523 #endif
524
525   if (olsrd_sanity_check_rtpolicy(cnf)) {
526     return -1;
527   }
528
529   if (in == NULL) {
530     fprintf(stderr, "No interfaces configured!\n");
531     return -1;
532   }
533
534   if (cnf->min_tc_vtime < 0.0) {
535     fprintf(stderr, "Error, negative minimal tc time not allowed.\n");
536     return -1;
537   }
538   if (cnf->min_tc_vtime > 0.0) {
539           fprintf(stderr, "Warning, you are using the min_tc_vtime hack. We hope you know what you are doing... contact olsr.org otherwise.\n");
540   }
541
542   if (cnf->smart_gw_type >= GW_UPLINK_CNT) {
543     fprintf(stderr, "Error, illegal gateway uplink type: %d\n", cnf->smart_gw_type);
544     return -1;
545   }
546   if (cnf->smart_gw_downlink < MIN_SMARTGW_SPEED || cnf->smart_gw_downlink > MAX_SMARTGW_SPEED) {
547     fprintf(stderr, "Error, bad gateway downlink speed: %d kbit/s (should be %d-%d)\n",
548         cnf->smart_gw_downlink, MIN_SMARTGW_SPEED, MAX_SMARTGW_SPEED);
549     return -1;
550   }
551   if (cnf->smart_gw_uplink < MIN_SMARTGW_SPEED || cnf->smart_gw_uplink > MAX_SMARTGW_SPEED) {
552     fprintf(stderr, "Error, bad gateway uplink speed: %d kbit/s (should be %d-%d)\n",
553         cnf->smart_gw_uplink, MIN_SMARTGW_SPEED, MAX_SMARTGW_SPEED);
554     return -1;
555   }
556
557   if (cnf->interface_defaults == NULL) {
558     /* get a default configuration if the user did not specify one */
559     cnf->interface_defaults = get_default_if_config();
560   } else {
561     olsrd_print_interface_cnf(cnf->interface_defaults, cnf->interface_defaults, false);
562     olsrd_sanity_check_interface_cnf(cnf->interface_defaults, cnf, interface_defaults_name);
563   }
564
565   /* Interfaces */
566   while (in) {
567     struct olsr_lq_mult *mult, *mult_orig;
568
569     io = in->cnf;
570
571     olsrd_print_interface_cnf(in->cnf, in->cnfi, false);
572
573     /*apply defaults*/
574     {
575       size_t pos;
576       struct olsr_lq_mult *mult_temp, *mult_orig_walk;
577       uint8_t *cnfptr = (uint8_t*)in->cnf;
578       uint8_t *cnfiptr = (uint8_t*)in->cnfi;
579       uint8_t *defptr = (uint8_t*)cnf->interface_defaults;
580
581       /*save interface specific lqmults, as they are merged togehter later*/
582       mult_orig = io->lq_mult;
583
584       assert(in->cnf);
585       assert(in->cnfi);
586       for (pos = 0; pos < sizeof(*in->cnf); pos++) {
587         if (cnfptr[pos] != cnfiptr[pos]) {
588           cnfptr[pos] = defptr[pos]; cnfiptr[pos]=0x00;
589         }
590         else cnfiptr[pos]=0xFF;
591       }
592
593       io->lq_mult=NULL;
594       /*copy default lqmults into this interface*/
595       for (mult = cnf->interface_defaults->lq_mult; mult; mult=mult->next) {
596         /*search same lqmult in orig_list*/
597         for (mult_orig_walk = mult_orig; mult_orig_walk; mult_orig_walk=mult_orig_walk->next) {
598           if (ipequal(&mult_orig_walk->addr,&mult->addr)) {
599             break;
600           }
601         }
602         if (mult_orig_walk == NULL) {
603           mult_temp=malloc(sizeof(struct olsr_lq_mult));
604           memcpy(mult_temp,mult,sizeof(struct olsr_lq_mult));
605           mult_temp->next=io->lq_mult;
606           io->lq_mult=mult_temp;
607         }
608       }
609     }
610
611     if (in->name == NULL || !strlen(in->name)) {
612       fprintf(stderr, "Interface has no name!\n");
613       return -1;
614     }
615
616     if (io == NULL) {
617       fprintf(stderr, "Interface %s has no configuration!\n", in->name);
618       return -1;
619     }
620
621     /*merge lqmults*/
622     if (mult_orig!=NULL) {
623       io->orig_lq_mult_cnt=1;
624       /*search last of interface specific lqmults*/
625       mult = mult_orig;
626       while (mult->next!=NULL) {
627         mult=mult->next;
628       }
629       /*append default lqmults ath the end of the interface specific (to ensure they can overwrite them)*/
630       mult->next=io->lq_mult;
631       io->lq_mult=mult_orig;
632     }
633
634     if (olsrd_sanity_check_interface_cnf(io, cnf, in->name)) return -1;
635
636     in = in->next;
637   }
638
639   return 0;
640 }
641
642 void
643 olsrd_free_cnf(struct olsrd_config *cnf)
644 {
645   struct ip_prefix_list *hd, *h = cnf->hna_entries;
646   struct olsr_if *ind, *in = cnf->interfaces;
647   struct plugin_entry *ped, *pe = cnf->plugins;
648   struct olsr_lq_mult *mult, *next_mult;
649
650   while (h) {
651     hd = h;
652     h = h->next;
653     free(hd);
654   }
655
656   while (in) {
657     for (mult = in->cnf->lq_mult; mult != NULL; mult = next_mult) {
658       next_mult = mult->next;
659       free(mult);
660     }
661
662     free(in->cnf);
663     free(in->cnfi);
664
665     ind = in;
666     in = in->next;
667
668     free(ind);
669   }
670
671   while (pe) {
672     ped = pe;
673     pe = pe->next;
674     free(ped->name);
675     free(ped);
676   }
677
678   return;
679 }
680
681 struct olsrd_config *
682 olsrd_get_default_cnf(void)
683 {
684   struct olsrd_config *c = malloc(sizeof(struct olsrd_config));
685   if (c == NULL) {
686     fprintf(stderr, "Out of memory %s\n", __func__);
687     return NULL;
688   }
689
690   set_default_cnf(c);
691   return c;
692 }
693
694 void
695 set_default_cnf(struct olsrd_config *cnf)
696 {
697   memset(cnf, 0, sizeof(*cnf));
698
699   cnf->debug_level = DEF_DEBUGLVL;
700   cnf->no_fork = false;
701   cnf->host_emul = false;
702   cnf->ip_version = AF_INET;
703   cnf->ipsize = sizeof(struct in_addr);
704   cnf->maxplen = 32;
705   cnf->allow_no_interfaces = DEF_ALLOW_NO_INTS;
706   cnf->tos = DEF_TOS;
707   cnf->olsrport = DEF_OLSRPORT;
708   cnf->rt_proto = DEF_RTPROTO;
709   cnf->rt_table = DEF_RT_AUTO;
710   cnf->rt_table_default = DEF_RT_AUTO;
711   cnf->rt_table_tunnel = DEF_RT_AUTO;
712   cnf->rt_table_pri = DEF_RT_AUTO;
713   cnf->rt_table_default_pri = DEF_RT_AUTO;
714   cnf->rt_table_defaultolsr_pri = DEF_RT_AUTO;
715   cnf->rt_table_tunnel_pri = DEF_RT_AUTO;
716
717   cnf->willingness_auto = DEF_WILL_AUTO;
718   cnf->willingness = DEF_WILLINGNESS;
719   cnf->ipc_connections = DEF_IPC_CONNECTIONS;
720   cnf->fib_metric = DEF_FIB_METRIC;
721
722   cnf->use_hysteresis = DEF_USE_HYST;
723   cnf->hysteresis_param.scaling = HYST_SCALING;
724   cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
725   cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
726
727   cnf->pollrate = DEF_POLLRATE;
728   cnf->nic_chgs_pollrate = DEF_NICCHGPOLLRT;
729
730   cnf->tc_redundancy = TC_REDUNDANCY;
731   cnf->mpr_coverage = MPR_COVERAGE;
732   cnf->lq_level = DEF_LQ_LEVEL;
733   cnf->lq_fish = DEF_LQ_FISH;
734   cnf->lq_aging = DEF_LQ_AGING;
735   cnf->lq_algorithm = NULL;
736   cnf->lq_nat_thresh = DEF_LQ_NAT_THRESH;
737   cnf->clear_screen = DEF_CLEAR_SCREEN;
738
739   cnf->del_gws = false;
740   cnf->will_int = 10 * HELLO_INTERVAL;
741   cnf->max_jitter = 0.0;
742   cnf->exit_value = EXIT_SUCCESS;
743   cnf->max_tc_vtime = 0.0;
744   cnf->ioctl_s = 0;
745   cnf->use_niit = DEF_USE_NIIT;
746   cnf->niit4to6_if_index = 0;
747   cnf->niit6to4_if_index = 0;
748
749   cnf->smart_gw_active = DEF_SMART_GW;
750   cnf->smart_gw_allow_nat = DEF_GW_ALLOW_NAT;
751   cnf->smart_gw_type = DEF_GW_TYPE;
752   cnf->smart_gw_uplink = DEF_UPLINK_SPEED;
753   cnf->smart_gw_uplink_nat = DEF_GW_UPLINK_NAT;
754   cnf->smart_gw_downlink = DEF_DOWNLINK_SPEED;
755
756   cnf->use_src_ip_routes = DEF_USE_SRCIP_ROUTES;
757
758 #ifdef LINUX_NETLINK_ROUTING
759   cnf->rtnl_s = 0;
760 #endif
761
762 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
763   cnf->rts = 0;
764 #endif
765 }
766
767 struct if_config_options *
768 get_default_if_config(void)
769 {
770   struct if_config_options *io = malloc(sizeof(*io));
771
772   if (io == NULL) {
773     fprintf(stderr, "Out of memory %s\n", __func__);
774     return NULL;
775   }
776
777   memset(io, 0, sizeof(*io));
778
779   io->mode = DEF_IF_MODE;
780
781   io->ipv6_multicast = ipv6_def_multicast;
782
783   io->lq_mult = NULL;
784
785   io->weight.fixed = false;
786   io->weight.value = 0;
787
788   io->hello_params.emission_interval = HELLO_INTERVAL;
789   io->hello_params.validity_time = NEIGHB_HOLD_TIME;
790   io->tc_params.emission_interval = TC_INTERVAL;
791   io->tc_params.validity_time = TOP_HOLD_TIME;
792   io->mid_params.emission_interval = MID_INTERVAL;
793   io->mid_params.validity_time = MID_HOLD_TIME;
794   io->hna_params.emission_interval = HNA_INTERVAL;
795   io->hna_params.validity_time = HNA_HOLD_TIME;
796   io->autodetect_chg = true;
797
798   return io;
799
800 }
801
802 void
803 olsrd_print_cnf(struct olsrd_config *cnf)
804 {
805   struct ip_prefix_list *h = cnf->hna_entries;
806   struct olsr_if *in = cnf->interfaces;
807   struct plugin_entry *pe = cnf->plugins;
808   struct ip_prefix_list *ie = cnf->ipc_nets;
809
810   printf(" *** olsrd configuration ***\n");
811
812   printf("Debug Level      : %d\n", cnf->debug_level);
813   if (cnf->ip_version == AF_INET6)
814     printf("IpVersion        : 6\n");
815   else
816     printf("IpVersion        : 4\n");
817   if (cnf->allow_no_interfaces)
818     printf("No interfaces    : ALLOWED\n");
819   else
820     printf("No interfaces    : NOT ALLOWED\n");
821   printf("TOS              : 0x%02x\n", cnf->tos);
822   printf("OlsrPort          : 0x%03x\n", cnf->olsrport);
823   printf("RtTable          : %u\n", cnf->rt_table);
824   printf("RtTableDefault   : %u\n", cnf->rt_table_default);
825   printf("RtTableTunnel    : %u\n", cnf->rt_table_tunnel);
826   if (cnf->willingness_auto)
827     printf("Willingness      : AUTO\n");
828   else
829     printf("Willingness      : %d\n", cnf->willingness);
830
831   printf("IPC connections  : %d\n", cnf->ipc_connections);
832   while (ie) {
833     struct ipaddr_str strbuf;
834     if (ie->net.prefix_len == olsr_cnf->maxplen) {
835       printf("\tHost %s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
836     } else {
837       printf("\tNet %s/%d\n", olsr_ip_to_string(&strbuf, &ie->net.prefix), ie->net.prefix_len);
838     }
839     ie = ie->next;
840   }
841
842   printf("Pollrate         : %0.2f\n", cnf->pollrate);
843
844   printf("NIC ChangPollrate: %0.2f\n", cnf->nic_chgs_pollrate);
845
846   printf("TC redundancy    : %d\n", cnf->tc_redundancy);
847
848   printf("MPR coverage     : %d\n", cnf->mpr_coverage);
849
850   printf("LQ level         : %d\n", cnf->lq_level);
851
852   printf("LQ fish eye      : %d\n", cnf->lq_fish);
853
854   printf("LQ aging factor  : %f\n", cnf->lq_aging);
855
856   printf("LQ algorithm name: %s\n", cnf->lq_algorithm ? cnf->lq_algorithm : "default");
857
858   printf("NAT threshold    : %f\n", cnf->lq_nat_thresh);
859
860   printf("Clear screen     : %s\n", cnf->clear_screen ? "yes" : "no");
861
862   printf("Use niit         : %s\n", cnf->use_niit ? "yes" : "no");
863
864   printf("Smart Gateway    : %s\n", cnf->smart_gw_active ? "yes" : "no");
865
866   printf("SmGw. Allow NAT  : %s\n", cnf->smart_gw_allow_nat ? "yes" : "no");
867
868   printf("Smart Gw. Uplink : %s\n", GW_UPLINK_TXT[cnf->smart_gw_type]);
869
870   printf("SmGw. Uplink NAT : %s\n", cnf->smart_gw_uplink_nat ? "yes" : "no");
871
872   printf("Smart Gw. speed  : %d kbit/s up, %d kbit/s down\n",
873       cnf->smart_gw_uplink, cnf->smart_gw_downlink);
874
875   if (olsr_cnf->smart_gw_prefix.prefix_len == 0) {
876     printf("# Smart Gw. prefix : ::/0\n");
877   }
878   else {
879     printf("Smart Gw. prefix : %s\n", olsr_ip_prefix_to_string(&cnf->smart_gw_prefix));
880   }
881
882   /* Interfaces */
883   if (in) {
884     /*print interface default config*/
885     printf(" InterfaceDefaults: \n");
886     olsrd_print_interface_cnf(cnf->interface_defaults, cnf->interface_defaults, true);
887
888     while (in)
889     { 
890       if (cnf->interface_defaults!=in->cnf)
891       {
892         printf(" dev: \"%s\"\n", in->name);
893
894         olsrd_print_interface_cnf(in->cnf, in->cnfi, false);
895       }
896       in = in->next;
897     }
898   }
899
900   /* Plugins */
901   if (pe) {
902     printf("Plugins:\n");
903
904     while (pe) {
905       printf("\tName: \"%s\"\n", pe->name);
906       pe = pe->next;
907     }
908   }
909
910   /* Hysteresis */
911   if (cnf->use_hysteresis) {
912     printf("Using hysteresis:\n");
913     printf("\tScaling      : %0.2f\n", cnf->hysteresis_param.scaling);
914     printf("\tThr high/low : %0.2f/%0.2f\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low);
915   } else {
916     printf("Not using hysteresis\n");
917   }
918
919   /* HNA IPv4 and IPv6 */
920   if (h) {
921     printf("HNA%d entries:\n", cnf->ip_version == AF_INET ? 4 : 6);
922     while (h) {
923       struct ipaddr_str buf;
924       printf("\t%s/", olsr_ip_to_string(&buf, &h->net.prefix));
925       if (cnf->ip_version == AF_INET) {
926         union olsr_ip_addr ip;
927         olsr_prefix_to_netmask(&ip, h->net.prefix_len);
928         printf("%s\n", olsr_ip_to_string(&buf, &ip));
929       } else {
930         printf("%d\n", h->net.prefix_len);
931       }
932       h = h->next;
933     }
934   }
935 }
936
937 #if defined WIN32
938 struct ioinfo {
939   unsigned int handle;
940   unsigned char attr;
941   char buff;
942   int flag;
943   CRITICAL_SECTION lock;
944 };
945
946 void
947 win32_stdio_hack(unsigned int handle)
948 {
949   HMODULE lib;
950   struct ioinfo **info;
951
952   lib = LoadLibrary("msvcrt.dll");
953
954   info = (struct ioinfo **)GetProcAddress(lib, "__pioinfo");
955
956   // (*info)[1].handle = handle;
957   // (*info)[1].attr = 0x89; // FOPEN | FTEXT | FPIPE;
958
959   (*info)[2].handle = handle;
960   (*info)[2].attr = 0x89;
961
962   // stdout->_file = 1;
963   stderr->_file = 2;
964
965   // setbuf(stdout, NULL);
966   setbuf(stderr, NULL);
967 }
968
969 void *
970 win32_olsrd_malloc(size_t size)
971 {
972   return malloc(size);
973 }
974
975 void
976 win32_olsrd_free(void *ptr)
977 {
978   free(ptr);
979 }
980 #endif
981
982 static void update_has_gateway_fields(void) {
983   struct ip_prefix_list *h;
984
985   olsr_cnf->has_ipv4_gateway = false;
986   olsr_cnf->has_ipv6_gateway = false;
987
988   for (h = olsr_cnf->hna_entries; h != NULL; h = h->next) {
989     olsr_cnf->has_ipv4_gateway |= ip_prefix_is_v4_inetgw(&h->net) || ip_prefix_is_mappedv4_inetgw(&h->net);
990     olsr_cnf->has_ipv6_gateway |= ip_prefix_is_v6_inetgw(&h->net);
991   }
992 }
993
994 void
995 ip_prefix_list_add(struct ip_prefix_list **list, const union olsr_ip_addr *net, uint8_t prefix_len)
996 {
997   struct ip_prefix_list *new_entry = malloc(sizeof(*new_entry));
998
999   new_entry->net.prefix = *net;
1000   new_entry->net.prefix_len = prefix_len;
1001
1002   /* Queue */
1003   new_entry->next = *list;
1004   *list = new_entry;
1005
1006   /* update gateway flags */
1007   update_has_gateway_fields();
1008 }
1009
1010 int
1011 ip_prefix_list_remove(struct ip_prefix_list **list, const union olsr_ip_addr *net, uint8_t prefix_len)
1012 {
1013   struct ip_prefix_list *h = *list, *prev = NULL;
1014
1015   while (h != NULL) {
1016     if (ipequal(net, &h->net.prefix) && h->net.prefix_len == prefix_len) {
1017       /* Dequeue */
1018       if (prev == NULL) {
1019         *list = h->next;
1020       } else {
1021         prev->next = h->next;
1022       }
1023       free(h);
1024
1025       /* update gateway flags */
1026       update_has_gateway_fields();
1027       return 1;
1028     }
1029     prev = h;
1030     h = h->next;
1031   }
1032   return 0;
1033 }
1034
1035 struct ip_prefix_list *
1036 ip_prefix_list_find(struct ip_prefix_list *list, const union olsr_ip_addr *net, uint8_t prefix_len)
1037 {
1038   struct ip_prefix_list *h;
1039   for (h = list; h != NULL; h = h->next) {
1040     if (prefix_len == h->net.prefix_len && ipequal(net, &h->net.prefix)) {
1041       return h;
1042     }
1043   }
1044   return NULL;
1045 }
1046
1047 /*
1048  * Local Variables:
1049  * c-basic-offset: 2
1050  * indent-tabs-mode: nil
1051  * End:
1052  */