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