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