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