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