lqnatthresh: maintain an advantage for the current (NAT) inet gw
[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   /* Pollrate */
238
239   if(cnf->pollrate < MIN_POLLRATE ||
240      cnf->pollrate > MAX_POLLRATE)
241     {
242       fprintf(stderr, "Pollrate %0.2f is not allowed\n", cnf->pollrate);
243       return -1;
244     }
245
246   /* NIC Changes Pollrate */
247
248   if(cnf->nic_chgs_pollrate < MIN_NICCHGPOLLRT ||
249      cnf->nic_chgs_pollrate > MAX_NICCHGPOLLRT)
250     {
251       fprintf(stderr, "NIC Changes Pollrate %0.2f is not allowed\n", cnf->nic_chgs_pollrate);
252       return -1;
253     }
254
255   /* TC redundancy */
256
257   if(//cnf->tc_redundancy < MIN_TC_REDUNDANCY ||
258      cnf->tc_redundancy > MAX_TC_REDUNDANCY)
259     {
260       fprintf(stderr, "TC redundancy %d is not allowed\n", cnf->tc_redundancy);
261       return -1;
262     }
263
264   /* MPR coverage */
265   if(cnf->mpr_coverage < MIN_MPR_COVERAGE ||
266      cnf->mpr_coverage > MAX_MPR_COVERAGE)
267     {
268       fprintf(stderr, "MPR coverage %d is not allowed\n", cnf->mpr_coverage);
269       return -1;
270     }
271
272   /* Link Q and hysteresis cannot be activated at the same time */
273   if(cnf->use_hysteresis == OLSR_TRUE && cnf->lq_level)
274     {
275       fprintf(stderr, "Hysteresis and LinkQuality cannot both be active! Deactivate one of them.\n");
276       return -1;
277     }
278
279   /* Link quality level */
280
281   if(cnf->lq_level > MAX_LQ_LEVEL)
282     {
283       fprintf(stderr, "LQ level %d is not allowed\n", cnf->lq_level);
284       return -1;
285     }
286
287   /* Link quality window size */
288   if(cnf->lq_level && (cnf->lq_wsize < MIN_LQ_WSIZE || cnf->lq_wsize > MAX_LQ_WSIZE))
289     {
290       fprintf(stderr, "LQ window size %d is not allowed\n", cnf->lq_wsize);
291       return -1;
292     }
293
294   /* NAT threshold value */
295   if(cnf->lq_level && (cnf->lq_nat_thresh < 0.1 || cnf->lq_nat_thresh > 1.0))
296     {
297       fprintf(stderr, "NAT threshold %f is not allowed\n", cnf->lq_nat_thresh);
298       return -1;
299     }
300
301   if(in == NULL)
302     {
303       fprintf(stderr, "No interfaces configured!\n");
304       return -1;
305     }
306
307   /* Interfaces */
308   while(in)
309     {
310       io = in->cnf;
311
312       if(in->name == NULL || !strlen(in->name))
313         {
314           fprintf(stderr, "Interface has no name!\n");
315           return -1;
316         }
317
318       if(io == NULL)
319         {
320           fprintf(stderr, "Interface %s has no configuration!\n", in->name);
321           return -1;
322         }
323         
324       /* HELLO interval */
325
326       if (io->hello_params.validity_time < 0.0)
327       {
328         if (cnf->lq_level == 0)
329           io->hello_params.validity_time = NEIGHB_HOLD_TIME;
330
331         else
332           io->hello_params.validity_time = cnf->lq_wsize * io->hello_params.emission_interval;
333       }
334
335       if(io->hello_params.emission_interval < cnf->pollrate ||
336          io->hello_params.emission_interval > io->hello_params.validity_time)
337         {
338           fprintf(stderr, "Bad HELLO parameters! (em: %0.2f, vt: %0.2f)\n", io->hello_params.emission_interval, io->hello_params.validity_time);
339           return -1;
340         }
341
342       /* TC interval */
343       if(io->tc_params.emission_interval < cnf->pollrate ||
344          io->tc_params.emission_interval > io->tc_params.validity_time)
345         {
346           fprintf(stderr, "Bad TC parameters! (em: %0.2f, vt: %0.2f)\n", io->tc_params.emission_interval, io->tc_params.validity_time);
347           return -1;
348         }
349
350       /* MID interval */
351       if(io->mid_params.emission_interval < cnf->pollrate ||
352          io->mid_params.emission_interval > io->mid_params.validity_time)
353         {
354           fprintf(stderr, "Bad MID parameters! (em: %0.2f, vt: %0.2f)\n", io->mid_params.emission_interval, io->mid_params.validity_time);
355           return -1;
356         }
357
358       /* HNA interval */
359       if(io->hna_params.emission_interval < cnf->pollrate ||
360          io->hna_params.emission_interval > io->hna_params.validity_time)
361         {
362           fprintf(stderr, "Bad HNA parameters! (em: %0.2f, vt: %0.2f)\n", io->hna_params.emission_interval, io->hna_params.validity_time);
363           return -1;
364         }
365
366       in = in->next;
367     }
368
369   return 0;
370 }
371
372
373 void
374 olsrd_free_cnf(struct olsrd_config *cnf)
375 {
376   struct ip_prefix_list   *hd,   *h = cnf->hna_entries;
377   struct olsr_if           *ind, *in = cnf->interfaces;
378   struct plugin_entry      *ped, *pe = cnf->plugins;
379   struct olsr_lq_mult      *mult, *next_mult;
380   
381   while(h)
382     {
383       hd = h;
384       h = h->next;
385       free(hd);
386     }
387
388   while(in)
389     {
390       for (mult = in->cnf->lq_mult; mult != NULL; mult = next_mult)
391       {
392         next_mult = mult->next;
393         free(mult);
394       }
395
396       free(in->cnf);
397       ind = in;
398       in = in->next;
399       free(ind->name);
400       free(ind->config);
401       free(ind);
402     }
403
404   while(pe)
405     {
406       ped = pe;
407       pe = pe->next;
408       free(ped->name);
409       free(ped);
410     }
411
412   return;
413 }
414
415
416
417 struct olsrd_config *
418 olsrd_get_default_cnf(void)
419 {
420   struct olsrd_config *c = malloc(sizeof(struct olsrd_config));
421   if (c == NULL) {
422     fprintf(stderr, "Out of memory %s\n", __func__);
423     return NULL;
424   }
425
426   set_default_cnf(c);
427   return c;
428 }
429
430
431
432
433 void
434 set_default_cnf(struct olsrd_config *cnf)
435 {
436     memset(cnf, 0, sizeof(*cnf));
437     
438     cnf->debug_level = DEF_DEBUGLVL;
439     cnf->no_fork = OLSR_FALSE;
440     cnf->host_emul = OLSR_FALSE;
441     cnf->ip_version  = AF_INET;
442     cnf->ipsize = sizeof(struct in_addr);
443     cnf->maxplen = 32;
444     cnf->allow_no_interfaces = DEF_ALLOW_NO_INTS;
445     cnf->tos = DEF_TOS;
446     cnf->rttable = 254;
447     cnf->willingness_auto = DEF_WILL_AUTO;
448     cnf->ipc_connections = DEF_IPC_CONNECTIONS;
449     cnf->fib_metric = DEF_FIB_METRIC;
450
451     cnf->use_hysteresis = DEF_USE_HYST;
452     cnf->hysteresis_param.scaling = HYST_SCALING;
453     cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
454     cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
455
456     cnf->pollrate = DEF_POLLRATE;
457     cnf->nic_chgs_pollrate = DEF_NICCHGPOLLRT;
458
459     cnf->tc_redundancy = TC_REDUNDANCY;
460     cnf->mpr_coverage = MPR_COVERAGE;
461     cnf->lq_level = DEF_LQ_LEVEL;
462     cnf->lq_fish = DEF_LQ_FISH;
463     cnf->lq_dlimit = DEF_LQ_DIJK_LIMIT;
464     cnf->lq_dinter = DEF_LQ_DIJK_INTER;
465     cnf->lq_wsize = DEF_LQ_WSIZE;
466     cnf->lq_nat_thresh = DEF_LQ_NAT_THRESH;
467     cnf->clear_screen = DEF_CLEAR_SCREEN;
468
469     cnf->del_gws = OLSR_FALSE;
470     cnf->will_int = 10 * HELLO_INTERVAL;
471     cnf->max_jitter = 0.0;
472     cnf->exit_value = EXIT_SUCCESS;
473     cnf->max_tc_vtime = 0.0;
474     cnf->ioctl_s = 0;
475 #if LINUX_POLICY_ROUTING
476     cnf->rtnl_s = 0;
477 #endif
478
479 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
480     cnf->rts = 0;
481 #endif
482 }
483
484
485
486
487 struct if_config_options *
488 get_default_if_config(void)
489 {
490   struct in6_addr in6;
491   struct if_config_options *io = malloc(sizeof(*io));
492
493   if(io == NULL) {
494     fprintf(stderr, "Out of memory %s\n", __func__);
495     return NULL;
496   }
497
498   memset(io, 0, sizeof(*io));
499
500   io->ipv6_addrtype = 1; /* XXX - FixMe */
501
502   inet_pton(AF_INET6, OLSR_IPV6_MCAST_SITE_LOCAL, &in6);
503   io->ipv6_multi_site.v6 = in6;
504
505   inet_pton(AF_INET6, OLSR_IPV6_MCAST_GLOBAL, &in6);
506   io->ipv6_multi_glbl.v6 = in6;
507
508   io->lq_mult = NULL;
509
510   io->weight.fixed = OLSR_FALSE;
511   io->weight.value = 0;
512
513   io->ipv6_addrtype = 0; /* global */
514
515   io->hello_params.emission_interval = HELLO_INTERVAL;
516   io->hello_params.validity_time = NEIGHB_HOLD_TIME;
517   io->tc_params.emission_interval = TC_INTERVAL;
518   io->tc_params.validity_time = TOP_HOLD_TIME;
519   io->mid_params.emission_interval = MID_INTERVAL;
520   io->mid_params.validity_time = MID_HOLD_TIME;
521   io->hna_params.emission_interval = HNA_INTERVAL;
522   io->hna_params.validity_time = HNA_HOLD_TIME;
523   io->autodetect_chg = OLSR_TRUE;
524
525   return io;
526
527 }
528
529
530
531 void
532 olsrd_print_cnf(struct olsrd_config *cnf)
533 {
534   struct ip_prefix_list   *h  = cnf->hna_entries;
535   struct olsr_if           *in = cnf->interfaces;
536   struct plugin_entry      *pe = cnf->plugins;
537   struct ip_prefix_list    *ie = cnf->ipc_nets;
538   struct olsr_lq_mult      *mult;
539   char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
540
541   printf(" *** olsrd configuration ***\n");
542
543   printf("Debug Level      : %d\n", cnf->debug_level);
544   if(cnf->ip_version == AF_INET6)
545     printf("IpVersion        : 6\n");
546   else
547     printf("IpVersion        : 4\n");
548   if(cnf->allow_no_interfaces)
549     printf("No interfaces    : ALLOWED\n");
550   else
551     printf("No interfaces    : NOT ALLOWED\n");
552   printf("TOS              : 0x%02x\n", cnf->tos);
553   printf("RtTable          : 0x%02x\n", cnf->rttable);
554   if(cnf->willingness_auto)
555     printf("Willingness      : AUTO\n");
556   else
557     printf("Willingness      : %d\n", cnf->willingness);
558
559   printf("IPC connections  : %d\n", cnf->ipc_connections);
560   while(ie)
561     {
562       struct ipaddr_str strbuf;
563       if (ie->net.prefix_len == olsr_cnf->maxplen) {
564           printf("\tHost %s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
565       } else {
566           printf("\tNet %s/%d\n", olsr_ip_to_string(&strbuf, &ie->net.prefix), ie->net.prefix_len);
567       }
568       ie = ie->next;
569     }
570
571
572   printf("Pollrate         : %0.2f\n", cnf->pollrate);
573
574   printf("NIC ChangPollrate: %0.2f\n", cnf->nic_chgs_pollrate);
575
576   printf("TC redundancy    : %d\n", cnf->tc_redundancy);
577
578   printf("MPR coverage     : %d\n", cnf->mpr_coverage);
579    
580   printf("LQ level         : %d\n", cnf->lq_level);
581
582   printf("LQ fish eye      : %d\n", cnf->lq_fish);
583
584   printf("LQ Dijkstra limit: %d, %0.2f\n", cnf->lq_dlimit, cnf->lq_dinter);
585
586   printf("LQ window size   : %d\n", cnf->lq_wsize);
587
588   printf("NAT threshold    : %f\n", cnf->lq_nat_thresh);
589
590   printf("Clear screen     : %s\n", cnf->clear_screen ? "yes" : "no");
591
592   /* Interfaces */
593   if(in)
594     {
595       printf("Interfaces:\n");
596       while(in)
597         {
598           printf(" dev: \"%s\"\n", in->name);
599           
600           if(in->cnf->ipv4_broadcast.v4.s_addr)
601             {
602               printf("\tIPv4 broadcast           : %s\n", inet_ntoa(in->cnf->ipv4_broadcast.v4));
603             }
604           else
605             {
606               printf("\tIPv4 broadcast           : AUTO\n");
607             }
608           
609           printf("\tIPv6 addrtype            : %s\n", in->cnf->ipv6_addrtype ? "site-local" : "global");
610           
611           //union olsr_ip_addr       ipv6_multi_site;
612           //union olsr_ip_addr       ipv6_multi_glbl;
613           printf("\tIPv6 multicast site/glbl : %s", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
614           printf("/%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
615           
616           printf("\tHELLO emission/validity  : %0.2f/%0.2f\n", in->cnf->hello_params.emission_interval, in->cnf->hello_params.validity_time);
617           printf("\tTC emission/validity     : %0.2f/%0.2f\n", in->cnf->tc_params.emission_interval, in->cnf->tc_params.validity_time);
618           printf("\tMID emission/validity    : %0.2f/%0.2f\n", in->cnf->mid_params.emission_interval, in->cnf->mid_params.validity_time);
619           printf("\tHNA emission/validity    : %0.2f/%0.2f\n", in->cnf->hna_params.emission_interval, in->cnf->hna_params.validity_time);
620           
621           for (mult = in->cnf->lq_mult; mult != NULL; mult = mult->next)
622           {
623             printf("\tLinkQualityMult          : %s %0.2f\n", inet_ntop(cnf->ip_version, &mult->addr, ipv6_buf, sizeof (ipv6_buf)), mult->val);
624           }
625
626           printf("\tAutodetetc changes       : %s\n", in->cnf->autodetect_chg ? "yes" : "no");
627
628           in = in->next;
629         }
630     }
631
632
633
634
635   /* Plugins */
636   if(pe)
637     {
638       printf("Plugins:\n");
639
640       while(pe)
641         {
642           printf("\tName: \"%s\"\n", pe->name);
643           pe = pe->next;
644         }
645     }
646
647   /* Hysteresis */
648   if(cnf->use_hysteresis) {
649     printf("Using hysteresis:\n");
650     printf("\tScaling      : %0.2f\n", cnf->hysteresis_param.scaling);
651     printf("\tThr high/low : %0.2f/%0.2f\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low);
652   } else {
653     printf("Not using hysteresis\n");
654   }
655
656   /* HNA IPv4 and IPv6 */
657   if(h) {
658     printf("HNA%d entries:\n", cnf->ip_version == AF_INET ? 4 : 6);
659     while(h) {
660       struct ipaddr_str buf;
661       printf("\t%s/", olsr_ip_to_string(&buf, &h->net.prefix));
662       if (cnf->ip_version == AF_INET) {
663         union olsr_ip_addr ip;
664         olsr_prefix_to_netmask(&ip, h->net.prefix_len);
665         printf("%s\n", olsr_ip_to_string(&buf, &ip));
666       } else {
667         printf("%d\n", h->net.prefix_len);
668       }
669       h = h->next;
670     }
671   }
672 }
673
674 #if defined WIN32
675 struct ioinfo
676 {
677         unsigned int handle;
678         unsigned char attr;
679         char buff;
680         int flag;
681         CRITICAL_SECTION lock;
682 };
683
684 void win32_stdio_hack(unsigned int handle)
685 {
686   HMODULE lib;
687   struct ioinfo **info;
688
689   lib = LoadLibrary("msvcrt.dll");
690
691   info = (struct ioinfo **)GetProcAddress(lib, "__pioinfo");
692
693   // (*info)[1].handle = handle;
694   // (*info)[1].attr = 0x89; // FOPEN | FTEXT | FPIPE;
695
696   (*info)[2].handle = handle;
697   (*info)[2].attr = 0x89;
698
699   // stdout->_file = 1;
700   stderr->_file = 2;
701
702   // setbuf(stdout, NULL);
703   setbuf(stderr, NULL);
704 }
705
706 void*
707 win32_olsrd_malloc(size_t size)
708 {
709         return malloc(size);
710 }
711
712 void
713 win32_olsrd_free(void* ptr)
714 {
715         free(ptr);
716 }
717 #endif
718
719 void ip_prefix_list_add(struct ip_prefix_list **list,
720                         const union olsr_ip_addr *net,
721                         olsr_u8_t prefix_len)
722 {
723   struct ip_prefix_list *new_entry = malloc(sizeof(*new_entry));
724   
725   new_entry->net.prefix = *net;
726   new_entry->net.prefix_len = prefix_len;
727
728   /* Queue */
729   new_entry->next = *list;
730   *list = new_entry;
731 }
732
733 int ip_prefix_list_remove(struct ip_prefix_list **list,
734                           const union olsr_ip_addr *net,
735                           olsr_u8_t prefix_len)
736 {
737   struct ip_prefix_list *h = *list, *prev = NULL;
738
739   while (h != NULL) {
740     if (ipequal(net, &h->net.prefix) && h->net.prefix_len == prefix_len) {
741       /* Dequeue */
742       if (prev == NULL) {
743         *list = h->next;
744       } else {
745         prev->next = h->next;
746       }
747       free(h);
748       return 1;
749     }
750     prev = h;
751     h = h->next;
752   }
753   return 0;
754 }
755
756 struct ip_prefix_list *ip_prefix_list_find(struct ip_prefix_list *list,
757                                            const union olsr_ip_addr *net,
758                                            olsr_u8_t prefix_len)
759 {
760   struct ip_prefix_list *h;
761   for (h = list; h != NULL; h = h->next) {
762     if (prefix_len == h->net.prefix_len && ipequal(net, &h->net.prefix)) {
763       return h;
764     }
765   }
766   return NULL;
767 }