5d4ab30bb82c80c2d33b0c01ac8af33ad3f85427
[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  * $Id: olsrd_conf.c,v 1.50 2006/09/14 08:03:29 kattemat Exp $
40  */
41
42
43 #include <stdio.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <stdlib.h>
47 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
51
52 #include "olsrd_conf.h"
53
54
55 extern FILE *yyin;
56 extern int yyparse(void);
57
58 static char copyright_string[] = "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org) All rights reserved.";
59
60 #ifdef MAKEBIN
61
62 /* Build as standalone binary */
63 int 
64 main(int argc, char *argv[])
65 {
66   struct olsrd_config *cnf;
67
68   if(argc == 1)
69     {
70       fprintf(stderr, "Usage: olsrd_cfgparser [filename] -print\n\n");
71       exit(EXIT_FAILURE);
72     }
73
74   if((cnf = olsrd_parse_cnf(argv[1])) != NULL)
75     {
76       if((argc > 2) && (!strcmp(argv[2], "-print")))
77         {
78           olsrd_print_cnf(cnf);  
79           olsrd_write_cnf(cnf, "./out.conf");
80         }
81       else
82         printf("Use -print to view parsed values\n");
83       printf("Configfile parsed OK\n");
84     }
85   else
86     {
87       printf("Failed parsing \"%s\"\n", argv[1]);
88     }
89
90   return 0;
91 }
92
93 #else
94
95 /* Build as part of olsrd */
96
97
98 #endif
99
100 struct olsrd_config *
101 olsrd_parse_cnf(const char *filename)
102 {
103   struct olsr_if *in, *new_ifqueue, *in_tmp;
104
105   /* Stop the compiler from complaining */
106   strlen(copyright_string);
107
108   cnf = malloc(sizeof(struct olsrd_config));
109   if (cnf == NULL)
110     {
111       fprintf(stderr, "Out of memory %s\n", __func__);
112       return NULL;
113     }
114
115   set_default_cnf(cnf);
116
117   printf("Parsing file: \"%s\"\n", filename);
118
119   yyin = fopen(filename, "r");
120   
121   if (yyin == NULL)
122     {
123       fprintf(stderr, "Cannot open configuration file '%s': %s.\n",
124               filename, strerror(errno));
125       free(cnf);
126       return NULL;
127     }
128
129   current_line = 1;
130
131   if (yyparse() != 0)
132     {
133       fclose(yyin);
134       olsrd_free_cnf(cnf);
135       return NULL;
136     }
137   
138   fclose(yyin);
139
140   /* Reverse the queue (added by user request) */
141   in = cnf->interfaces;
142   new_ifqueue = NULL;
143
144   while(in)
145     {
146       in_tmp = in; 
147       in = in->next;
148
149       in_tmp->next = new_ifqueue;
150       new_ifqueue = in_tmp;
151     }
152
153   cnf->interfaces = new_ifqueue;
154
155   in = cnf->interfaces;
156
157   while(in)
158     {
159       /* set various stuff */
160       in->index = cnf->ifcnt++;
161       in->configured = OLSR_FALSE;
162       in->interf = NULL;
163       in->host_emul = OLSR_FALSE;
164       in = in->next;
165     }
166
167
168   return cnf;
169 }
170
171
172 int
173 olsrd_sanity_check_cnf(struct olsrd_config *cnf)
174 {
175   struct olsr_if           *in = cnf->interfaces;
176   struct if_config_options *io;
177
178   /* Debug level */
179   if(cnf->debug_level < MIN_DEBUGLVL ||
180      cnf->debug_level > MAX_DEBUGLVL)
181     {
182       fprintf(stderr, "Debuglevel %d is not allowed\n", cnf->debug_level);
183       return -1;
184     }
185
186   /* IP version */
187   if(cnf->ip_version != AF_INET &&
188      cnf->ip_version != AF_INET6)
189     {
190       fprintf(stderr, "Ipversion %d not allowed!\n", cnf->ip_version);
191       return -1;
192     }
193
194   /* TOS */
195   if(//cnf->tos < MIN_TOS ||
196      cnf->tos > MAX_TOS)
197     {
198       fprintf(stderr, "TOS %d is not allowed\n", cnf->tos);
199       return -1;
200     }
201
202   if(cnf->willingness_auto == OLSR_FALSE &&
203      (cnf->willingness > MAX_WILLINGNESS))
204     {
205       fprintf(stderr, "Willingness %d is not allowed\n", cnf->willingness);
206       return -1;
207     }
208
209   /* Hysteresis */
210   if(cnf->use_hysteresis == OLSR_TRUE)
211     {
212       if(cnf->hysteresis_param.scaling < MIN_HYST_PARAM ||
213          cnf->hysteresis_param.scaling > MAX_HYST_PARAM)
214         {
215           fprintf(stderr, "Hyst scaling %0.2f is not allowed\n", cnf->hysteresis_param.scaling);
216           return -1;
217         }
218
219       if(cnf->hysteresis_param.thr_high <= cnf->hysteresis_param.thr_low)
220         {
221           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);
222           return -1;
223         }
224
225       if(cnf->hysteresis_param.thr_high < MIN_HYST_PARAM ||
226          cnf->hysteresis_param.thr_high > MAX_HYST_PARAM)
227         {
228           fprintf(stderr, "Hyst upper thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_high);
229           return -1;
230         }
231
232       if(cnf->hysteresis_param.thr_low < MIN_HYST_PARAM ||
233          cnf->hysteresis_param.thr_low > MAX_HYST_PARAM)
234         {
235           fprintf(stderr, "Hyst lower thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_low);
236           return -1;
237         }
238     }
239
240   /* Pollrate */
241
242   if(cnf->pollrate < MIN_POLLRATE ||
243      cnf->pollrate > MAX_POLLRATE)
244     {
245       fprintf(stderr, "Pollrate %0.2f is not allowed\n", cnf->pollrate);
246       return -1;
247     }
248
249   /* NIC Changes Pollrate */
250
251   if(cnf->nic_chgs_pollrate < MIN_NICCHGPOLLRT ||
252      cnf->nic_chgs_pollrate > MAX_NICCHGPOLLRT)
253     {
254       fprintf(stderr, "NIC Changes Pollrate %0.2f is not allowed\n", cnf->nic_chgs_pollrate);
255       return -1;
256     }
257
258   /* TC redundancy */
259
260   if(//cnf->tc_redundancy < MIN_TC_REDUNDANCY ||
261      cnf->tc_redundancy > MAX_TC_REDUNDANCY)
262     {
263       fprintf(stderr, "TC redundancy %d is not allowed\n", cnf->tc_redundancy);
264       return -1;
265     }
266
267   /* MPR coverage */
268   if(cnf->mpr_coverage < MIN_MPR_COVERAGE ||
269      cnf->mpr_coverage > MAX_MPR_COVERAGE)
270     {
271       fprintf(stderr, "MPR coverage %d is not allowed\n", cnf->mpr_coverage);
272       return -1;
273     }
274
275   /* Link Q and hysteresis cannot be activated at the same time */
276   if(cnf->use_hysteresis == OLSR_TRUE && cnf->lq_level)
277     {
278       fprintf(stderr, "Hysteresis and LinkQuality cannot both be active! Deactivate one of them.\n");
279       return -1;
280     }
281
282   /* Link quality level */
283
284   if(cnf->lq_level > MAX_LQ_LEVEL)
285     {
286       fprintf(stderr, "LQ level %d is not allowed\n", cnf->lq_level);
287       return -1;
288     }
289
290   /* Link quality window size */
291   if(cnf->lq_level && (cnf->lq_wsize < MIN_LQ_WSIZE || cnf->lq_wsize > MAX_LQ_WSIZE))
292     {
293       fprintf(stderr, "LQ window size %d is not allowed\n", cnf->lq_wsize);
294       return -1;
295     }
296
297   if(in == NULL)
298     {
299       fprintf(stderr, "No interfaces configured!\n");
300       return -1;
301     }
302
303   /* Interfaces */
304   while(in)
305     {
306       io = in->cnf;
307
308       if(in->name == NULL || !strlen(in->name))
309         {
310           fprintf(stderr, "Interface has no name!\n");
311           return -1;
312         }
313
314       if(io == NULL)
315         {
316           fprintf(stderr, "Interface %s has no configuration!\n", in->name);
317           return -1;
318         }
319         
320       /* HELLO interval */
321
322       if (io->hello_params.validity_time < 0.0)
323       {
324         if (cnf->lq_level == 0)
325           io->hello_params.validity_time = NEIGHB_HOLD_TIME;
326
327         else
328           io->hello_params.validity_time = cnf->lq_wsize * io->hello_params.emission_interval;
329       }
330
331       if(io->hello_params.emission_interval < cnf->pollrate ||
332          io->hello_params.emission_interval > io->hello_params.validity_time)
333         {
334           fprintf(stderr, "Bad HELLO parameters! (em: %0.2f, vt: %0.2f)\n", io->hello_params.emission_interval, io->hello_params.validity_time);
335           return -1;
336         }
337
338       /* TC interval */
339       if(io->tc_params.emission_interval < cnf->pollrate ||
340          io->tc_params.emission_interval > io->tc_params.validity_time)
341         {
342           fprintf(stderr, "Bad TC parameters! (em: %0.2f, vt: %0.2f)\n", io->tc_params.emission_interval, io->tc_params.validity_time);
343           return -1;
344         }
345
346       /* MID interval */
347       if(io->mid_params.emission_interval < cnf->pollrate ||
348          io->mid_params.emission_interval > io->mid_params.validity_time)
349         {
350           fprintf(stderr, "Bad MID parameters! (em: %0.2f, vt: %0.2f)\n", io->mid_params.emission_interval, io->mid_params.validity_time);
351           return -1;
352         }
353
354       /* HNA interval */
355       if(io->hna_params.emission_interval < cnf->pollrate ||
356          io->hna_params.emission_interval > io->hna_params.validity_time)
357         {
358           fprintf(stderr, "Bad HNA parameters! (em: %0.2f, vt: %0.2f)\n", io->hna_params.emission_interval, io->hna_params.validity_time);
359           return -1;
360         }
361
362       in = in->next;
363     }
364
365   return 0;
366 }
367
368
369 void
370 olsrd_free_cnf(struct olsrd_config *cnf)
371 {
372   struct hna4_entry        *h4d, *h4 = cnf->hna4_entries;
373   struct hna6_entry        *h6d, *h6 = cnf->hna6_entries;
374   struct olsr_if           *ind, *in = cnf->interfaces;
375   struct plugin_entry      *ped, *pe = cnf->plugins;
376   struct olsr_lq_mult      *mult, *next_mult;
377   
378   while(h4)
379     {
380       h4d = h4;
381       h4 = h4->next;
382       free(h4d);
383     }
384
385   while(h6)
386     {
387       h6d = h6;
388       h6 = h6->next;
389       free(h6d);
390     }
391
392   while(in)
393     {
394       for (mult = in->cnf->lq_mult; mult != NULL; mult = next_mult)
395       {
396         next_mult = mult->next;
397         free(mult);
398       }
399
400       free(in->cnf);
401       ind = in;
402       in = in->next;
403       free(ind->name);
404       free(ind->config);
405       free(ind);
406     }
407
408   while(pe)
409     {
410       ped = pe;
411       pe = pe->next;
412       free(ped->name);
413       free(ped);
414     }
415
416   return;
417 }
418
419
420
421 struct olsrd_config *
422 olsrd_get_default_cnf()
423 {
424   cnf = malloc(sizeof(struct olsrd_config));
425   if (cnf == NULL)
426     {
427       fprintf(stderr, "Out of memory %s\n", __func__);
428       return NULL;
429     }
430
431   set_default_cnf(cnf);
432
433   return cnf;
434 }
435
436
437
438
439 void
440 set_default_cnf(struct olsrd_config *cnf)
441 {
442     memset(cnf, 0, sizeof(struct olsrd_config));
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->allow_no_interfaces = DEF_ALLOW_NO_INTS;
449     cnf->tos = DEF_TOS;
450     cnf->willingness_auto = DEF_WILL_AUTO;
451     cnf->ipc_connections = DEF_IPC_CONNECTIONS;
452     cnf->open_ipc = cnf->ipc_connections ? OLSR_TRUE : OLSR_FALSE;
453
454     cnf->use_hysteresis = DEF_USE_HYST;
455     cnf->hysteresis_param.scaling = HYST_SCALING;
456     cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
457     cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
458
459     cnf->pollrate = DEF_POLLRATE;
460     cnf->nic_chgs_pollrate = DEF_NICCHGPOLLRT;
461
462     cnf->tc_redundancy = TC_REDUNDANCY;
463     cnf->mpr_coverage = MPR_COVERAGE;
464     cnf->lq_level = DEF_LQ_LEVEL;
465     cnf->lq_fish = DEF_LQ_FISH;
466     cnf->lq_dlimit = DEF_LQ_DIJK_LIMIT;
467     cnf->lq_dinter = DEF_LQ_DIJK_INTER;
468     cnf->lq_wsize = DEF_LQ_WSIZE;
469     cnf->clear_screen = DEF_CLEAR_SCREEN;
470
471     cnf->del_gws = OLSR_FALSE;
472     cnf->will_int = 10 * HELLO_INTERVAL;
473     cnf->max_jitter = 0.0;
474     cnf->exit_value = EXIT_SUCCESS;
475     cnf->max_tc_vtime = 0.0;
476     cnf->ioctl_s = 0;
477     cnf->rts = 0;
478 }
479
480
481
482
483 struct if_config_options *
484 get_default_if_config()
485 {
486   struct if_config_options *io = malloc(sizeof(struct if_config_options));
487   struct in6_addr in6;
488
489   if(io == NULL)
490     {
491       fprintf(stderr, "Out of memory %s\n", __func__);
492       return NULL;
493     }
494
495   memset(io, 0, sizeof(struct if_config_options));
496
497   io->ipv6_addrtype = 1; /* XXX - FixMe */
498
499   inet_pton(AF_INET6, OLSR_IPV6_MCAST_SITE_LOCAL, &in6);
500   memcpy(&io->ipv6_multi_site.v6, &in6, sizeof(struct in6_addr));
501
502   inet_pton(AF_INET6, OLSR_IPV6_MCAST_GLOBAL, &in6);
503   memcpy(&io->ipv6_multi_glbl.v6, &in6, sizeof(struct in6_addr));
504
505   io->lq_mult = NULL;
506
507   io->weight.fixed = OLSR_FALSE;
508   io->weight.value = 0;
509
510   io->ipv6_addrtype = 0; /* global */
511
512   io->hello_params.emission_interval = HELLO_INTERVAL;
513   io->hello_params.validity_time = -1.0;
514   io->tc_params.emission_interval = TC_INTERVAL;
515   io->tc_params.validity_time = TOP_HOLD_TIME;
516   io->mid_params.emission_interval = MID_INTERVAL;
517   io->mid_params.validity_time = MID_HOLD_TIME;
518   io->hna_params.emission_interval = HNA_INTERVAL;
519   io->hna_params.validity_time = HNA_HOLD_TIME;
520   io->autodetect_chg = OLSR_TRUE;
521
522   return io;
523
524 }
525
526
527
528 void
529 olsrd_print_cnf(struct olsrd_config *cnf)
530 {
531   struct hna4_entry        *h4 = cnf->hna4_entries;
532   struct hna6_entry        *h6 = cnf->hna6_entries;
533   struct olsr_if           *in = cnf->interfaces;
534   struct plugin_entry      *pe = cnf->plugins;
535   struct ipc_host          *ih = cnf->ipc_hosts;
536   struct ipc_net           *ie = cnf->ipc_nets;
537   struct olsr_lq_mult      *mult;
538   char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
539   struct in_addr in4;
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   if(cnf->willingness_auto)
554     printf("Willingness      : AUTO\n");
555   else
556     printf("Willingness      : %d\n", cnf->willingness);
557
558   printf("IPC connections  : %d\n", cnf->ipc_connections);
559
560   while(ih)
561     {
562       in4.s_addr = ih->host.v4;
563       printf("\tHost %s\n", inet_ntoa(in4));
564       ih = ih->next;
565     }
566   
567   while(ie)
568     {
569       in4.s_addr = ie->net.v4;
570       printf("\tNet %s/", inet_ntoa(in4));
571       in4.s_addr = ie->mask.v4;
572       printf("%s\n", inet_ntoa(in4));
573       ie = ie->next;
574     }
575
576
577   printf("Pollrate         : %0.2f\n", cnf->pollrate);
578
579   printf("NIC ChangPollrate: %0.2f\n", cnf->nic_chgs_pollrate);
580
581   printf("TC redundancy    : %d\n", cnf->tc_redundancy);
582
583   printf("MPR coverage     : %d\n", cnf->mpr_coverage);
584    
585   printf("LQ level         : %d\n", cnf->lq_level);
586
587   printf("LQ fish eye      : %d\n", cnf->lq_fish);
588
589   printf("LQ Dijkstra limit: %d, %0.2f\n", cnf->lq_dlimit, cnf->lq_dinter);
590
591   printf("LQ window size   : %d\n", cnf->lq_wsize);
592
593   printf("Clear screen     : %s\n", cnf->clear_screen ? "yes" : "no");
594
595   /* Interfaces */
596   if(in)
597     {
598       printf("Interfaces:\n");
599       while(in)
600         {
601           printf(" dev: \"%s\"\n", in->name);
602           
603           if(in->cnf->ipv4_broadcast.v4)
604             {
605               in4.s_addr = in->cnf->ipv4_broadcast.v4;
606               printf("\tIPv4 broadcast           : %s\n", inet_ntoa(in4));
607             }
608           else
609             {
610               printf("\tIPv4 broadcast           : AUTO\n");
611             }
612           
613           printf("\tIPv6 addrtype            : %s\n", in->cnf->ipv6_addrtype ? "site-local" : "global");
614           
615           //union olsr_ip_addr       ipv6_multi_site;
616           //union olsr_ip_addr       ipv6_multi_glbl;
617           printf("\tIPv6 multicast site/glbl : %s", (char *)inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
618           printf("/%s\n", (char *)inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
619           
620           printf("\tHELLO emission/validity  : %0.2f/%0.2f\n", in->cnf->hello_params.emission_interval, in->cnf->hello_params.validity_time);
621           printf("\tTC emission/validity     : %0.2f/%0.2f\n", in->cnf->tc_params.emission_interval, in->cnf->tc_params.validity_time);
622           printf("\tMID emission/validity    : %0.2f/%0.2f\n", in->cnf->mid_params.emission_interval, in->cnf->mid_params.validity_time);
623           printf("\tHNA emission/validity    : %0.2f/%0.2f\n", in->cnf->hna_params.emission_interval, in->cnf->hna_params.validity_time);
624           
625           for (mult = in->cnf->lq_mult; mult != NULL; mult = mult->next)
626           {
627             inet_ntop(cnf->ip_version, &mult->addr, ipv6_buf,
628                       sizeof (ipv6_buf));
629
630             printf("\tLinkQualityMult          : %s %0.2f\n",
631                    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     {
658       printf("Using hysteresis:\n");
659       printf("\tScaling      : %0.2f\n", cnf->hysteresis_param.scaling);
660       printf("\tThr high/low : %0.2f/%0.2f\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low);
661     }
662   else
663     printf("Not using hysteresis\n");
664
665   /* HNA IPv4 */
666   if(h4)
667     {
668
669       printf("HNA4 entries:\n");
670       while(h4)
671         {
672           in4.s_addr = h4->net.v4;
673           printf("\t%s/", inet_ntoa(in4));
674           in4.s_addr = h4->netmask.v4;
675           printf("%s\n", inet_ntoa(in4));
676
677           h4 = h4->next;
678         }
679     }
680
681   /* HNA IPv6 */
682   if(h6)
683     {
684       printf("HNA6 entries:\n");
685       while(h6)
686         {
687           printf("\t%s/%d\n", (char *)inet_ntop(AF_INET6, &h6->net.v6, ipv6_buf, sizeof(ipv6_buf)), h6->prefix_len);
688           h6 = h6->next;
689         }
690     }
691 }
692
693 void *olsrd_cnf_malloc(unsigned int len)
694 {
695   return malloc(len);
696 }
697
698 void olsrd_cnf_free(void *addr)
699 {
700   free(addr);
701 }
702
703 #if defined WIN32_STDIO_HACK
704 struct ioinfo
705 {
706         unsigned int handle;
707         unsigned char attr;
708         char buff;
709         int flag;
710         CRITICAL_SECTION lock;
711 };
712
713 void win32_stdio_hack(unsigned int handle)
714 {
715   HMODULE lib;
716   struct ioinfo **info;
717
718   lib = LoadLibrary("msvcrt.dll");
719
720   info = (struct ioinfo **)GetProcAddress(lib, "__pioinfo");
721
722   // (*info)[1].handle = handle;
723   // (*info)[1].attr = 0x89; // FOPEN | FTEXT | FPIPE;
724
725   (*info)[2].handle = handle;
726   (*info)[2].attr = 0x89;
727
728   // stdout->_file = 1;
729   stderr->_file = 2;
730
731   // setbuf(stdout, NULL);
732   setbuf(stderr, NULL);
733 }
734 #else
735 void win32_stdio_hack(unsigned int handle) {}
736 #endif