Support for Debian/FreeBSD
[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 <stdio.h>
50 #include <string.h>
51 #include <errno.h>
52 #include <stdlib.h>
53 #include <sys/types.h>
54 #include <sys/socket.h>
55 #include <netinet/in.h>
56 #include <arpa/inet.h>
57
58 extern FILE *yyin;
59 extern int yyparse(void);
60
61 static char copyright_string[] __attribute__ ((unused)) =
62   "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
63
64 int current_line;
65
66 /* Global stuff externed in defs.h */
67 FILE *debug_handle;                    /* Where to send debug(defaults to stdout) */
68 struct olsrd_config *olsr_cnf;         /* The global configuration */
69
70 #ifdef MAKEBIN
71
72 /* Build as standalone binary */
73 int
74 main(int argc, char *argv[])
75 {
76   struct olsrd_config *cnf;
77
78   if (argc == 1) {
79     fprintf(stderr, "Usage: olsrd_cfgparser [filename] -print\n\n");
80     exit(EXIT_FAILURE);
81   }
82
83   if ((cnf = olsrd_parse_cnf(argv[1])) != NULL) {
84     if ((argc > 2) && (!strcmp(argv[2], "-print"))) {
85       olsrd_print_cnf(cnf);
86       olsrd_write_cnf(cnf, "./out.conf");
87     } else
88       printf("Use -print to view parsed values\n");
89     printf("Configfile parsed OK\n");
90   } else {
91     printf("Failed parsing \"%s\"\n", argv[1]);
92   }
93
94   return 0;
95 }
96
97 #else
98
99 /* Build as part of olsrd */
100
101 #endif
102
103 struct olsrd_config *
104 olsrd_parse_cnf(const char *filename)
105 {
106   struct olsr_if *in, *new_ifqueue;
107   int rc;
108
109   /* Initialize the global varibles - oparse.y needs it there */
110   olsr_cnf = malloc(sizeof(*olsr_cnf));
111   if (olsr_cnf == NULL) {
112     fprintf(stderr, "Out of memory %s\n", __func__);
113     return NULL;
114   }
115
116   set_default_cnf(olsr_cnf);
117
118   printf("Parsing file: \"%s\"\n", filename);
119
120   yyin = fopen(filename, "r");
121   if (yyin == NULL) {
122     fprintf(stderr, "Cannot open configuration file '%s': %s.\n", filename, strerror(errno));
123     olsrd_free_cnf(olsr_cnf);
124     olsr_cnf = NULL;
125     return NULL;
126   }
127
128   current_line = 1;
129   rc = yyparse();
130   fclose(yyin);
131   if (rc != 0) {
132     olsrd_free_cnf(olsr_cnf);
133     olsr_cnf = NULL;
134     return NULL;
135   }
136
137   /* Reverse the queue (added by user request) */
138   in = olsr_cnf->interfaces;
139   new_ifqueue = NULL;
140
141   while (in) {
142     struct olsr_if *in_tmp = in;
143     in = in->next;
144
145     in_tmp->next = new_ifqueue;
146     new_ifqueue = in_tmp;
147   }
148
149   olsr_cnf->interfaces = new_ifqueue;
150
151   for (in = olsr_cnf->interfaces; in != NULL; in = in->next) {
152     /* set various stuff */
153     in->configured = false;
154     in->interf = NULL;
155     in->host_emul = false;
156   }
157   return olsr_cnf;
158 }
159
160 int
161 olsrd_sanity_check_cnf(struct olsrd_config *cnf)
162 {
163   struct olsr_if *in = cnf->interfaces;
164   struct if_config_options *io;
165
166   /* Debug level */
167   if (cnf->debug_level < MIN_DEBUGLVL || cnf->debug_level > MAX_DEBUGLVL) {
168     fprintf(stderr, "Debuglevel %d is not allowed\n", cnf->debug_level);
169     return -1;
170   }
171
172   /* IP version */
173   if (cnf->ip_version != AF_INET && cnf->ip_version != AF_INET6) {
174     fprintf(stderr, "Ipversion %d not allowed!\n", cnf->ip_version);
175     return -1;
176   }
177
178   /* TOS */
179   if (                          //cnf->tos < MIN_TOS ||
180        cnf->tos > MAX_TOS) {
181     fprintf(stderr, "TOS %d is not allowed\n", cnf->tos);
182     return -1;
183   }
184
185   if (cnf->willingness_auto == false && (cnf->willingness > MAX_WILLINGNESS)) {
186     fprintf(stderr, "Willingness %d is not allowed\n", cnf->willingness);
187     return -1;
188   }
189
190   /* Hysteresis */
191   if (cnf->use_hysteresis == true) {
192     if (cnf->hysteresis_param.scaling < MIN_HYST_PARAM || cnf->hysteresis_param.scaling > MAX_HYST_PARAM) {
193       fprintf(stderr, "Hyst scaling %0.2f is not allowed\n", cnf->hysteresis_param.scaling);
194       return -1;
195     }
196
197     if (cnf->hysteresis_param.thr_high <= cnf->hysteresis_param.thr_low) {
198       fprintf(stderr, "Hyst upper(%0.2f) thr must be bigger than lower(%0.2f) threshold!\n", cnf->hysteresis_param.thr_high,
199               cnf->hysteresis_param.thr_low);
200       return -1;
201     }
202
203     if (cnf->hysteresis_param.thr_high < MIN_HYST_PARAM || cnf->hysteresis_param.thr_high > MAX_HYST_PARAM) {
204       fprintf(stderr, "Hyst upper thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_high);
205       return -1;
206     }
207
208     if (cnf->hysteresis_param.thr_low < MIN_HYST_PARAM || cnf->hysteresis_param.thr_low > MAX_HYST_PARAM) {
209       fprintf(stderr, "Hyst lower thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_low);
210       return -1;
211     }
212   }
213
214   /* Check Link quality dijkstra limit */
215   if (olsr_cnf->lq_dinter < cnf->pollrate && olsr_cnf->lq_dlimit != 255) {
216     fprintf(stderr, "Link quality dijkstra limit must be higher than pollrate\n");
217     return -1;
218   }
219
220   /* Pollrate */
221
222   if (cnf->pollrate < MIN_POLLRATE || cnf->pollrate > MAX_POLLRATE) {
223     fprintf(stderr, "Pollrate %0.2f is not allowed\n", cnf->pollrate);
224     return -1;
225   }
226
227   /* NIC Changes Pollrate */
228
229   if (cnf->nic_chgs_pollrate < MIN_NICCHGPOLLRT || cnf->nic_chgs_pollrate > MAX_NICCHGPOLLRT) {
230     fprintf(stderr, "NIC Changes Pollrate %0.2f is not allowed\n", cnf->nic_chgs_pollrate);
231     return -1;
232   }
233
234   /* TC redundancy */
235   if (cnf->tc_redundancy != 2) {
236     fprintf(stderr, "Sorry, tc-redundancy 0/1 are not working on 0.5.6. "
237         "It was discovered late in the stable tree development and cannot "
238         "be solved without a difficult change in the dijkstra code. "
239         "Feel free to contact the olsr-user mailinglist "
240         "(http://www.olsr.org/?q=mailing-lists) to learn more "
241         "about the problem. The next version of OLSR will have working "
242         "tc-redundancy again.\n");
243     return -1;
244   }
245
246   /* MPR coverage */
247   if (cnf->mpr_coverage < MIN_MPR_COVERAGE || cnf->mpr_coverage > MAX_MPR_COVERAGE) {
248     fprintf(stderr, "MPR coverage %d is not allowed\n", cnf->mpr_coverage);
249     return -1;
250   }
251
252   /* Link Q and hysteresis cannot be activated at the same time */
253   if (cnf->use_hysteresis == true && cnf->lq_level) {
254     fprintf(stderr, "Hysteresis and LinkQuality cannot both be active! Deactivate one of them.\n");
255     return -1;
256   }
257
258   /* Link quality level */
259
260   if (cnf->lq_level > MAX_LQ_LEVEL) {
261     fprintf(stderr, "LQ level %d is not allowed\n", cnf->lq_level);
262     return -1;
263   }
264
265   /* Link quality window size */
266   if (cnf->lq_level && (cnf->lq_aging < MIN_LQ_AGING || cnf->lq_aging > MAX_LQ_AGING)) {
267     fprintf(stderr, "LQ aging factor %f is not allowed\n", cnf->lq_aging);
268     return -1;
269   }
270
271   /* NAT threshold value */
272   if (cnf->lq_level && (cnf->lq_nat_thresh < 0.1 || cnf->lq_nat_thresh > 1.0)) {
273     fprintf(stderr, "NAT threshold %f is not allowed\n", cnf->lq_nat_thresh);
274     return -1;
275   }
276
277   if (in == NULL) {
278     fprintf(stderr, "No interfaces configured!\n");
279     return -1;
280   }
281
282   if (cnf->min_tc_vtime < 0.0) {
283         fprintf(stderr, "Error, negative minimal tc time not allowed.\n");
284         return -1;
285   }
286   if (cnf->min_tc_vtime > 0.0) {
287           fprintf(stderr, "Warning, you are using the min_tc_vtime hack. We hope you know what you are doing... contact olsr.org otherwise.\n");
288   }
289
290   /* Interfaces */
291   while (in) {
292     struct olsr_lq_mult *mult;
293
294     io = in->cnf;
295
296     if (in->name == NULL || !strlen(in->name)) {
297       fprintf(stderr, "Interface has no name!\n");
298       return -1;
299     }
300
301     if (io == NULL) {
302       fprintf(stderr, "Interface %s has no configuration!\n", in->name);
303       return -1;
304     }
305
306     /* HELLO interval */
307
308     if (io->hello_params.validity_time < 0.0) {
309       if (cnf->lq_level == 0)
310         io->hello_params.validity_time = NEIGHB_HOLD_TIME;
311
312       else
313         io->hello_params.validity_time = (int)(REFRESH_INTERVAL / cnf->lq_aging);
314     }
315
316     if (io->hello_params.emission_interval < cnf->pollrate || io->hello_params.emission_interval > io->hello_params.validity_time) {
317       fprintf(stderr, "Bad HELLO parameters! (em: %0.2f, vt: %0.2f)\n", io->hello_params.emission_interval,
318               io->hello_params.validity_time);
319       return -1;
320     }
321
322     /* TC interval */
323     if (io->tc_params.emission_interval < cnf->pollrate || io->tc_params.emission_interval > io->tc_params.validity_time) {
324       fprintf(stderr, "Bad TC parameters! (em: %0.2f, vt: %0.2f)\n", io->tc_params.emission_interval, io->tc_params.validity_time);
325       return -1;
326     }
327
328     if (cnf->min_tc_vtime > 0.0 && (io->tc_params.validity_time / io->tc_params.emission_interval) < 128) {
329       fprintf(stderr, "Please use a tc vtime at least 128 times the emission interval while using the min_tc_vtime hack.\n");
330       return -1;
331     }
332     /* MID interval */
333     if (io->mid_params.emission_interval < cnf->pollrate || io->mid_params.emission_interval > io->mid_params.validity_time) {
334       fprintf(stderr, "Bad MID parameters! (em: %0.2f, vt: %0.2f)\n", io->mid_params.emission_interval,
335               io->mid_params.validity_time);
336       return -1;
337     }
338
339     /* HNA interval */
340     if (io->hna_params.emission_interval < cnf->pollrate || io->hna_params.emission_interval > io->hna_params.validity_time) {
341       fprintf(stderr, "Bad HNA parameters! (em: %0.2f, vt: %0.2f)\n", io->hna_params.emission_interval,
342               io->hna_params.validity_time);
343       return -1;
344     }
345
346     for (mult = io->lq_mult; mult; mult=mult->next) {
347       if (mult->value > LINK_LOSS_MULTIPLIER) {
348         struct ipaddr_str buf;
349
350         fprintf(stderr, "Bad Linkquality multiplier ('%s' on IP %s: %0.2f)\n",
351             in->name, olsr_ip_to_string(&buf, &mult->addr), (float)mult->value / (float)LINK_LOSS_MULTIPLIER);
352         return -1;
353       }
354     }
355     in = in->next;
356   }
357
358   return 0;
359 }
360
361 void
362 olsrd_free_cnf(struct olsrd_config *cnf)
363 {
364   struct ip_prefix_list *hd, *h = cnf->hna_entries;
365   struct olsr_if *ind, *in = cnf->interfaces;
366   struct plugin_entry *ped, *pe = cnf->plugins;
367   struct olsr_lq_mult *mult, *next_mult;
368
369   while (h) {
370     hd = h;
371     h = h->next;
372     free(hd);
373   }
374
375   while (in) {
376     for (mult = in->cnf->lq_mult; mult != NULL; mult = next_mult) {
377       next_mult = mult->next;
378       free(mult);
379     }
380
381     free(in->cnf);
382     ind = in;
383     in = in->next;
384     free(ind->name);
385     free(ind->config);
386     free(ind);
387   }
388
389   while (pe) {
390     ped = pe;
391     pe = pe->next;
392     free(ped->name);
393     free(ped);
394   }
395
396   return;
397 }
398
399 struct olsrd_config *
400 olsrd_get_default_cnf(void)
401 {
402   struct olsrd_config *c = malloc(sizeof(struct olsrd_config));
403   if (c == NULL) {
404     fprintf(stderr, "Out of memory %s\n", __func__);
405     return NULL;
406   }
407
408   set_default_cnf(c);
409   return c;
410 }
411
412 void
413 set_default_cnf(struct olsrd_config *cnf)
414 {
415   memset(cnf, 0, sizeof(*cnf));
416
417   cnf->debug_level = DEF_DEBUGLVL;
418   cnf->no_fork = false;
419   cnf->host_emul = false;
420   cnf->ip_version = AF_INET;
421   cnf->ipsize = sizeof(struct in_addr);
422   cnf->maxplen = 32;
423   cnf->allow_no_interfaces = DEF_ALLOW_NO_INTS;
424   cnf->tos = DEF_TOS;
425   cnf->olsrport = DEF_OLSRPORT;
426   cnf->rttable = DEF_RTTABLE;
427   cnf->rtproto = DEF_RTPROTO;
428   cnf->rttable_default = 0;
429   cnf->willingness_auto = DEF_WILL_AUTO;
430   cnf->ipc_connections = DEF_IPC_CONNECTIONS;
431   cnf->fib_metric = DEF_FIB_METRIC;
432
433   cnf->use_hysteresis = DEF_USE_HYST;
434   cnf->hysteresis_param.scaling = HYST_SCALING;
435   cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
436   cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
437
438   cnf->pollrate = DEF_POLLRATE;
439   cnf->nic_chgs_pollrate = DEF_NICCHGPOLLRT;
440
441   cnf->tc_redundancy = TC_REDUNDANCY;
442   cnf->mpr_coverage = MPR_COVERAGE;
443   cnf->lq_level = DEF_LQ_LEVEL;
444   cnf->lq_fish = DEF_LQ_FISH;
445   cnf->lq_dlimit = DEF_LQ_DIJK_LIMIT;
446   cnf->lq_dinter = DEF_LQ_DIJK_INTER;
447   cnf->lq_aging = DEF_LQ_AGING;
448   cnf->lq_algorithm = NULL;
449   cnf->lq_nat_thresh = DEF_LQ_NAT_THRESH;
450   cnf->clear_screen = DEF_CLEAR_SCREEN;
451
452   cnf->del_gws = false;
453   cnf->will_int = 10 * HELLO_INTERVAL;
454   cnf->max_jitter = 0.0;
455   cnf->exit_value = EXIT_SUCCESS;
456   cnf->max_tc_vtime = 0.0;
457   cnf->ioctl_s = 0;
458 #if LINUX_POLICY_ROUTING
459   cnf->rtnl_s = 0;
460 #endif
461
462 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
463   cnf->rts = 0;
464 #endif
465 }
466
467 struct if_config_options *
468 get_default_if_config(void)
469 {
470   struct in6_addr in6;
471   struct if_config_options *io = malloc(sizeof(*io));
472
473   if (io == NULL) {
474     fprintf(stderr, "Out of memory %s\n", __func__);
475     return NULL;
476   }
477
478   memset(io, 0, sizeof(*io));
479
480   io->ipv6_addrtype = 1;        /* XXX - FixMe */
481
482   inet_pton(AF_INET6, OLSR_IPV6_MCAST_SITE_LOCAL, &in6);
483   io->ipv6_multi_site.v6 = in6;
484
485   inet_pton(AF_INET6, OLSR_IPV6_MCAST_GLOBAL, &in6);
486   io->ipv6_multi_glbl.v6 = in6;
487
488   io->lq_mult = NULL;
489
490   io->weight.fixed = false;
491   io->weight.value = 0;
492
493   io->ipv6_addrtype = 0;        /* global */
494
495   io->hello_params.emission_interval = HELLO_INTERVAL;
496   io->hello_params.validity_time = NEIGHB_HOLD_TIME;
497   io->tc_params.emission_interval = TC_INTERVAL;
498   io->tc_params.validity_time = TOP_HOLD_TIME;
499   io->mid_params.emission_interval = MID_INTERVAL;
500   io->mid_params.validity_time = MID_HOLD_TIME;
501   io->hna_params.emission_interval = HNA_INTERVAL;
502   io->hna_params.validity_time = HNA_HOLD_TIME;
503   io->autodetect_chg = true;
504
505   return io;
506
507 }
508
509 void
510 olsrd_print_cnf(struct olsrd_config *cnf)
511 {
512   struct ip_prefix_list *h = cnf->hna_entries;
513   struct olsr_if *in = cnf->interfaces;
514   struct plugin_entry *pe = cnf->plugins;
515   struct ip_prefix_list *ie = cnf->ipc_nets;
516   struct olsr_lq_mult *mult;
517   char ipv6_buf[100];                  /* buffer for IPv6 inet_htop */
518
519   printf(" *** olsrd configuration ***\n");
520
521   printf("Debug Level      : %d\n", cnf->debug_level);
522   if (cnf->ip_version == AF_INET6)
523     printf("IpVersion        : 6\n");
524   else
525     printf("IpVersion        : 4\n");
526   if (cnf->allow_no_interfaces)
527     printf("No interfaces    : ALLOWED\n");
528   else
529     printf("No interfaces    : NOT ALLOWED\n");
530   printf("TOS              : 0x%02x\n", cnf->tos);
531   printf("OlsrPort          : 0x%03x\n", cnf->olsrport);
532   printf("RtTable          : 0x%02x\n", cnf->rttable);
533   printf("RtTableDefault   : 0x%02x\n", cnf->rttable_default);
534   if (cnf->willingness_auto)
535     printf("Willingness      : AUTO\n");
536   else
537     printf("Willingness      : %d\n", cnf->willingness);
538
539   printf("IPC connections  : %d\n", cnf->ipc_connections);
540   while (ie) {
541     struct ipaddr_str strbuf;
542     if (ie->net.prefix_len == olsr_cnf->maxplen) {
543       printf("\tHost %s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
544     } else {
545       printf("\tNet %s/%d\n", olsr_ip_to_string(&strbuf, &ie->net.prefix), ie->net.prefix_len);
546     }
547     ie = ie->next;
548   }
549
550   printf("Pollrate         : %0.2f\n", cnf->pollrate);
551
552   printf("NIC ChangPollrate: %0.2f\n", cnf->nic_chgs_pollrate);
553
554   printf("TC redundancy    : %d\n", cnf->tc_redundancy);
555
556   printf("MPR coverage     : %d\n", cnf->mpr_coverage);
557
558   printf("LQ level         : %d\n", cnf->lq_level);
559
560   printf("LQ fish eye      : %d\n", cnf->lq_fish);
561
562   printf("LQ Dijkstra limit: %d, %0.2f\n", cnf->lq_dlimit, cnf->lq_dinter);
563
564   printf("LQ aging factor  : %f\n", cnf->lq_aging);
565
566   printf("LQ algorithm name: %s\n", cnf->lq_algorithm ? cnf->lq_algorithm : "default");
567
568   printf("NAT threshold    : %f\n", cnf->lq_nat_thresh);
569
570   printf("Clear screen     : %s\n", cnf->clear_screen ? "yes" : "no");
571
572   /* Interfaces */
573   if (in) {
574     printf("Interfaces:\n");
575     while (in) {
576       printf(" dev: \"%s\"\n", in->name);
577
578       if (in->cnf->ipv4_broadcast.v4.s_addr) {
579         printf("\tIPv4 broadcast           : %s\n", inet_ntoa(in->cnf->ipv4_broadcast.v4));
580       } else {
581         printf("\tIPv4 broadcast           : AUTO\n");
582       }
583
584       if (in->cnf->mode==IF_MODE_ETHER){
585         printf("\tMode           : ether\n");
586       } else {
587         printf("\tMode           : mesh\n");
588       }
589
590       printf("\tIPv6 addrtype            : %s\n", in->cnf->ipv6_addrtype ? "site-local" : "global");
591
592       //union olsr_ip_addr       ipv6_multi_site;
593       //union olsr_ip_addr       ipv6_multi_glbl;
594       printf("\tIPv6 multicast site/glbl : %s", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
595       printf("/%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
596
597       printf("\tHELLO emission/validity  : %0.2f/%0.2f\n", in->cnf->hello_params.emission_interval,
598              in->cnf->hello_params.validity_time);
599       printf("\tTC emission/validity     : %0.2f/%0.2f\n", in->cnf->tc_params.emission_interval, in->cnf->tc_params.validity_time);
600       printf("\tMID emission/validity    : %0.2f/%0.2f\n", in->cnf->mid_params.emission_interval,
601              in->cnf->mid_params.validity_time);
602       printf("\tHNA emission/validity    : %0.2f/%0.2f\n", in->cnf->hna_params.emission_interval,
603              in->cnf->hna_params.validity_time);
604
605       for (mult = in->cnf->lq_mult; mult != NULL; mult = mult->next) {
606         printf("\tLinkQualityMult          : %s %0.2f\n", inet_ntop(cnf->ip_version, &mult->addr, ipv6_buf, sizeof(ipv6_buf)),
607                (float)(mult->value) / 65536.0);
608       }
609
610       printf("\tAutodetetc changes       : %s\n", in->cnf->autodetect_chg ? "yes" : "no");
611
612       in = in->next;
613     }
614   }
615
616   /* Plugins */
617   if (pe) {
618     printf("Plugins:\n");
619
620     while (pe) {
621       printf("\tName: \"%s\"\n", pe->name);
622       pe = pe->next;
623     }
624   }
625
626   /* Hysteresis */
627   if (cnf->use_hysteresis) {
628     printf("Using hysteresis:\n");
629     printf("\tScaling      : %0.2f\n", cnf->hysteresis_param.scaling);
630     printf("\tThr high/low : %0.2f/%0.2f\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low);
631   } else {
632     printf("Not using hysteresis\n");
633   }
634
635   /* HNA IPv4 and IPv6 */
636   if (h) {
637     printf("HNA%d entries:\n", cnf->ip_version == AF_INET ? 4 : 6);
638     while (h) {
639       struct ipaddr_str buf;
640       printf("\t%s/", olsr_ip_to_string(&buf, &h->net.prefix));
641       if (cnf->ip_version == AF_INET) {
642         union olsr_ip_addr ip;
643         olsr_prefix_to_netmask(&ip, h->net.prefix_len);
644         printf("%s\n", olsr_ip_to_string(&buf, &ip));
645       } else {
646         printf("%d\n", h->net.prefix_len);
647       }
648       h = h->next;
649     }
650   }
651 }
652
653 #if defined WIN32
654 struct ioinfo {
655   unsigned int handle;
656   unsigned char attr;
657   char buff;
658   int flag;
659   CRITICAL_SECTION lock;
660 };
661
662 void
663 win32_stdio_hack(unsigned int handle)
664 {
665   HMODULE lib;
666   struct ioinfo **info;
667
668   lib = LoadLibrary("msvcrt.dll");
669
670   info = (struct ioinfo **)GetProcAddress(lib, "__pioinfo");
671
672   // (*info)[1].handle = handle;
673   // (*info)[1].attr = 0x89; // FOPEN | FTEXT | FPIPE;
674
675   (*info)[2].handle = handle;
676   (*info)[2].attr = 0x89;
677
678   // stdout->_file = 1;
679   stderr->_file = 2;
680
681   // setbuf(stdout, NULL);
682   setbuf(stderr, NULL);
683 }
684
685 void *
686 win32_olsrd_malloc(size_t size)
687 {
688   return malloc(size);
689 }
690
691 void
692 win32_olsrd_free(void *ptr)
693 {
694   free(ptr);
695 }
696 #endif
697
698 void
699 ip_prefix_list_add(struct ip_prefix_list **list, const union olsr_ip_addr *net, uint8_t prefix_len)
700 {
701   struct ip_prefix_list *new_entry = malloc(sizeof(*new_entry));
702
703   new_entry->net.prefix = *net;
704   new_entry->net.prefix_len = prefix_len;
705
706   /* Queue */
707   new_entry->next = *list;
708   *list = new_entry;
709 }
710
711 int
712 ip_prefix_list_remove(struct ip_prefix_list **list, const union olsr_ip_addr *net, uint8_t prefix_len)
713 {
714   struct ip_prefix_list *h = *list, *prev = NULL;
715
716   while (h != NULL) {
717     if (ipequal(net, &h->net.prefix) && h->net.prefix_len == prefix_len) {
718       /* Dequeue */
719       if (prev == NULL) {
720         *list = h->next;
721       } else {
722         prev->next = h->next;
723       }
724       free(h);
725       return 1;
726     }
727     prev = h;
728     h = h->next;
729   }
730   return 0;
731 }
732
733 struct ip_prefix_list *
734 ip_prefix_list_find(struct ip_prefix_list *list, const union olsr_ip_addr *net, uint8_t prefix_len)
735 {
736   struct ip_prefix_list *h;
737   for (h = list; h != NULL; h = h->next) {
738     if (prefix_len == h->net.prefix_len && ipequal(net, &h->net.prefix)) {
739       return h;
740     }
741   }
742   return NULL;
743 }
744
745 /*
746  * Local Variables:
747  * c-basic-offset: 2
748  * indent-tabs-mode: nil
749  * End:
750  */