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