f8558dd9213e27f61341e26fdedaadea220cd735
[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 printf("dev %s before applying defaultSection:\n",in->name);
330     olsrd_print_interface_cnf(in->cnf, in->cnfi, false);
331
332     /*apply defaults (if this is not the default interface stub)*/
333     if (in->cnf != cnf->interface_defaults)
334     {
335       size_t pos;
336       struct olsr_lq_mult *mult_temp, *mult_orig_walk;
337       uint8_t *cnfptr = (uint8_t*)in->cnf;
338       uint8_t *cnfiptr = (uint8_t*)in->cnfi;
339       uint8_t *defptr = (uint8_t*)cnf->interface_defaults;
340
341       /*save interface specific lqmults, as they are merged togehter later*/
342       mult_orig = io->lq_mult;
343
344       assert(in->cnf);
345       assert(in->cnfi);
346       for (pos = 0; pos < sizeof(*in->cnf); pos++) {
347         if (cnfptr[pos] != cnfiptr[pos]) {
348           cnfptr[pos] = defptr[pos]; cnfiptr[pos]=0x00;
349         }
350         else cnfiptr[pos]=0xFF;
351       }
352
353       io->lq_mult=NULL;
354       /*copy default lqmults into this interface*/
355       for (mult = cnf->interface_defaults->lq_mult; mult; mult=mult->next) {
356         /*search same lqmult in orig_list*/
357         for (mult_orig_walk = mult_orig; mult_orig_walk; mult_orig_walk=mult_orig_walk->next) {
358           if (ipequal(&mult_orig_walk->addr,&mult->addr)) {
359             break;
360           }
361         }
362         if (mult_orig_walk == NULL) {
363           mult_temp=malloc(sizeof(struct olsr_lq_mult));
364           memcpy(mult_temp,mult,sizeof(struct olsr_lq_mult));
365           mult_temp->next=io->lq_mult;
366           io->lq_mult=mult_temp;
367         }
368       }
369     }
370     else
371     { /* check if there are no lqmults
372        *  as copying the pointer to the interfaces, 
373        *  would lead 1. to unexpected results if this interface defines its own lqmults 
374        *  2. to problems when freeing lqmult structures them) 
375       if (io->lq_mult!=NULL) {
376         fprintf(stderr, "LinkQualityMult directives are not supported within InterfaceDefaults section!\n", in->name);
377         return -1;
378       }*/
379       mult_orig = NULL;
380     }
381
382     if (in->name == NULL || !strlen(in->name)) {
383       fprintf(stderr, "Interface has no name!\n");
384       return -1;
385     }
386
387     if (io == NULL) {
388       fprintf(stderr, "Interface %s has no configuration!\n", in->name);
389       return -1;
390     }
391
392     /* HELLO interval */
393
394     if (io->hello_params.validity_time < 0.0) {
395       if (cnf->lq_level == 0)
396         io->hello_params.validity_time = NEIGHB_HOLD_TIME;
397
398       else
399         io->hello_params.validity_time = (int)(REFRESH_INTERVAL / cnf->lq_aging);
400     }
401
402     if (io->hello_params.emission_interval < cnf->pollrate || io->hello_params.emission_interval > io->hello_params.validity_time) {
403       fprintf(stderr, "Bad HELLO parameters! (em: %0.2f, vt: %0.2f) for dev %s\n", io->hello_params.emission_interval,
404               io->hello_params.validity_time, in->name);
405       return -1;
406     }
407
408     /* TC interval */
409     if (io->tc_params.emission_interval < cnf->pollrate || io->tc_params.emission_interval > io->tc_params.validity_time) {
410       fprintf(stderr, "Bad TC parameters! (em: %0.2f, vt: %0.2f) for dev %s\n", io->tc_params.emission_interval,
411           io->tc_params.validity_time, in->name);
412       return -1;
413     }
414
415     if (cnf->min_tc_vtime > 0.0 && (io->tc_params.validity_time / io->tc_params.emission_interval) < 128) {
416       fprintf(stderr, "Please use a tc vtime at least 128 times the emission interval while using the min_tc_vtime hack.\n");
417       return -1;
418     }
419     /* MID interval */
420     if (io->mid_params.emission_interval < cnf->pollrate || io->mid_params.emission_interval > io->mid_params.validity_time) {
421       fprintf(stderr, "Bad MID parameters! (em: %0.2f, vt: %0.2f) for dev %s\n", io->mid_params.emission_interval,
422               io->mid_params.validity_time, in->name);
423       return -1;
424     }
425
426     /* HNA interval */
427     if (io->hna_params.emission_interval < cnf->pollrate || io->hna_params.emission_interval > io->hna_params.validity_time) {
428       fprintf(stderr, "Bad HNA parameters! (em: %0.2f, vt: %0.2f) for dev %s\n", io->hna_params.emission_interval,
429               io->hna_params.validity_time, in->name);
430       return -1;
431     }
432
433     /*merge lqmults*/
434     if (mult_orig!=NULL) {
435       io->orig_lq_mult_cnt=1;
436       /*search last of interface specific lqmults*/
437       mult = mult_orig;
438       while (mult->next!=NULL) {
439         mult=mult->next;
440       }
441       /*append default lqmults ath the end of the interface specific (to ensure they can overwrite them)*/
442       mult->next=io->lq_mult;
443       io->lq_mult=mult_orig;
444     }
445
446     for (mult = io->lq_mult; mult; mult=mult->next) {
447       if (mult->value > LINK_LOSS_MULTIPLIER) {
448         struct ipaddr_str buf;
449
450         fprintf(stderr, "Bad Linkquality multiplier ('%s' on IP %s: %0.2f)\n",
451             in->name, olsr_ip_to_string(&buf, &mult->addr), (float)mult->value / (float)LINK_LOSS_MULTIPLIER);
452         return -1;
453       }
454     }
455     in = in->next;
456   }
457
458   return 0;
459 }
460
461 void
462 olsrd_free_cnf(struct olsrd_config *cnf)
463 {
464   struct ip_prefix_list *hd, *h = cnf->hna_entries;
465   struct olsr_if *ind, *in = cnf->interfaces;
466   struct plugin_entry *ped, *pe = cnf->plugins;
467   struct olsr_lq_mult *mult, *next_mult;
468
469   while (h) {
470     hd = h;
471     h = h->next;
472     free(hd);
473   }
474
475   while (in) {
476     for (mult = in->cnf->lq_mult; mult != NULL; mult = next_mult) {
477       next_mult = mult->next;
478       free(mult);
479     }
480
481     free(in->cnf);
482     free(in->cnfi);
483
484     ind = in;
485     in = in->next;
486
487     free(ind);
488   }
489
490   while (pe) {
491     ped = pe;
492     pe = pe->next;
493     free(ped->name);
494     free(ped);
495   }
496
497   return;
498 }
499
500 struct olsrd_config *
501 olsrd_get_default_cnf(void)
502 {
503   struct olsrd_config *c = malloc(sizeof(struct olsrd_config));
504   if (c == NULL) {
505     fprintf(stderr, "Out of memory %s\n", __func__);
506     return NULL;
507   }
508
509   set_default_cnf(c);
510   return c;
511 }
512
513 void
514 set_default_cnf(struct olsrd_config *cnf)
515 {
516   memset(cnf, 0, sizeof(*cnf));
517
518   cnf->debug_level = DEF_DEBUGLVL;
519   cnf->no_fork = false;
520   cnf->host_emul = false;
521   cnf->ip_version = AF_INET;
522   cnf->ipsize = sizeof(struct in_addr);
523   cnf->maxplen = 32;
524   cnf->allow_no_interfaces = DEF_ALLOW_NO_INTS;
525   cnf->tos = DEF_TOS;
526   cnf->olsrport = DEF_OLSRPORT;
527   cnf->rttable = DEF_RTTABLE;
528   cnf->rtproto = DEF_RTPROTO;
529   cnf->rttable_default = 0;
530   cnf->willingness_auto = DEF_WILL_AUTO;
531   cnf->willingness = DEF_WILLINGNESS;
532   cnf->ipc_connections = DEF_IPC_CONNECTIONS;
533   cnf->fib_metric = DEF_FIB_METRIC;
534
535   cnf->use_hysteresis = DEF_USE_HYST;
536   cnf->hysteresis_param.scaling = HYST_SCALING;
537   cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
538   cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
539
540   cnf->pollrate = DEF_POLLRATE;
541   cnf->nic_chgs_pollrate = DEF_NICCHGPOLLRT;
542
543   cnf->tc_redundancy = TC_REDUNDANCY;
544   cnf->mpr_coverage = MPR_COVERAGE;
545   cnf->lq_level = DEF_LQ_LEVEL;
546   cnf->lq_fish = DEF_LQ_FISH;
547   cnf->lq_dlimit = DEF_LQ_DIJK_LIMIT;
548   cnf->lq_dinter = DEF_LQ_DIJK_INTER;
549   cnf->lq_aging = DEF_LQ_AGING;
550   cnf->lq_algorithm = NULL;
551   cnf->lq_nat_thresh = DEF_LQ_NAT_THRESH;
552   cnf->clear_screen = DEF_CLEAR_SCREEN;
553
554   cnf->del_gws = false;
555   cnf->will_int = 10 * HELLO_INTERVAL;
556   cnf->max_jitter = 0.0;
557   cnf->exit_value = EXIT_SUCCESS;
558   cnf->max_tc_vtime = 0.0;
559   cnf->ioctl_s = 0;
560 #if LINUX_POLICY_ROUTING
561   cnf->rtnl_s = 0;
562 #endif
563
564 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
565   cnf->rts = 0;
566 #endif
567 }
568
569 struct if_config_options *
570 get_default_if_config(void)
571 {
572   struct in6_addr in6;
573   struct if_config_options *io = malloc(sizeof(*io));
574
575   if (io == NULL) {
576     fprintf(stderr, "Out of memory %s\n", __func__);
577     return NULL;
578   }
579
580   memset(io, 0, sizeof(*io));
581
582   inet_pton(AF_INET6, OLSR_IPV6_MCAST, &in6);
583   io->ipv6_multicast.v6 = in6;
584
585   io->lq_mult = NULL;
586
587   io->weight.fixed = false;
588   io->weight.value = 0;
589
590   io->hello_params.emission_interval = HELLO_INTERVAL;
591   io->hello_params.validity_time = NEIGHB_HOLD_TIME;
592   io->tc_params.emission_interval = TC_INTERVAL;
593   io->tc_params.validity_time = TOP_HOLD_TIME;
594   io->mid_params.emission_interval = MID_INTERVAL;
595   io->mid_params.validity_time = MID_HOLD_TIME;
596   io->hna_params.emission_interval = HNA_INTERVAL;
597   io->hna_params.validity_time = HNA_HOLD_TIME;
598   io->autodetect_chg = true;
599
600   return io;
601
602 }
603
604 void
605 olsrd_print_cnf(struct olsrd_config *cnf)
606 {
607   struct ip_prefix_list *h = cnf->hna_entries;
608   struct olsr_if *in = cnf->interfaces;
609   struct plugin_entry *pe = cnf->plugins;
610   struct ip_prefix_list *ie = cnf->ipc_nets;
611
612   printf(" *** olsrd configuration ***\n");
613
614   printf("Debug Level      : %d\n", cnf->debug_level);
615   if (cnf->ip_version == AF_INET6)
616     printf("IpVersion        : 6\n");
617   else
618     printf("IpVersion        : 4\n");
619   if (cnf->allow_no_interfaces)
620     printf("No interfaces    : ALLOWED\n");
621   else
622     printf("No interfaces    : NOT ALLOWED\n");
623   printf("TOS              : 0x%02x\n", cnf->tos);
624   printf("OlsrPort          : 0x%03x\n", cnf->olsrport);
625   printf("RtTable          : 0x%02x\n", cnf->rttable);
626   printf("RtTableDefault   : 0x%02x\n", cnf->rttable_default);
627   if (cnf->willingness_auto)
628     printf("Willingness      : AUTO\n");
629   else
630     printf("Willingness      : %d\n", cnf->willingness);
631
632   printf("IPC connections  : %d\n", cnf->ipc_connections);
633   while (ie) {
634     struct ipaddr_str strbuf;
635     if (ie->net.prefix_len == olsr_cnf->maxplen) {
636       printf("\tHost %s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
637     } else {
638       printf("\tNet %s/%d\n", olsr_ip_to_string(&strbuf, &ie->net.prefix), ie->net.prefix_len);
639     }
640     ie = ie->next;
641   }
642
643   printf("Pollrate         : %0.2f\n", cnf->pollrate);
644
645   printf("NIC ChangPollrate: %0.2f\n", cnf->nic_chgs_pollrate);
646
647   printf("TC redundancy    : %d\n", cnf->tc_redundancy);
648
649   printf("MPR coverage     : %d\n", cnf->mpr_coverage);
650
651   printf("LQ level         : %d\n", cnf->lq_level);
652
653   printf("LQ fish eye      : %d\n", cnf->lq_fish);
654
655   printf("LQ Dijkstra limit: %d, %0.2f\n", cnf->lq_dlimit, cnf->lq_dinter);
656
657   printf("LQ aging factor  : %f\n", cnf->lq_aging);
658
659   printf("LQ algorithm name: %s\n", cnf->lq_algorithm ? cnf->lq_algorithm : "default");
660
661   printf("NAT threshold    : %f\n", cnf->lq_nat_thresh);
662
663   printf("Clear screen     : %s\n", cnf->clear_screen ? "yes" : "no");
664
665   /* Interfaces */
666   if (in) {
667     /*print interface default config*/
668     printf(" InterfaceDefaults: \n");
669     olsrd_print_interface_cnf(cnf->interface_defaults, cnf->interface_defaults, true);
670
671     while (in)
672     { 
673       if (cnf->interface_defaults!=in->cnf)
674       {
675         printf(" dev: \"%s\"\n", in->name);
676
677         olsrd_print_interface_cnf(in->cnf, in->cnfi, false);
678       }
679       in = in->next;
680     }
681   }
682
683   /* Plugins */
684   if (pe) {
685     printf("Plugins:\n");
686
687     while (pe) {
688       printf("\tName: \"%s\"\n", pe->name);
689       pe = pe->next;
690     }
691   }
692
693   /* Hysteresis */
694   if (cnf->use_hysteresis) {
695     printf("Using hysteresis:\n");
696     printf("\tScaling      : %0.2f\n", cnf->hysteresis_param.scaling);
697     printf("\tThr high/low : %0.2f/%0.2f\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low);
698   } else {
699     printf("Not using hysteresis\n");
700   }
701
702   /* HNA IPv4 and IPv6 */
703   if (h) {
704     printf("HNA%d entries:\n", cnf->ip_version == AF_INET ? 4 : 6);
705     while (h) {
706       struct ipaddr_str buf;
707       printf("\t%s/", olsr_ip_to_string(&buf, &h->net.prefix));
708       if (cnf->ip_version == AF_INET) {
709         union olsr_ip_addr ip;
710         olsr_prefix_to_netmask(&ip, h->net.prefix_len);
711         printf("%s\n", olsr_ip_to_string(&buf, &ip));
712       } else {
713         printf("%d\n", h->net.prefix_len);
714       }
715       h = h->next;
716     }
717   }
718 }
719
720 #if defined WIN32
721 struct ioinfo {
722   unsigned int handle;
723   unsigned char attr;
724   char buff;
725   int flag;
726   CRITICAL_SECTION lock;
727 };
728
729 void
730 win32_stdio_hack(unsigned int handle)
731 {
732   HMODULE lib;
733   struct ioinfo **info;
734
735   lib = LoadLibrary("msvcrt.dll");
736
737   info = (struct ioinfo **)GetProcAddress(lib, "__pioinfo");
738
739   // (*info)[1].handle = handle;
740   // (*info)[1].attr = 0x89; // FOPEN | FTEXT | FPIPE;
741
742   (*info)[2].handle = handle;
743   (*info)[2].attr = 0x89;
744
745   // stdout->_file = 1;
746   stderr->_file = 2;
747
748   // setbuf(stdout, NULL);
749   setbuf(stderr, NULL);
750 }
751
752 void *
753 win32_olsrd_malloc(size_t size)
754 {
755   return malloc(size);
756 }
757
758 void
759 win32_olsrd_free(void *ptr)
760 {
761   free(ptr);
762 }
763 #endif
764
765 void
766 ip_prefix_list_add(struct ip_prefix_list **list, const union olsr_ip_addr *net, uint8_t prefix_len)
767 {
768   struct ip_prefix_list *new_entry = malloc(sizeof(*new_entry));
769
770   new_entry->net.prefix = *net;
771   new_entry->net.prefix_len = prefix_len;
772
773   /* Queue */
774   new_entry->next = *list;
775   *list = new_entry;
776 }
777
778 int
779 ip_prefix_list_remove(struct ip_prefix_list **list, const union olsr_ip_addr *net, uint8_t prefix_len)
780 {
781   struct ip_prefix_list *h = *list, *prev = NULL;
782
783   while (h != NULL) {
784     if (ipequal(net, &h->net.prefix) && h->net.prefix_len == prefix_len) {
785       /* Dequeue */
786       if (prev == NULL) {
787         *list = h->next;
788       } else {
789         prev->next = h->next;
790       }
791       free(h);
792       return 1;
793     }
794     prev = h;
795     h = h->next;
796   }
797   return 0;
798 }
799
800 struct ip_prefix_list *
801 ip_prefix_list_find(struct ip_prefix_list *list, const union olsr_ip_addr *net, uint8_t prefix_len)
802 {
803   struct ip_prefix_list *h;
804   for (h = list; h != NULL; h = h->next) {
805     if (prefix_len == h->net.prefix_len && ipequal(net, &h->net.prefix)) {
806       return h;
807     }
808   }
809   return NULL;
810 }
811
812 /*
813  * Local Variables:
814  * c-basic-offset: 2
815  * indent-tabs-mode: nil
816  * End:
817  */