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