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