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