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