Bugfix for Link quality dijkstra limit
[olsrd.git] / src / cfgparser / olsrd_conf.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
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
59 extern FILE *yyin;
60 extern int yyparse(void);
61
62 static char copyright_string[] __attribute__((unused)) = "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas T√łnnesen(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     {
80       fprintf(stderr, "Usage: olsrd_cfgparser [filename] -print\n\n");
81       exit(EXIT_FAILURE);
82     }
83
84   if((cnf = olsrd_parse_cnf(argv[1])) != NULL)
85     {
86       if((argc > 2) && (!strcmp(argv[2], "-print")))
87         {
88           olsrd_print_cnf(cnf);  
89           olsrd_write_cnf(cnf, "./out.conf");
90         }
91       else
92         printf("Use -print to view parsed values\n");
93       printf("Configfile parsed OK\n");
94     }
95   else
96     {
97       printf("Failed parsing \"%s\"\n", argv[1]);
98     }
99
100   return 0;
101 }
102
103 #else
104
105 /* Build as part of olsrd */
106
107
108 #endif
109
110 struct olsrd_config *
111 olsrd_parse_cnf(const char *filename)
112 {
113   struct olsr_if *in, *new_ifqueue;
114   int rc;
115
116   /* Initialize the global varibles - oparse.y needs it there */
117   olsr_cnf = malloc(sizeof(*olsr_cnf));
118   if (olsr_cnf == NULL) {
119     fprintf(stderr, "Out of memory %s\n", __func__);
120     return NULL;
121   }
122
123   set_default_cnf(olsr_cnf);
124
125   printf("Parsing file: \"%s\"\n", filename);
126
127   yyin = fopen(filename, "r");
128   if (yyin == NULL) {
129     fprintf(stderr, "Cannot open configuration file '%s': %s.\n",
130             filename, strerror(errno));
131     olsrd_free_cnf(olsr_cnf);
132     olsr_cnf = NULL;
133     return NULL;
134   }
135
136   current_line = 1;
137   rc = yyparse();
138   fclose(yyin);
139   if (rc != 0) {
140     olsrd_free_cnf(olsr_cnf);
141     olsr_cnf = NULL;
142     return NULL;
143   }
144
145   /* Reverse the queue (added by user request) */
146   in = olsr_cnf->interfaces;
147   new_ifqueue = NULL;
148
149   while(in) {
150     struct olsr_if *in_tmp = in; 
151     in = in->next;
152
153     in_tmp->next = new_ifqueue;
154     new_ifqueue = in_tmp;
155   }
156
157   olsr_cnf->interfaces = new_ifqueue;
158
159   for (in = olsr_cnf->interfaces; in != NULL; in = in->next) {
160       /* set various stuff */
161       in->configured = OLSR_FALSE;
162       in->interf = NULL;
163       in->host_emul = OLSR_FALSE;
164   }
165   return olsr_cnf;
166 }
167
168
169 int
170 olsrd_sanity_check_cnf(struct olsrd_config *cnf)
171 {
172   struct olsr_if           *in = cnf->interfaces;
173   struct if_config_options *io;
174
175   /* Debug level */
176   if(cnf->debug_level < MIN_DEBUGLVL ||
177      cnf->debug_level > MAX_DEBUGLVL)
178     {
179       fprintf(stderr, "Debuglevel %d is not allowed\n", cnf->debug_level);
180       return -1;
181     }
182
183   /* IP version */
184   if(cnf->ip_version != AF_INET &&
185      cnf->ip_version != AF_INET6)
186     {
187       fprintf(stderr, "Ipversion %d not allowed!\n", cnf->ip_version);
188       return -1;
189     }
190
191   /* TOS */
192   if(//cnf->tos < MIN_TOS ||
193      cnf->tos > MAX_TOS)
194     {
195       fprintf(stderr, "TOS %d is not allowed\n", cnf->tos);
196       return -1;
197     }
198
199   if(cnf->willingness_auto == OLSR_FALSE &&
200      (cnf->willingness > MAX_WILLINGNESS))
201     {
202       fprintf(stderr, "Willingness %d is not allowed\n", cnf->willingness);
203       return -1;
204     }
205
206   /* Hysteresis */
207   if(cnf->use_hysteresis == OLSR_TRUE)
208     {
209       if(cnf->hysteresis_param.scaling < MIN_HYST_PARAM ||
210          cnf->hysteresis_param.scaling > MAX_HYST_PARAM)
211         {
212           fprintf(stderr, "Hyst scaling %0.2f is not allowed\n", cnf->hysteresis_param.scaling);
213           return -1;
214         }
215
216       if(cnf->hysteresis_param.thr_high <= cnf->hysteresis_param.thr_low)
217         {
218           fprintf(stderr, "Hyst upper(%0.2f) thr must be bigger than lower(%0.2f) threshold!\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low);
219           return -1;
220         }
221
222       if(cnf->hysteresis_param.thr_high < MIN_HYST_PARAM ||
223          cnf->hysteresis_param.thr_high > MAX_HYST_PARAM)
224         {
225           fprintf(stderr, "Hyst upper thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_high);
226           return -1;
227         }
228
229       if(cnf->hysteresis_param.thr_low < MIN_HYST_PARAM ||
230          cnf->hysteresis_param.thr_low > MAX_HYST_PARAM)
231         {
232           fprintf(stderr, "Hyst lower thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_low);
233           return -1;
234         }
235     }
236
237   /* Check Link quality dijkstra limit */
238   if (olsr_cnf->lq_dinter < cnf->pollrate && olsr_cnf->lq_dlimit != 255) {
239         fprintf(stderr, "Link quality dijkstra limit must be higher than pollrate\n");
240         return -1;
241   }
242   
243   /* Pollrate */
244
245   if(cnf->pollrate < MIN_POLLRATE ||
246      cnf->pollrate > MAX_POLLRATE)
247     {
248       fprintf(stderr, "Pollrate %0.2f is not allowed\n", cnf->pollrate);
249       return -1;
250     }
251
252   /* NIC Changes Pollrate */
253
254   if(cnf->nic_chgs_pollrate < MIN_NICCHGPOLLRT ||
255      cnf->nic_chgs_pollrate > MAX_NICCHGPOLLRT)
256     {
257       fprintf(stderr, "NIC Changes Pollrate %0.2f is not allowed\n", cnf->nic_chgs_pollrate);
258       return -1;
259     }
260
261   /* TC redundancy */
262
263   if(//cnf->tc_redundancy < MIN_TC_REDUNDANCY ||
264      cnf->tc_redundancy > MAX_TC_REDUNDANCY)
265     {
266       fprintf(stderr, "TC redundancy %d is not allowed\n", cnf->tc_redundancy);
267       return -1;
268     }
269
270   /* MPR coverage */
271   if(cnf->mpr_coverage < MIN_MPR_COVERAGE ||
272      cnf->mpr_coverage > MAX_MPR_COVERAGE)
273     {
274       fprintf(stderr, "MPR coverage %d is not allowed\n", cnf->mpr_coverage);
275       return -1;
276     }
277
278   /* Link Q and hysteresis cannot be activated at the same time */
279   if(cnf->use_hysteresis == OLSR_TRUE && cnf->lq_level)
280     {
281       fprintf(stderr, "Hysteresis and LinkQuality cannot both be active! Deactivate one of them.\n");
282       return -1;
283     }
284
285   /* Link quality level */
286
287   if(cnf->lq_level > MAX_LQ_LEVEL)
288     {
289       fprintf(stderr, "LQ level %d is not allowed\n", cnf->lq_level);
290       return -1;
291     }
292
293   /* Link quality window size */
294   if(cnf->lq_level && (cnf->lq_wsize < MIN_LQ_WSIZE || cnf->lq_wsize > MAX_LQ_WSIZE))
295     {
296       fprintf(stderr, "LQ window size %d is not allowed\n", cnf->lq_wsize);
297       return -1;
298     }
299
300   /* NAT threshold value */
301   if(cnf->lq_level && (cnf->lq_nat_thresh < 0.1 || cnf->lq_nat_thresh > 1.0))
302     {
303       fprintf(stderr, "NAT threshold %f is not allowed\n", cnf->lq_nat_thresh);
304       return -1;
305     }
306
307   if(in == NULL)
308     {
309       fprintf(stderr, "No interfaces configured!\n");
310       return -1;
311     }
312
313   /* Interfaces */
314   while(in)
315     {
316       io = in->cnf;
317
318       if(in->name == NULL || !strlen(in->name))
319         {
320           fprintf(stderr, "Interface has no name!\n");
321           return -1;
322         }
323
324       if(io == NULL)
325         {
326           fprintf(stderr, "Interface %s has no configuration!\n", in->name);
327           return -1;
328         }
329         
330       /* HELLO interval */
331
332       if (io->hello_params.validity_time < 0.0)
333       {
334         if (cnf->lq_level == 0)
335           io->hello_params.validity_time = NEIGHB_HOLD_TIME;
336
337         else
338           io->hello_params.validity_time = cnf->lq_wsize * io->hello_params.emission_interval;
339       }
340
341       if(io->hello_params.emission_interval < cnf->pollrate ||
342          io->hello_params.emission_interval > io->hello_params.validity_time)
343         {
344           fprintf(stderr, "Bad HELLO parameters! (em: %0.2f, vt: %0.2f)\n", io->hello_params.emission_interval, io->hello_params.validity_time);
345           return -1;
346         }
347
348       /* TC interval */
349       if(io->tc_params.emission_interval < cnf->pollrate ||
350          io->tc_params.emission_interval > io->tc_params.validity_time)
351         {
352           fprintf(stderr, "Bad TC parameters! (em: %0.2f, vt: %0.2f)\n", io->tc_params.emission_interval, io->tc_params.validity_time);
353           return -1;
354         }
355
356       /* MID interval */
357       if(io->mid_params.emission_interval < cnf->pollrate ||
358          io->mid_params.emission_interval > io->mid_params.validity_time)
359         {
360           fprintf(stderr, "Bad MID parameters! (em: %0.2f, vt: %0.2f)\n", io->mid_params.emission_interval, io->mid_params.validity_time);
361           return -1;
362         }
363
364       /* HNA interval */
365       if(io->hna_params.emission_interval < cnf->pollrate ||
366          io->hna_params.emission_interval > io->hna_params.validity_time)
367         {
368           fprintf(stderr, "Bad HNA parameters! (em: %0.2f, vt: %0.2f)\n", io->hna_params.emission_interval, io->hna_params.validity_time);
369           return -1;
370         }
371
372       in = in->next;
373     }
374
375   return 0;
376 }
377
378
379 void
380 olsrd_free_cnf(struct olsrd_config *cnf)
381 {
382   struct ip_prefix_list   *hd,   *h = cnf->hna_entries;
383   struct olsr_if           *ind, *in = cnf->interfaces;
384   struct plugin_entry      *ped, *pe = cnf->plugins;
385   struct olsr_lq_mult      *mult, *next_mult;
386   
387   while(h)
388     {
389       hd = h;
390       h = h->next;
391       free(hd);
392     }
393
394   while(in)
395     {
396       for (mult = in->cnf->lq_mult; mult != NULL; mult = next_mult)
397       {
398         next_mult = mult->next;
399         free(mult);
400       }
401
402       free(in->cnf);
403       ind = in;
404       in = in->next;
405       free(ind->name);
406       free(ind->config);
407       free(ind);
408     }
409
410   while(pe)
411     {
412       ped = pe;
413       pe = pe->next;
414       free(ped->name);
415       free(ped);
416     }
417
418   return;
419 }
420
421
422
423 struct olsrd_config *
424 olsrd_get_default_cnf(void)
425 {
426   struct olsrd_config *c = malloc(sizeof(struct olsrd_config));
427   if (c == NULL) {
428     fprintf(stderr, "Out of memory %s\n", __func__);
429     return NULL;
430   }
431
432   set_default_cnf(c);
433   return c;
434 }
435
436
437
438
439 void
440 set_default_cnf(struct olsrd_config *cnf)
441 {
442     memset(cnf, 0, sizeof(*cnf));
443     
444     cnf->debug_level = DEF_DEBUGLVL;
445     cnf->no_fork = OLSR_FALSE;
446     cnf->host_emul = OLSR_FALSE;
447     cnf->ip_version  = AF_INET;
448     cnf->ipsize = sizeof(struct in_addr);
449     cnf->maxplen = 32;
450     cnf->allow_no_interfaces = DEF_ALLOW_NO_INTS;
451     cnf->tos = DEF_TOS;
452     cnf->rttable = 254;
453     cnf->rttable_default = 0;
454     cnf->willingness_auto = DEF_WILL_AUTO;
455     cnf->ipc_connections = DEF_IPC_CONNECTIONS;
456     cnf->fib_metric = DEF_FIB_METRIC;
457
458     cnf->use_hysteresis = DEF_USE_HYST;
459     cnf->hysteresis_param.scaling = HYST_SCALING;
460     cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
461     cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
462
463     cnf->pollrate = DEF_POLLRATE;
464     cnf->nic_chgs_pollrate = DEF_NICCHGPOLLRT;
465
466     cnf->tc_redundancy = TC_REDUNDANCY;
467     cnf->mpr_coverage = MPR_COVERAGE;
468     cnf->lq_level = DEF_LQ_LEVEL;
469     cnf->lq_fish = DEF_LQ_FISH;
470     cnf->lq_dlimit = DEF_LQ_DIJK_LIMIT;
471     cnf->lq_dinter = DEF_LQ_DIJK_INTER;
472     cnf->lq_wsize = DEF_LQ_WSIZE;
473     cnf->lq_nat_thresh = DEF_LQ_NAT_THRESH;
474     cnf->clear_screen = DEF_CLEAR_SCREEN;
475
476     cnf->del_gws = OLSR_FALSE;
477     cnf->will_int = 10 * HELLO_INTERVAL;
478     cnf->max_jitter = 0.0;
479     cnf->exit_value = EXIT_SUCCESS;
480     cnf->max_tc_vtime = 0.0;
481     cnf->ioctl_s = 0;
482 #if LINUX_POLICY_ROUTING
483     cnf->rtnl_s = 0;
484 #endif
485
486 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
487     cnf->rts = 0;
488 #endif
489 }
490
491
492
493
494 struct if_config_options *
495 get_default_if_config(void)
496 {
497   struct in6_addr in6;
498   struct if_config_options *io = malloc(sizeof(*io));
499
500   if(io == NULL) {
501     fprintf(stderr, "Out of memory %s\n", __func__);
502     return NULL;
503   }
504
505   memset(io, 0, sizeof(*io));
506
507   io->ipv6_addrtype = 1; /* XXX - FixMe */
508
509   inet_pton(AF_INET6, OLSR_IPV6_MCAST_SITE_LOCAL, &in6);
510   io->ipv6_multi_site.v6 = in6;
511
512   inet_pton(AF_INET6, OLSR_IPV6_MCAST_GLOBAL, &in6);
513   io->ipv6_multi_glbl.v6 = in6;
514
515   io->lq_mult = NULL;
516
517   io->weight.fixed = OLSR_FALSE;
518   io->weight.value = 0;
519
520   io->ipv6_addrtype = 0; /* global */
521
522   io->hello_params.emission_interval = HELLO_INTERVAL;
523   io->hello_params.validity_time = NEIGHB_HOLD_TIME;
524   io->tc_params.emission_interval = TC_INTERVAL;
525   io->tc_params.validity_time = TOP_HOLD_TIME;
526   io->mid_params.emission_interval = MID_INTERVAL;
527   io->mid_params.validity_time = MID_HOLD_TIME;
528   io->hna_params.emission_interval = HNA_INTERVAL;
529   io->hna_params.validity_time = HNA_HOLD_TIME;
530   io->autodetect_chg = OLSR_TRUE;
531
532   return io;
533
534 }
535
536
537
538 void
539 olsrd_print_cnf(struct olsrd_config *cnf)
540 {
541   struct ip_prefix_list   *h  = cnf->hna_entries;
542   struct olsr_if           *in = cnf->interfaces;
543   struct plugin_entry      *pe = cnf->plugins;
544   struct ip_prefix_list    *ie = cnf->ipc_nets;
545   struct olsr_lq_mult      *mult;
546   char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
547
548   printf(" *** olsrd configuration ***\n");
549
550   printf("Debug Level      : %d\n", cnf->debug_level);
551   if(cnf->ip_version == AF_INET6)
552     printf("IpVersion        : 6\n");
553   else
554     printf("IpVersion        : 4\n");
555   if(cnf->allow_no_interfaces)
556     printf("No interfaces    : ALLOWED\n");
557   else
558     printf("No interfaces    : NOT ALLOWED\n");
559   printf("TOS              : 0x%02x\n", cnf->tos);
560   printf("RtTable          : 0x%02x\n", cnf->rttable);
561   printf("RtTableDefault   : 0x%02x\n", cnf->rttable_default);
562   if(cnf->willingness_auto)
563     printf("Willingness      : AUTO\n");
564   else
565     printf("Willingness      : %d\n", cnf->willingness);
566
567   printf("IPC connections  : %d\n", cnf->ipc_connections);
568   while(ie)
569     {
570       struct ipaddr_str strbuf;
571       if (ie->net.prefix_len == olsr_cnf->maxplen) {
572           printf("\tHost %s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
573       } else {
574           printf("\tNet %s/%d\n", olsr_ip_to_string(&strbuf, &ie->net.prefix), ie->net.prefix_len);
575       }
576       ie = ie->next;
577     }
578
579
580   printf("Pollrate         : %0.2f\n", cnf->pollrate);
581
582   printf("NIC ChangPollrate: %0.2f\n", cnf->nic_chgs_pollrate);
583
584   printf("TC redundancy    : %d\n", cnf->tc_redundancy);
585
586   printf("MPR coverage     : %d\n", cnf->mpr_coverage);
587    
588   printf("LQ level         : %d\n", cnf->lq_level);
589
590   printf("LQ fish eye      : %d\n", cnf->lq_fish);
591
592   printf("LQ Dijkstra limit: %d, %0.2f\n", cnf->lq_dlimit, cnf->lq_dinter);
593
594   printf("LQ window size   : %d\n", cnf->lq_wsize);
595
596   printf("NAT threshold    : %f\n", cnf->lq_nat_thresh);
597
598   printf("Clear screen     : %s\n", cnf->clear_screen ? "yes" : "no");
599
600   /* Interfaces */
601   if(in)
602     {
603       printf("Interfaces:\n");
604       while(in)
605         {
606           printf(" dev: \"%s\"\n", in->name);
607           
608           if(in->cnf->ipv4_broadcast.v4.s_addr)
609             {
610               printf("\tIPv4 broadcast           : %s\n", inet_ntoa(in->cnf->ipv4_broadcast.v4));
611             }
612           else
613             {
614               printf("\tIPv4 broadcast           : AUTO\n");
615             }
616           
617           printf("\tIPv6 addrtype            : %s\n", in->cnf->ipv6_addrtype ? "site-local" : "global");
618           
619           //union olsr_ip_addr       ipv6_multi_site;
620           //union olsr_ip_addr       ipv6_multi_glbl;
621           printf("\tIPv6 multicast site/glbl : %s", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
622           printf("/%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
623           
624           printf("\tHELLO emission/validity  : %0.2f/%0.2f\n", in->cnf->hello_params.emission_interval, in->cnf->hello_params.validity_time);
625           printf("\tTC emission/validity     : %0.2f/%0.2f\n", in->cnf->tc_params.emission_interval, in->cnf->tc_params.validity_time);
626           printf("\tMID emission/validity    : %0.2f/%0.2f\n", in->cnf->mid_params.emission_interval, in->cnf->mid_params.validity_time);
627           printf("\tHNA emission/validity    : %0.2f/%0.2f\n", in->cnf->hna_params.emission_interval, in->cnf->hna_params.validity_time);
628           
629           for (mult = in->cnf->lq_mult; mult != NULL; mult = mult->next)
630           {
631             printf("\tLinkQualityMult          : %s %0.2f\n", inet_ntop(cnf->ip_version, &mult->addr, ipv6_buf, sizeof (ipv6_buf)), mult->val);
632           }
633
634           printf("\tAutodetetc changes       : %s\n", in->cnf->autodetect_chg ? "yes" : "no");
635
636           in = in->next;
637         }
638     }
639
640
641
642
643   /* Plugins */
644   if(pe)
645     {
646       printf("Plugins:\n");
647
648       while(pe)
649         {
650           printf("\tName: \"%s\"\n", pe->name);
651           pe = pe->next;
652         }
653     }
654
655   /* Hysteresis */
656   if(cnf->use_hysteresis) {
657     printf("Using hysteresis:\n");
658     printf("\tScaling      : %0.2f\n", cnf->hysteresis_param.scaling);
659     printf("\tThr high/low : %0.2f/%0.2f\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low);
660   } else {
661     printf("Not using hysteresis\n");
662   }
663
664   /* HNA IPv4 and IPv6 */
665   if(h) {
666     printf("HNA%d entries:\n", cnf->ip_version == AF_INET ? 4 : 6);
667     while(h) {
668       struct ipaddr_str buf;
669       printf("\t%s/", olsr_ip_to_string(&buf, &h->net.prefix));
670       if (cnf->ip_version == AF_INET) {
671         union olsr_ip_addr ip;
672         olsr_prefix_to_netmask(&ip, h->net.prefix_len);
673         printf("%s\n", olsr_ip_to_string(&buf, &ip));
674       } else {
675         printf("%d\n", h->net.prefix_len);
676       }
677       h = h->next;
678     }
679   }
680 }
681
682 #if defined WIN32
683 struct ioinfo
684 {
685         unsigned int handle;
686         unsigned char attr;
687         char buff;
688         int flag;
689         CRITICAL_SECTION lock;
690 };
691
692 void win32_stdio_hack(unsigned int handle)
693 {
694   HMODULE lib;
695   struct ioinfo **info;
696
697   lib = LoadLibrary("msvcrt.dll");
698
699   info = (struct ioinfo **)GetProcAddress(lib, "__pioinfo");
700
701   // (*info)[1].handle = handle;
702   // (*info)[1].attr = 0x89; // FOPEN | FTEXT | FPIPE;
703
704   (*info)[2].handle = handle;
705   (*info)[2].attr = 0x89;
706
707   // stdout->_file = 1;
708   stderr->_file = 2;
709
710   // setbuf(stdout, NULL);
711   setbuf(stderr, NULL);
712 }
713
714 void*
715 win32_olsrd_malloc(size_t size)
716 {
717         return malloc(size);
718 }
719
720 void
721 win32_olsrd_free(void* ptr)
722 {
723         free(ptr);
724 }
725 #endif
726
727 void ip_prefix_list_add(struct ip_prefix_list **list,
728                         const union olsr_ip_addr *net,
729                         olsr_u8_t prefix_len)
730 {
731   struct ip_prefix_list *new_entry = malloc(sizeof(*new_entry));
732   
733   new_entry->net.prefix = *net;
734   new_entry->net.prefix_len = prefix_len;
735
736   /* Queue */
737   new_entry->next = *list;
738   *list = new_entry;
739 }
740
741 int ip_prefix_list_remove(struct ip_prefix_list **list,
742                           const union olsr_ip_addr *net,
743                           olsr_u8_t prefix_len)
744 {
745   struct ip_prefix_list *h = *list, *prev = NULL;
746
747   while (h != NULL) {
748     if (ipequal(net, &h->net.prefix) && h->net.prefix_len == prefix_len) {
749       /* Dequeue */
750       if (prev == NULL) {
751         *list = h->next;
752       } else {
753         prev->next = h->next;
754       }
755       free(h);
756       return 1;
757     }
758     prev = h;
759     h = h->next;
760   }
761   return 0;
762 }
763
764 struct ip_prefix_list *ip_prefix_list_find(struct ip_prefix_list *list,
765                                            const union olsr_ip_addr *net,
766                                            olsr_u8_t prefix_len)
767 {
768   struct ip_prefix_list *h;
769   for (h = list; h != NULL; h = h->next) {
770     if (prefix_len == h->net.prefix_len && ipequal(net, &h->net.prefix)) {
771       return h;
772     }
773   }
774   return NULL;
775 }