fixed conflicting definition
[olsrd.git] / src / cfgparser / olsrd_conf.c
1 /*
2  * OLSR ad-hoc routing table management protocol config parser
3  * Copyright (C) 2004 Andreas T√łnnesen (andreto@olsr.org)
4  *
5  * This file is part of the olsr.org OLSR daemon.
6  *
7  * olsr.org is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * olsr.org is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  * 
21  * 
22  * $Id: olsrd_conf.c,v 1.8 2004/10/19 20:20:26 kattemat Exp $
23  *
24  */
25
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34
35 #include "olsrd_conf.h"
36
37
38 extern FILE *yyin;
39 extern int yyparse(void);
40
41
42 #ifdef MAKELIB
43
44 /* Build as DLL */
45
46 void __attribute__ ((constructor)) 
47 my_init(void);
48
49 void __attribute__ ((destructor)) 
50 my_fini(void);
51
52
53 /**
54  *Constructor
55  */
56 void
57 my_init()
58 {
59   /* Print plugin info to stdout */
60   printf("olsrd config file parser %s loaded\n", SOFTWARE_VERSION);
61
62   return;
63 }
64
65 /**
66  *Destructor
67  */
68 void
69 my_fini()
70 {
71   printf("See you around!\n");
72   return;
73 }
74
75 #else
76
77 #ifdef MAKEBIN
78
79 /* Build as standalone binary */
80 int 
81 main(int argc, char *argv[])
82 {
83   struct olsrd_config *cnf;
84
85   if(argc == 1)
86     {
87       fprintf(stderr, "Usage: olsrd_cfgparser [filename] -print\n\n");
88       exit(EXIT_FAILURE);
89     }
90
91   if((cnf = olsrd_parse_cnf(argv[1])) != NULL)
92     {
93       if((argc > 2) && (!strcmp(argv[2], "-print")))
94         {
95           olsrd_print_cnf(cnf);  
96           olsrd_write_cnf(cnf, "./out.conf");
97         }
98       else
99         printf("Use -print to view parsed values\n");
100       printf("Configfile parsed OK\n");
101     }
102   else
103     {
104       printf("Failed parsing \"%s\"\n", argv[1]);
105     }
106
107   return 0;
108 }
109
110 #else
111
112 /* Build as part of olsrd */
113
114
115 #endif
116
117 #endif
118
119 struct olsrd_config *
120 olsrd_parse_cnf(char *filename)
121 {
122   struct olsr_if *in;
123   struct if_config_options *io;
124
125   cnf = malloc(sizeof(struct olsrd_config));
126   if (cnf == NULL)
127     {
128       fprintf(stderr, "Out of memory %s\n", __func__);
129       return NULL;
130   }
131
132   set_default_cnf(cnf);
133
134   printf("Parsing file: \"%s\"\n", filename);
135
136   yyin = fopen(filename, "r");
137   
138   if (yyin == NULL)
139     {
140       fprintf(stderr, "Cannot open configuration file '%s': %s.\n",
141               filename, strerror(errno));
142       free(cnf);
143       return NULL;
144   }
145
146   current_line = 1;
147
148   if (yyparse() != 0)
149     {
150       fclose(yyin);
151       olsrd_free_cnf(cnf);
152       exit(0);
153     }
154   
155   fclose(yyin);
156
157   /* Add default ruleset */
158
159   io = get_default_if_config();
160   io->name = malloc(strlen(DEFAULT_IF_CONFIG_NAME) + 1);
161   strcpy(io->name, DEFAULT_IF_CONFIG_NAME);
162
163   /* Queue */
164   io->next = cnf->if_options;
165   cnf->if_options = io;
166
167   /* Verify and set up interface rulesets */
168   in = cnf->interfaces;
169
170   while(in)
171     {
172       in->cnf = find_if_rule_by_name(cnf->if_options, in->config);
173
174       if(in->cnf == NULL)
175         {
176           fprintf(stderr, "ERROR: Could not find a matching ruleset \"%s\" for %s\n", in->config, in->name);
177           olsrd_free_cnf(cnf);
178           exit(0);
179         }
180       /* set various stuff */
181       in->index = cnf->ifcnt++;
182       in->configured = 0;
183       in->interf = NULL;
184       /* Calculate max jitter */
185       in = in->next;
186     }
187
188
189   return cnf;
190 }
191
192
193
194
195 struct olsrd_config *
196 olsrd_get_default_cnf()
197 {
198   cnf = malloc(sizeof(struct olsrd_config));
199   if (cnf == NULL)
200     {
201       fprintf(stderr, "Out of memory %s\n", __func__);
202       return NULL;
203   }
204
205   set_default_cnf(cnf);
206
207   cnf->if_options = get_default_if_config();
208   cnf->if_options->name = malloc(strlen(DEFAULT_IF_CONFIG_NAME) + 1);
209   strcpy(cnf->if_options->name, DEFAULT_IF_CONFIG_NAME);
210
211   return cnf;
212 }
213
214
215
216
217
218
219
220 void
221 olsrd_free_cnf(struct olsrd_config *cnf)
222 {
223   struct hna4_entry        *h4d, *h4 = cnf->hna4_entries;
224   struct hna6_entry        *h6d, *h6 = cnf->hna6_entries;
225   struct olsr_if           *ind, *in = cnf->interfaces;
226   struct plugin_entry      *ped, *pe = cnf->plugins;
227   struct if_config_options *iod, *io = cnf->if_options;
228   
229   while(h4)
230     {
231       h4d = h4;
232       h4 = h4->next;
233       free(h4d);
234     }
235
236   while(h6)
237     {
238       h6d = h6;
239       h6 = h6->next;
240       free(h6d);
241     }
242
243   while(in)
244     {
245       ind = in;
246       in = in->next;
247       free(ind->name);
248       free(ind->config);
249       free(ind);
250     }
251
252   while(pe)
253     {
254       ped = pe;
255       pe = pe->next;
256       free(ped->name);
257       free(ped);
258     }
259
260   while(io)
261     {
262       iod = io;
263       io = io->next;
264       free(iod->name);
265       free(iod);
266     }
267
268   return;
269 }
270
271
272
273 void
274 set_default_cnf(struct olsrd_config *cnf)
275 {
276     memset(cnf, 0, sizeof(struct olsrd_config));
277     
278     cnf->debug_level = 1;
279     cnf->ip_version  = AF_INET;
280     cnf->allow_no_interfaces = 1;
281     cnf->tos = 16;
282     cnf->willingness_auto = 1;
283     cnf->open_ipc = 0;
284
285     cnf->use_hysteresis = 1;
286     cnf->hysteresis_param.scaling = HYST_SCALING;
287     cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
288     cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
289
290     cnf->pollrate = 0.1;
291
292     cnf->tc_redundancy = TC_REDUNDANCY;
293     cnf->mpr_coverage = MPR_COVERAGE;
294 }
295
296
297
298
299 struct if_config_options *
300 get_default_if_config()
301 {
302   struct if_config_options *io = malloc(sizeof(struct if_config_options));
303   struct in6_addr in6;
304  
305   memset(io, 0, sizeof(struct if_config_options));
306
307   io->ipv6_addrtype = 1;
308
309   if(inet_pton(AF_INET6, OLSR_IPV6_MCAST_SITE_LOCAL, &in6) < 0)
310     {
311       fprintf(stderr, "Failed converting IP address %s\n", OLSR_IPV6_MCAST_SITE_LOCAL);
312       exit(EXIT_FAILURE);
313     }
314   memcpy(&io->ipv6_multi_site.v6, &in6, sizeof(struct in6_addr));
315
316   if(inet_pton(AF_INET6, OLSR_IPV6_MCAST_GLOBAL, &in6) < 0)
317     {
318       fprintf(stderr, "Failed converting IP address %s\n", OLSR_IPV6_MCAST_GLOBAL);
319       exit(EXIT_FAILURE);
320     }
321   memcpy(&io->ipv6_multi_glbl.v6, &in6, sizeof(struct in6_addr));
322
323
324   io->hello_params.emission_interval = HELLO_INTERVAL;
325   io->hello_params.validity_time = NEIGHB_HOLD_TIME;
326   io->tc_params.emission_interval = TC_INTERVAL;
327   io->tc_params.validity_time = TOP_HOLD_TIME;
328   io->mid_params.emission_interval = MID_INTERVAL;
329   io->mid_params.validity_time = MID_HOLD_TIME;
330   io->hna_params.emission_interval = HNA_INTERVAL;
331   io->hna_params.validity_time = HNA_HOLD_TIME;
332
333   return io;
334
335 }
336
337
338
339
340
341 int
342 olsrd_write_cnf(struct olsrd_config *cnf, char *fname)
343 {
344   struct hna4_entry        *h4 = cnf->hna4_entries;
345   struct hna6_entry        *h6 = cnf->hna6_entries;
346   struct olsr_if           *in = cnf->interfaces;
347   struct plugin_entry      *pe = cnf->plugins;
348   struct if_config_options *io = cnf->if_options;
349   char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
350   struct in_addr in4;
351
352   FILE *fd;
353
354   fd = fopen(fname, "w");
355
356   if(fd == NULL)
357     {
358       fprintf(stderr, "Could not open file %s for writing\n%s\n", fname, strerror(errno));
359       return -1;
360     }
361
362   printf("Writing config to file \"%s\".... ", fname);
363
364   fprintf(fd, "#\n# Configuration file for olsr.org olsrd\n# automatically generated by olsrd-cnf %s\n#\n\n\n", PARSER_VERSION);
365
366   /* Debug level */
367   fprintf(fd, "# Debug level(0-9)\n# If set to 0 the daemon runs in the background\n\nDebugLevel\t%d\n\n", cnf->debug_level);
368
369   /* IP version */
370   fprintf(fd, "# IP version to use (4 or 6)\n\nIpVersion\t%d\n\n", cnf->ip_version);
371
372
373   /* HNA IPv4 */
374   fprintf(fd, "# HNA IPv4 routes\n# syntax: netaddr netmask\n# Example Internet gateway:\n# 0.0.0.0 0.0.0.0\n\nHna4\n{\n");
375   while(h4)
376     {
377       in4.s_addr = h4->net.v4;
378       fprintf(fd, "    %s ", inet_ntoa(in4));
379       in4.s_addr = h4->netmask.v4;
380       fprintf(fd, "%s\n", inet_ntoa(in4));
381       h4 = h4->next;
382     }
383   fprintf(fd, "}\n\n");
384
385
386   /* HNA IPv6 */
387   fprintf(fd, "# HNA IPv6 routes\n# syntax: netaddr prefix\n# Example Internet gateway:\nHna6\n{\n");
388   while(h6)
389     {
390       fprintf(fd, "    %s/%d\n", (char *)inet_ntop(AF_INET6, &h6->net.v6, ipv6_buf, sizeof(ipv6_buf)), h6->prefix_len);
391       h6 = h6->next;
392     }
393
394   fprintf(fd, "}\n\n");
395
396
397   /* Interfaces */
398   fprintf(fd, "# Interfaces and their rulesets\n\n");
399   /* Interfaces */
400   if(in)
401     {
402       while(in)
403         {
404           fprintf(fd, "Interface \"%s\"\n{\n", in->name);
405           fprintf(fd, "    Setup\"%s\"\n", in->config);
406           fprintf(fd, "}\n\n");
407           in = in->next;
408         }
409     }
410   fprintf(fd, "\n");
411
412
413   /* No interfaces */
414   fprintf(fd, "# Should olsrd keep on running even if there are\n# no interfaces available? This is a good idea\n# for a PCMCIA/USB hotswap environment.\n# \"yes\" OR \"no\"\n\nAllowNoInt\t");
415   if(cnf->allow_no_interfaces)
416     fprintf(fd, "yes\n\n");
417   else
418     fprintf(fd, "no\n\n");
419
420   /* TOS */
421   fprintf(fd, "# TOS(type of service) value for\n# the IP header of control traffic.\n# default is 16\n\n");
422   fprintf(fd, "TosValue\t%d\n\n", cnf->tos);
423
424   /* Willingness */
425   fprintf(fd, "# The fixed willingness to use(0-7)\n# or \"auto\" to set willingness dynammically\n# based on battery/power status\n\n");
426   if(cnf->willingness_auto)
427     fprintf(fd, "Willingness\tauto\n\n");
428   else
429     fprintf(fd, "Willingness%d\n\n", cnf->willingness);
430
431   /* IPC */
432   fprintf(fd, "# Allow processes like the GUI front-end\n# to connect to the daemon. 'yes' or 'no'\n\n");
433   if(cnf->open_ipc)
434     fprintf(fd, "IpcConnect\tyes\n\n");
435   else
436     fprintf(fd, "IpcConnect\tno\n\n");
437
438
439
440   /* Hysteresis */
441   fprintf(fd, "# Wether to use hysteresis or not\n# Hysteresis adds more robustness to the\n# link sensing but delays neighbor registration.\n# Used by default. 'yes' or 'no'\n\n");
442
443   if(cnf->use_hysteresis)
444     {
445       fprintf(fd, "UseHysteresis\tyes\n\n");
446       fprintf(fd, "# Hysteresis parameters\n# Do not alter these unless you know \n# what you are doing!\n# Set to auto by default. Allowed\n# values are floating point values\n# in the interval 0,1\n# THR_LOW must always be lower than\n# THR_HIGH!!\n\n");
447       fprintf(fd, "HystScaling\t%0.2f\n", cnf->hysteresis_param.scaling);
448       fprintf(fd, "HystThrHigh\t%0.2f\n", cnf->hysteresis_param.thr_high);
449       fprintf(fd, "HystThrLow\t%0.2f\n", cnf->hysteresis_param.thr_low);
450     }
451   else
452     fprintf(fd, "UseHysteresis\tno\n\n");
453
454   fprintf(fd, "\n\n");
455
456   /* Pollrate */
457   fprintf(fd, "# Polling rate in seconds(float).\n# Auto uses default value 0.1 sec\n\n");
458   fprintf(fd, "Pollrate\t%0.2f\n", cnf->pollrate);
459
460   /* TC redundancy */
461   fprintf(fd, "# TC redundancy\n# Specifies how much neighbor info should\n# be sent in TC messages\n# Possible values are:\n# 0 - only send MPR selectors\n# 1 - send MPR selectors and MPRs\n# 2 - send all neighbors\n#\n# defaults to 0\n\n");
462   fprintf(fd, "TcRedundancy\t%d\n\n", cnf->tc_redundancy);
463
464   /* MPR coverage */
465   fprintf(fd, "# MPR coverage\n# Specifies how many MPRs a node should\n# try select to reach every 2 hop neighbor\n# Can be set to any integer >0\n# defaults to 1\n\n");
466
467   fprintf(fd, "MprCoverage\t%d\n\n", cnf->mpr_coverage);
468    
469
470
471   /* Plugins */
472   fprintf(fd, "# Olsrd plugins to load\n# This must be the absolute path to the file\n# or the loader will use the following scheme:\n# - Try the paths in the LD_LIBRARY_PATH \n#   environment variable.\n# - The list of libraries cached in /etc/ld.so.cache\n# - /lib, followed by /usr/lib\n\n");
473   if(pe)
474     {
475       while(pe)
476         {
477           fprintf(fd, "LoadPlugin \"%s\"\n{\n", pe->name);
478           pe = pe->next;
479           fprintf(fd, "}\n");
480         }
481     }
482           fprintf(fd, "\n");
483
484   /* Rulesets */
485   while(io)
486     {
487       fprintf(fd, "IfSetup \"%s\"\n{\n", io->name);
488
489       
490       fprintf(fd, "    # IPv4 broadcast address to use. The\n    # one usefull example would be 255.255.255.255\n    # If not defined the broadcastaddress\n    # every card is configured with is used\n\n");
491
492       if(io->ipv4_broadcast.v4)
493         {
494           in4.s_addr = io->ipv4_broadcast.v4;
495           fprintf(fd, "    Ip4Broadcast\t %s\n\n", inet_ntoa(in4));
496         }
497       else
498         {
499           fprintf(fd, "    #Ip4Broadcast\t255.255.255.255\n\n");
500         }
501
502
503       fprintf(fd, "    # IPv6 address scope to use.\n    # Must be 'site-local' or 'global'\n\n");
504       if(io->ipv6_addrtype)
505         fprintf(fd, "    Ip6AddrType \tsite-local\n\n");
506       else
507         fprintf(fd, "    Ip6AddrType \tglobal\n\n");
508
509       fprintf(fd, "    # IPv6 multicast address to use when\n    # using site-local addresses.\n    # If not defined, ff05::15 is used\n");
510       fprintf(fd, "    Ip6MulticastSite\t%s\n\n", (char *)inet_ntop(AF_INET6, &io->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
511       fprintf(fd, "    # IPv6 multicast address to use when\n    # using global addresses\n    # If not defined, ff0e::1 is used\n");
512       fprintf(fd, "    Ip6MulticastGlobal\t%s\n\n", (char *)inet_ntop(AF_INET6, &io->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
513
514
515
516       fprintf(fd, "    # Emission intervals.\n    # If not defined, RFC proposed values will\n    # in most cases be used.\n\n");
517
518
519       fprintf(fd, "    HelloInterval\t%0.2f\n", io->hello_params.emission_interval);
520       fprintf(fd, "    HelloValidityTime\t%0.2f\n", io->hello_params.validity_time);
521       fprintf(fd, "    TcInterval\t\t%0.2f\n", io->tc_params.emission_interval);
522       fprintf(fd, "    TcValidityTime\t%0.2f\n", io->tc_params.validity_time);
523       fprintf(fd, "    MidInterval\t\t%0.2f\n", io->mid_params.emission_interval);
524       fprintf(fd, "    MidValidityTime\t%0.2f\n", io->mid_params.validity_time);
525       fprintf(fd, "    HnaInterval\t\t%0.2f\n", io->hna_params.emission_interval);
526       fprintf(fd, "    HnaValidityTime\t%0.2f\n", io->hna_params.validity_time);
527
528
529
530       io = io->next;
531
532       fprintf(fd, "}\n\n\n");
533     }
534
535   fprintf(fd, "\n# END AUTOGENERATED CONFIG\n");
536
537   fclose(fd);
538   printf("DONE\n");
539
540   return 1;
541 }
542
543
544
545
546
547 void
548 olsrd_print_cnf(struct olsrd_config *cnf)
549 {
550   struct hna4_entry        *h4 = cnf->hna4_entries;
551   struct hna6_entry        *h6 = cnf->hna6_entries;
552   struct olsr_if           *in = cnf->interfaces;
553   struct plugin_entry      *pe = cnf->plugins;
554   struct if_config_options *io = cnf->if_options;
555   char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
556   struct in_addr in4;
557
558   printf(" *** olsrd configuration ***\n");
559
560   printf("Debug Level      : %d\n", cnf->debug_level);
561   printf("IpVersion        : %d\n", cnf->ip_version);
562   if(cnf->allow_no_interfaces)
563     printf("No interfaces    : ALLOWED\n");
564   else
565     printf("No interfaces    : NOT ALLOWED\n");
566   printf("TOS              : 0x%02x\n", cnf->tos);
567   if(cnf->willingness_auto)
568     printf("Willingness      : AUTO\n");
569   else
570     printf("Willingness      : %d\n", cnf->willingness);
571
572   if(cnf->open_ipc)
573     printf("IPC              : ENABLED\n");
574   else
575     printf("IPC              : DISABLED\n");
576
577   printf("Pollrate         : %0.2f\n", cnf->pollrate);
578
579   printf("TC redundancy    : %d\n", cnf->tc_redundancy);
580
581   printf("MPR coverage     : %d\n", cnf->mpr_coverage);
582    
583   /* Interfaces */
584   if(in)
585     {
586       printf("Interfaces:\n");
587       while(in)
588         {
589           printf("\tdev: \"%s\" ruleset: \"%s\"\n", in->name, in->config);
590           in = in->next;
591         }
592     }
593
594   /* Rulesets */
595   while(io)
596     {
597       printf("Interface ruleset \"%s\":\n", io->name);
598
599       
600       if(io->ipv4_broadcast.v4)
601         {
602           in4.s_addr = io->ipv4_broadcast.v4;
603           printf("\tIPv4 broadcast        : %s\n", inet_ntoa(in4));
604         }
605       else
606         {
607           printf("\tIPv4 broadcast        : AUTO\n");
608         }
609
610       if(io->ipv6_addrtype)
611         printf("\tIPv6 addrtype         : site-local\n");
612       else
613         printf("\tIPv6 addrtype         : global\n");
614
615       //union olsr_ip_addr       ipv6_multi_site;
616       //union olsr_ip_addr       ipv6_multi_glbl;
617       printf("\tIPv6 multicast site   : %s\n", (char *)inet_ntop(AF_INET6, &io->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
618       printf("\tIPv6 multicast global : %s\n", (char *)inet_ntop(AF_INET6, &io->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
619
620       printf("\tHELLO emission int    : %0.2f\n", io->hello_params.emission_interval);
621       printf("\tHELLO validity time   : %0.2f\n", io->hello_params.validity_time);
622       printf("\tTC emission int       : %0.2f\n", io->tc_params.emission_interval);
623       printf("\tTC validity time      : %0.2f\n", io->tc_params.validity_time);
624       printf("\tMID emission int      : %0.2f\n", io->mid_params.emission_interval);
625       printf("\tMID validity time     : %0.2f\n", io->mid_params.validity_time);
626       printf("\tHNA emission int      : %0.2f\n", io->hna_params.emission_interval);
627       printf("\tHNA validity time     : %0.2f\n", io->hna_params.validity_time);
628
629
630
631       io = io->next;
632     }
633
634   /* Plugins */
635   if(pe)
636     {
637       printf("Plugins:\n");
638
639       while(pe)
640         {
641           printf("\tName: \"%s\"\n", pe->name);
642           pe = pe->next;
643         }
644     }
645
646   /* Hysteresis */
647   if(cnf->use_hysteresis)
648     {
649       printf("Using hysteresis:\n");
650       printf("\tScaling : %0.2f\n", cnf->hysteresis_param.scaling);
651       printf("\tThr high: %0.2f\n", cnf->hysteresis_param.thr_high);
652       printf("\tThr low : %0.2f\n", cnf->hysteresis_param.thr_low);
653     }
654   else
655     printf("Not using hysteresis\n");
656
657   /* HNA IPv4 */
658   if(h4)
659     {
660
661       printf("HNA4 entries:\n");
662       while(h4)
663         {
664           in4.s_addr = h4->net.v4;
665           printf("\t%s/", inet_ntoa(in4));
666           in4.s_addr = h4->netmask.v4;
667           printf("%s\n", inet_ntoa(in4));
668
669           h4 = h4->next;
670         }
671     }
672
673   /* HNA IPv6 */
674   if(h6)
675     {
676       printf("HNA6 entries:\n");
677       while(h6)
678         {
679           printf("\t%s/%d\n", (char *)inet_ntop(AF_INET6, &h6->net.v6, ipv6_buf, sizeof(ipv6_buf)), h6->prefix_len);
680           h6 = h6->next;
681         }
682     }
683 }
684
685
686
687
688 struct if_config_options *
689 find_if_rule_by_name(struct if_config_options *io, char *name)
690 {
691
692   while(io)
693     {
694       if(strcmp(io->name, name) == 0)
695         return io;
696       io = io->next;
697     }
698   return NULL;
699 }