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