4e205da405d3fdf4301e135e32e568e4ca38767e
[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->rttable_default = 0;
448     cnf->willingness_auto = DEF_WILL_AUTO;
449     cnf->ipc_connections = DEF_IPC_CONNECTIONS;
450     cnf->fib_metric = DEF_FIB_METRIC;
451
452     cnf->use_hysteresis = DEF_USE_HYST;
453     cnf->hysteresis_param.scaling = HYST_SCALING;
454     cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
455     cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
456
457     cnf->pollrate = DEF_POLLRATE;
458     cnf->nic_chgs_pollrate = DEF_NICCHGPOLLRT;
459
460     cnf->tc_redundancy = TC_REDUNDANCY;
461     cnf->mpr_coverage = MPR_COVERAGE;
462     cnf->lq_level = DEF_LQ_LEVEL;
463     cnf->lq_fish = DEF_LQ_FISH;
464     cnf->lq_dlimit = DEF_LQ_DIJK_LIMIT;
465     cnf->lq_dinter = DEF_LQ_DIJK_INTER;
466     cnf->lq_wsize = DEF_LQ_WSIZE;
467     cnf->lq_nat_thresh = DEF_LQ_NAT_THRESH;
468     cnf->clear_screen = DEF_CLEAR_SCREEN;
469
470     cnf->del_gws = OLSR_FALSE;
471     cnf->will_int = 10 * HELLO_INTERVAL;
472     cnf->max_jitter = 0.0;
473     cnf->exit_value = EXIT_SUCCESS;
474     cnf->max_tc_vtime = 0.0;
475     cnf->ioctl_s = 0;
476 #if LINUX_POLICY_ROUTING
477     cnf->rtnl_s = 0;
478 #endif
479
480 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
481     cnf->rts = 0;
482 #endif
483 }
484
485
486
487
488 struct if_config_options *
489 get_default_if_config(void)
490 {
491   struct in6_addr in6;
492   struct if_config_options *io = malloc(sizeof(*io));
493
494   if(io == NULL) {
495     fprintf(stderr, "Out of memory %s\n", __func__);
496     return NULL;
497   }
498
499   memset(io, 0, sizeof(*io));
500
501   io->ipv6_addrtype = 1; /* XXX - FixMe */
502
503   inet_pton(AF_INET6, OLSR_IPV6_MCAST_SITE_LOCAL, &in6);
504   io->ipv6_multi_site.v6 = in6;
505
506   inet_pton(AF_INET6, OLSR_IPV6_MCAST_GLOBAL, &in6);
507   io->ipv6_multi_glbl.v6 = in6;
508
509   io->lq_mult = NULL;
510
511   io->weight.fixed = OLSR_FALSE;
512   io->weight.value = 0;
513
514   io->ipv6_addrtype = 0; /* global */
515
516   io->hello_params.emission_interval = HELLO_INTERVAL;
517   io->hello_params.validity_time = NEIGHB_HOLD_TIME;
518   io->tc_params.emission_interval = TC_INTERVAL;
519   io->tc_params.validity_time = TOP_HOLD_TIME;
520   io->mid_params.emission_interval = MID_INTERVAL;
521   io->mid_params.validity_time = MID_HOLD_TIME;
522   io->hna_params.emission_interval = HNA_INTERVAL;
523   io->hna_params.validity_time = HNA_HOLD_TIME;
524   io->autodetect_chg = OLSR_TRUE;
525
526   return io;
527
528 }
529
530
531
532 void
533 olsrd_print_cnf(struct olsrd_config *cnf)
534 {
535   struct ip_prefix_list   *h  = cnf->hna_entries;
536   struct olsr_if           *in = cnf->interfaces;
537   struct plugin_entry      *pe = cnf->plugins;
538   struct ip_prefix_list    *ie = cnf->ipc_nets;
539   struct olsr_lq_mult      *mult;
540   char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
541
542   printf(" *** olsrd configuration ***\n");
543
544   printf("Debug Level      : %d\n", cnf->debug_level);
545   if(cnf->ip_version == AF_INET6)
546     printf("IpVersion        : 6\n");
547   else
548     printf("IpVersion        : 4\n");
549   if(cnf->allow_no_interfaces)
550     printf("No interfaces    : ALLOWED\n");
551   else
552     printf("No interfaces    : NOT ALLOWED\n");
553   printf("TOS              : 0x%02x\n", cnf->tos);
554   printf("RtTable          : 0x%02x\n", cnf->rttable);
555   printf("RtTableDefault   : 0x%02x\n", cnf->rttable_default);
556   if(cnf->willingness_auto)
557     printf("Willingness      : AUTO\n");
558   else
559     printf("Willingness      : %d\n", cnf->willingness);
560
561   printf("IPC connections  : %d\n", cnf->ipc_connections);
562   while(ie)
563     {
564       struct ipaddr_str strbuf;
565       if (ie->net.prefix_len == olsr_cnf->maxplen) {
566           printf("\tHost %s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
567       } else {
568           printf("\tNet %s/%d\n", olsr_ip_to_string(&strbuf, &ie->net.prefix), ie->net.prefix_len);
569       }
570       ie = ie->next;
571     }
572
573
574   printf("Pollrate         : %0.2f\n", cnf->pollrate);
575
576   printf("NIC ChangPollrate: %0.2f\n", cnf->nic_chgs_pollrate);
577
578   printf("TC redundancy    : %d\n", cnf->tc_redundancy);
579
580   printf("MPR coverage     : %d\n", cnf->mpr_coverage);
581    
582   printf("LQ level         : %d\n", cnf->lq_level);
583
584   printf("LQ fish eye      : %d\n", cnf->lq_fish);
585
586   printf("LQ Dijkstra limit: %d, %0.2f\n", cnf->lq_dlimit, cnf->lq_dinter);
587
588   printf("LQ window size   : %d\n", cnf->lq_wsize);
589
590   printf("NAT threshold    : %f\n", cnf->lq_nat_thresh);
591
592   printf("Clear screen     : %s\n", cnf->clear_screen ? "yes" : "no");
593
594   /* Interfaces */
595   if(in)
596     {
597       printf("Interfaces:\n");
598       while(in)
599         {
600           printf(" dev: \"%s\"\n", in->name);
601           
602           if(in->cnf->ipv4_broadcast.v4.s_addr)
603             {
604               printf("\tIPv4 broadcast           : %s\n", inet_ntoa(in->cnf->ipv4_broadcast.v4));
605             }
606           else
607             {
608               printf("\tIPv4 broadcast           : AUTO\n");
609             }
610           
611           printf("\tIPv6 addrtype            : %s\n", in->cnf->ipv6_addrtype ? "site-local" : "global");
612           
613           //union olsr_ip_addr       ipv6_multi_site;
614           //union olsr_ip_addr       ipv6_multi_glbl;
615           printf("\tIPv6 multicast site/glbl : %s", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
616           printf("/%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
617           
618           printf("\tHELLO emission/validity  : %0.2f/%0.2f\n", in->cnf->hello_params.emission_interval, in->cnf->hello_params.validity_time);
619           printf("\tTC emission/validity     : %0.2f/%0.2f\n", in->cnf->tc_params.emission_interval, in->cnf->tc_params.validity_time);
620           printf("\tMID emission/validity    : %0.2f/%0.2f\n", in->cnf->mid_params.emission_interval, in->cnf->mid_params.validity_time);
621           printf("\tHNA emission/validity    : %0.2f/%0.2f\n", in->cnf->hna_params.emission_interval, in->cnf->hna_params.validity_time);
622           
623           for (mult = in->cnf->lq_mult; mult != NULL; mult = mult->next)
624           {
625             printf("\tLinkQualityMult          : %s %0.2f\n", inet_ntop(cnf->ip_version, &mult->addr, ipv6_buf, sizeof (ipv6_buf)), mult->val);
626           }
627
628           printf("\tAutodetetc changes       : %s\n", in->cnf->autodetect_chg ? "yes" : "no");
629
630           in = in->next;
631         }
632     }
633
634
635
636
637   /* Plugins */
638   if(pe)
639     {
640       printf("Plugins:\n");
641
642       while(pe)
643         {
644           printf("\tName: \"%s\"\n", pe->name);
645           pe = pe->next;
646         }
647     }
648
649   /* Hysteresis */
650   if(cnf->use_hysteresis) {
651     printf("Using hysteresis:\n");
652     printf("\tScaling      : %0.2f\n", cnf->hysteresis_param.scaling);
653     printf("\tThr high/low : %0.2f/%0.2f\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low);
654   } else {
655     printf("Not using hysteresis\n");
656   }
657
658   /* HNA IPv4 and IPv6 */
659   if(h) {
660     printf("HNA%d entries:\n", cnf->ip_version == AF_INET ? 4 : 6);
661     while(h) {
662       struct ipaddr_str buf;
663       printf("\t%s/", olsr_ip_to_string(&buf, &h->net.prefix));
664       if (cnf->ip_version == AF_INET) {
665         union olsr_ip_addr ip;
666         olsr_prefix_to_netmask(&ip, h->net.prefix_len);
667         printf("%s\n", olsr_ip_to_string(&buf, &ip));
668       } else {
669         printf("%d\n", h->net.prefix_len);
670       }
671       h = h->next;
672     }
673   }
674 }
675
676 #if defined WIN32
677 struct ioinfo
678 {
679         unsigned int handle;
680         unsigned char attr;
681         char buff;
682         int flag;
683         CRITICAL_SECTION lock;
684 };
685
686 void win32_stdio_hack(unsigned int handle)
687 {
688   HMODULE lib;
689   struct ioinfo **info;
690
691   lib = LoadLibrary("msvcrt.dll");
692
693   info = (struct ioinfo **)GetProcAddress(lib, "__pioinfo");
694
695   // (*info)[1].handle = handle;
696   // (*info)[1].attr = 0x89; // FOPEN | FTEXT | FPIPE;
697
698   (*info)[2].handle = handle;
699   (*info)[2].attr = 0x89;
700
701   // stdout->_file = 1;
702   stderr->_file = 2;
703
704   // setbuf(stdout, NULL);
705   setbuf(stderr, NULL);
706 }
707
708 void*
709 win32_olsrd_malloc(size_t size)
710 {
711         return malloc(size);
712 }
713
714 void
715 win32_olsrd_free(void* ptr)
716 {
717         free(ptr);
718 }
719 #endif
720
721 void ip_prefix_list_add(struct ip_prefix_list **list,
722                         const union olsr_ip_addr *net,
723                         olsr_u8_t prefix_len)
724 {
725   struct ip_prefix_list *new_entry = malloc(sizeof(*new_entry));
726   
727   new_entry->net.prefix = *net;
728   new_entry->net.prefix_len = prefix_len;
729
730   /* Queue */
731   new_entry->next = *list;
732   *list = new_entry;
733 }
734
735 int ip_prefix_list_remove(struct ip_prefix_list **list,
736                           const union olsr_ip_addr *net,
737                           olsr_u8_t prefix_len)
738 {
739   struct ip_prefix_list *h = *list, *prev = NULL;
740
741   while (h != NULL) {
742     if (ipequal(net, &h->net.prefix) && h->net.prefix_len == prefix_len) {
743       /* Dequeue */
744       if (prev == NULL) {
745         *list = h->next;
746       } else {
747         prev->next = h->next;
748       }
749       free(h);
750       return 1;
751     }
752     prev = h;
753     h = h->next;
754   }
755   return 0;
756 }
757
758 struct ip_prefix_list *ip_prefix_list_find(struct ip_prefix_list *list,
759                                            const union olsr_ip_addr *net,
760                                            olsr_u8_t prefix_len)
761 {
762   struct ip_prefix_list *h;
763   for (h = list; h != NULL; h = h->next) {
764     if (prefix_len == h->net.prefix_len && ipequal(net, &h->net.prefix)) {
765       return h;
766     }
767   }
768   return NULL;
769 }