99a85266721f0f232c13471c370abf1662c76dcf
[olsrd.git] / src / cfgparser / olsrd_conf.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <stdlib.h>
5 #include <sys/socket.h>
6 #include <netinet/in.h>
7 #include <arpa/inet.h>
8
9 #include "olsrd_conf.h"
10
11
12 extern FILE *yyin;
13 extern int yyparse(void);
14
15
16 #ifdef MAKELIB
17
18 /* Build as DLL */
19
20 void __attribute__ ((constructor)) 
21 my_init(void);
22
23 void __attribute__ ((destructor)) 
24 my_fini(void);
25
26
27 /**
28  *Constructor
29  */
30 void
31 my_init()
32 {
33   /* Print plugin info to stdout */
34   printf("olsrd config file parser %s loaded\n", SOFTWARE_VERSION);
35
36   return;
37 }
38
39 /**
40  *Destructor
41  */
42 void
43 my_fini()
44 {
45   printf("See you around!\n");
46   return;
47 }
48
49 #else
50
51 #ifdef MAKEBIN
52
53 /* Build as standalone binary */
54 int 
55 main(int argc, char *argv[])
56 {
57   struct olsrd_config *cnf;
58
59   if(argc == 1)
60     {
61       fprintf(stderr, "Usage: olsrd_cfgparser [filename] -print\n\n");
62       exit(EXIT_FAILURE);
63     }
64
65   if((cnf = olsrd_parse_cnf(argv[1])) != NULL)
66     {
67       if((argc > 2) && (!strcmp(argv[2], "-print")))
68         {
69           olsrd_print_cnf(cnf);  
70           olsrd_write_cnf(cnf, "./out.conf");
71         }
72       else
73         printf("Use -print to view parsed values\n");
74       printf("Configfile parsed OK\n");
75     }
76   else
77     {
78       printf("Failed parsing \"%s\"\n", argv[1]);
79     }
80
81   return 0;
82 }
83
84 #else
85
86 /* Build as part of olsrd */
87
88
89 #endif
90
91 #endif
92
93 struct olsrd_config *
94 olsrd_parse_cnf(char *filename)
95 {
96   struct olsr_if *in;
97
98   cnf = malloc(sizeof(struct olsrd_config));
99   if (cnf == NULL)
100     {
101       fprintf(stderr, "Out of memory %s\n", __func__);
102       return NULL;
103   }
104
105   set_default_cnf(cnf);
106
107   printf("Parsing file: \"%s\"\n", filename);
108
109   yyin = fopen(filename, "r");
110   
111   if (yyin == NULL)
112     {
113       fprintf(stderr, "Cannot open configuration file '%s': %s.\n",
114               filename, strerror(errno));
115       free(cnf);
116       return NULL;
117   }
118
119   current_line = 1;
120
121   if (yyparse() != 0)
122     {
123       fclose(yyin);
124       olsrd_free_cnf(cnf);
125       return NULL;
126     }
127   
128   fclose(yyin);
129
130   /* Verify interface rulesets */
131   in = cnf->interfaces;
132
133   while(in)
134     {
135       in->if_options = find_if_rule_by_name(cnf->if_options, in->config);
136
137       if(in->if_options == NULL)
138         {
139           fprintf(stderr, "ERROR: Could not find a matching ruleset \"%s\" for %s\n", in->config, in->name);
140           olsrd_free_cnf(cnf);
141           return NULL;
142         }
143       in = in->next;
144     }
145
146   return cnf;
147 }
148
149
150
151
152
153
154
155
156 void
157 olsrd_free_cnf(struct olsrd_config *cnf)
158 {
159   struct hna4_entry        *h4d, *h4 = cnf->hna4_entries;
160   struct hna6_entry        *h6d, *h6 = cnf->hna6_entries;
161   struct olsr_if           *ind, *in = cnf->interfaces;
162   struct plugin_entry      *ped, *pe = cnf->plugins;
163   struct if_config_options *iod, *io = cnf->if_options;
164   
165   while(h4)
166     {
167       h4d = h4;
168       h4 = h4->next;
169       free(h4d);
170     }
171
172   while(h6)
173     {
174       h6d = h6;
175       h6 = h6->next;
176       free(h6d);
177     }
178
179   while(in)
180     {
181       ind = in;
182       in = in->next;
183       free(ind->name);
184       free(ind->config);
185       free(ind);
186     }
187
188   while(pe)
189     {
190       ped = pe;
191       pe = pe->next;
192       free(ped->name);
193       free(ped);
194     }
195
196   while(io)
197     {
198       iod = io;
199       io = io->next;
200       free(iod->name);
201       free(iod);
202     }
203
204   return;
205 }
206
207
208
209 void
210 set_default_cnf(struct olsrd_config *cnf)
211 {
212     memset(cnf, 0, sizeof(struct olsrd_config));
213     
214     cnf->debug_level = 1;
215     cnf->ip_version  = 4;
216     cnf->allow_no_interfaces = 1;
217     cnf->tos = 16;
218     cnf->auto_willingness = 1;
219     cnf->open_ipc = 0;
220
221     cnf->use_hysteresis = 1;
222     cnf->hysteresis_param.scaling = HYST_SCALING;
223     cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
224     cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
225
226     cnf->pollrate = 0.1;
227
228     cnf->tc_redundancy = TC_REDUNDANCY;
229     cnf->mpr_coverage = MPR_COVERAGE;
230 }
231
232
233
234
235
236
237 int
238 olsrd_write_cnf(struct olsrd_config *cnf, char *fname)
239 {
240   struct hna4_entry        *h4 = cnf->hna4_entries;
241   struct hna6_entry        *h6 = cnf->hna6_entries;
242   struct olsr_if           *in = cnf->interfaces;
243   struct plugin_entry      *pe = cnf->plugins;
244   struct if_config_options *io = cnf->if_options;
245   char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
246   struct in_addr in4;
247
248   FILE *fd;
249
250   fd = fopen(fname, "w");
251
252   if(fd == NULL)
253     {
254       fprintf(stderr, "Could not open file %s for writing\n%s\n", fname, strerror(errno));
255       return -1;
256     }
257
258   printf("Writing config to file \"%s\".... ", fname);
259
260   fprintf(fd, "#\n# Configuration file for olsr.org olsrd\n# automatically generated by olsrd-cnf %s\n#\n\n\n", SOFTWARE_VERSION);
261
262   /* Debug level */
263   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);
264
265   /* IP version */
266   fprintf(fd, "# IP version to use (4 or 6)\n\nIpVersion\t%d\n\n", cnf->ip_version);
267
268
269   /* HNA IPv4 */
270   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");
271   if(h4)
272     {
273       while(h4)
274         {
275           in4.s_addr=h4->net;
276           fprintf(fd, "    %s ", inet_ntoa(in4));
277           in4.s_addr=h4->netmask;
278           fprintf(fd, "%s\n", inet_ntoa(in4));
279           h4 = h4->next;
280         }
281     }
282   fprintf(fd, "}\n\n");
283
284
285   /* HNA IPv6 */
286   fprintf(fd, "# HNA IPv6 routes\n# syntax: netaddr prefix\n# Example Internet gateway:\nHna6\n{\n");
287   if(h6)
288     {
289       while(h6)
290         {
291           fprintf(fd, "    %s/%d\n", (char *)inet_ntop(AF_INET6, &h6->net.v6, ipv6_buf, sizeof(ipv6_buf)), h6->prefix_len);
292           h6 = h6->next;
293         }
294     }
295
296   fprintf(fd, "}\n\n");
297
298
299   /* Interfaces */
300   fprintf(fd, "# Interfaces and their rulesets\nInterfaces\n{\n");
301   /* Interfaces */
302   if(in)
303     {
304       while(in)
305         {
306           fprintf(fd, "    \"%s\" \"%s\"\n", in->name, in->config);
307           in = in->next;
308         }
309     }
310   fprintf(fd, "}\n\n");
311
312
313   /* No interfaces */
314   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");
315   if(cnf->allow_no_interfaces)
316     fprintf(fd, "yes\n\n");
317   else
318     fprintf(fd, "no\n\n");
319
320   /* TOS */
321   fprintf(fd, "# TOS(type of service) value for\n# the IP header of control traffic.\n# default is 16\n\n");
322   fprintf(fd, "TosValue\t%d\n\n", cnf->tos);
323
324   /* Willingness */
325   fprintf(fd, "# The fixed willingness to use(0-7)\n# or \"auto\" to set willingness dynammically\n# based on battery/power status\n\n");
326   if(cnf->auto_willingness)
327     fprintf(fd, "Willingness\tauto\n\n");
328   else
329     fprintf(fd, "Willingness%d\n\n", cnf->fixed_willingness);
330
331   /* IPC */
332   fprintf(fd, "# Allow processes like the GUI front-end\n# to connect to the daemon. 'yes' or 'no'\n\n");
333   if(cnf->open_ipc)
334     fprintf(fd, "IpcConnect\tyes\n\n");
335   else
336     fprintf(fd, "IpcConnect\tno\n\n");
337
338
339
340   /* Hysteresis */
341   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");
342
343   if(cnf->use_hysteresis)
344     {
345       fprintf(fd, "UseHysteresis\tyes\n\n");
346       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");
347       fprintf(fd, "HystScaling\t%0.2f\n", cnf->hysteresis_param.scaling);
348       fprintf(fd, "HystThrHigh\t%0.2f\n", cnf->hysteresis_param.thr_high);
349       fprintf(fd, "HystThrLow\t%0.2f\n", cnf->hysteresis_param.thr_low);
350     }
351   else
352     fprintf(fd, "UseHysteresis\tno\n\n");
353
354   fprintf(fd, "\n\n");
355
356   /* Pollrate */
357   fprintf(fd, "# Polling rate in seconds(float).\n# Auto uses default value 0.1 sec\n\n");
358   fprintf(fd, "Pollrate\t%0.2f\n", cnf->pollrate);
359
360   /* TC redundancy */
361   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");
362   fprintf(fd, "TcRedundancy\t%d\n\n", cnf->tc_redundancy);
363
364   /* MPR coverage */
365   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");
366
367   fprintf(fd, "MprCoverage\t%d\n\n", cnf->mpr_coverage);
368    
369
370
371   /* Plugins */
372   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\nLoadPlugin\n{\n");
373   if(pe)
374     {
375       while(pe)
376         {
377           fprintf(fd, "    PlName \"%s\"\n", pe->name);
378           pe = pe->next;
379         }
380     }
381   fprintf(fd, "}\n\n");
382
383
384   /* Rulesets */
385   while(io)
386     {
387       fprintf(fd, "IfSetup \"%s\"\n{\n", io->name);
388
389       
390       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");
391
392       if(io->ipv4_broadcast.v4)
393         {
394           in4.s_addr = io->ipv4_broadcast.v4;
395           fprintf(fd, "    Ip4Broadcast\t %s\n\n", inet_ntoa(in4));
396         }
397       else
398         {
399           fprintf(fd, "    #Ip4Broadcast\t255.255.255.255\n\n");
400         }
401
402
403       fprintf(fd, "    # IPv6 address scope to use.\n    # Must be 'site-local' or 'global'\n\n");
404       if(io->ipv6_addrtype)
405         fprintf(fd, "    Ip6AddrType \tsite-local\n\n");
406       else
407         fprintf(fd, "    Ip6AddrType \tglobal\n\n");
408
409       fprintf(fd, "    # IPv6 multicast address to use when\n    # using site-local addresses.\n    # If not defined, ff05::15 is used\n");
410       fprintf(fd, "    Ip6MulticastSite\t%s\n\n", (char *)inet_ntop(AF_INET6, &io->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
411       fprintf(fd, "    # IPv6 multicast address to use when\n    # using global addresses\n    # If not defined, ff0e::1 is used\n");
412       fprintf(fd, "    Ip6MulticastGlobal\t%s\n\n", (char *)inet_ntop(AF_INET6, &io->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
413
414
415
416       fprintf(fd, "    # Emission intervals.\n    # If not defined, RFC proposed values will\n    # in most cases be used.\n\n");
417
418
419       fprintf(fd, "    HelloInterval\t%0.2f\n", io->hello_params.emission_interval);
420       fprintf(fd, "    HelloValidityTime\t%0.2f\n", io->hello_params.validity_time);
421       fprintf(fd, "    TcInterval\t\t%0.2f\n", io->tc_params.emission_interval);
422       fprintf(fd, "    TcValidityTime\t%0.2f\n", io->tc_params.validity_time);
423       fprintf(fd, "    MidInterval\t\t%0.2f\n", io->mid_params.emission_interval);
424       fprintf(fd, "    MidValidityTime\t%0.2f\n", io->mid_params.validity_time);
425       fprintf(fd, "    HnaInterval\t\t%0.2f\n", io->hna_params.emission_interval);
426       fprintf(fd, "    HnaValidityTime\t%0.2f\n", io->hna_params.validity_time);
427
428
429
430       io = io->next;
431
432       fprintf(fd, "}\n\n\n");
433     }
434
435   fprintf(fd, "\n# END AUTOGENERATED CONFIG\n");
436
437   fclose(fd);
438   printf("DONE\n");
439
440   return 1;
441 }
442
443
444
445
446
447 void
448 olsrd_print_cnf(struct olsrd_config *cnf)
449 {
450   struct hna4_entry        *h4 = cnf->hna4_entries;
451   struct hna6_entry        *h6 = cnf->hna6_entries;
452   struct olsr_if           *in = cnf->interfaces;
453   struct plugin_entry      *pe = cnf->plugins;
454   struct if_config_options *io = cnf->if_options;
455   char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
456   struct in_addr in4;
457
458   printf(" *** olsrd configuration ***\n");
459
460   printf("Debug Level      : %d\n", cnf->debug_level);
461   printf("IpVersion        : %d\n", cnf->ip_version);
462   if(cnf->allow_no_interfaces)
463     printf("No interfaces    : ALLOWED\n");
464   else
465     printf("No interfaces    : NOT ALLOWED\n");
466   printf("TOS              : 0x%02x\n", cnf->tos);
467   if(cnf->auto_willingness)
468     printf("Willingness      : AUTO\n");
469   else
470     printf("Willingness      : %d\n", cnf->fixed_willingness);
471
472   if(cnf->open_ipc)
473     printf("IPC              : ENABLED\n");
474   else
475     printf("IPC              : DISABLED\n");
476
477   printf("Pollrate         : %0.2f\n", cnf->pollrate);
478
479   printf("TC redundancy    : %d\n", cnf->tc_redundancy);
480
481   printf("MPR coverage     : %d\n", cnf->mpr_coverage);
482    
483   /* Interfaces */
484   if(in)
485     {
486       printf("Interfaces:\n");
487       while(in)
488         {
489           printf("\tdev: \"%s\" ruleset: \"%s\"\n", in->name, in->config);
490           in = in->next;
491         }
492     }
493
494   /* Rulesets */
495   while(io)
496     {
497       printf("Interface ruleset \"%s\":\n", io->name);
498
499       
500       if(io->ipv4_broadcast.v4)
501         {
502           in4.s_addr = io->ipv4_broadcast.v4;
503           printf("\tIPv4 broadcast        : %s\n", inet_ntoa(in4));
504         }
505       else
506         {
507           printf("\tIPv4 broadcast        : AUTO\n");
508         }
509
510       if(io->ipv6_addrtype)
511         printf("\tIPv6 addrtype         : site-local\n");
512       else
513         printf("\tIPv6 addrtype         : global\n");
514
515       //union olsr_ip_addr       ipv6_multi_site;
516       //union olsr_ip_addr       ipv6_multi_glbl;
517       printf("\tIPv6 multicast site   : %s\n", (char *)inet_ntop(AF_INET6, &io->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
518       printf("\tIPv6 multicast global : %s\n", (char *)inet_ntop(AF_INET6, &io->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
519
520       printf("\tHELLO emission int    : %0.2f\n", io->hello_params.emission_interval);
521       printf("\tHELLO validity time   : %0.2f\n", io->hello_params.validity_time);
522       printf("\tTC emission int       : %0.2f\n", io->tc_params.emission_interval);
523       printf("\tTC validity time      : %0.2f\n", io->tc_params.validity_time);
524       printf("\tMID emission int      : %0.2f\n", io->mid_params.emission_interval);
525       printf("\tMID validity time     : %0.2f\n", io->mid_params.validity_time);
526       printf("\tHNA emission int      : %0.2f\n", io->hna_params.emission_interval);
527       printf("\tHNA validity time     : %0.2f\n", io->hna_params.validity_time);
528
529
530
531       io = io->next;
532     }
533
534   /* Plugins */
535   if(pe)
536     {
537       printf("Plugins:\n");
538
539       while(pe)
540         {
541           printf("\tName: \"%s\"\n", pe->name);
542           pe = pe->next;
543         }
544     }
545
546   /* Hysteresis */
547   if(cnf->use_hysteresis)
548     {
549       printf("Using hysteresis:\n");
550       printf("\tScaling : %0.2f\n", cnf->hysteresis_param.scaling);
551       printf("\tThr high: %0.2f\n", cnf->hysteresis_param.thr_high);
552       printf("\tThr low : %0.2f\n", cnf->hysteresis_param.thr_low);
553     }
554   else
555     printf("Not using hysteresis\n");
556
557   /* HNA IPv4 */
558   if(h4)
559     {
560
561       printf("HNA4 entries:\n");
562       while(h4)
563         {
564           in4.s_addr=h4->net;
565           printf("\t%s/", inet_ntoa(in4));
566           in4.s_addr=h4->netmask;
567           printf("%s\n", inet_ntoa(in4));
568
569           h4 = h4->next;
570         }
571     }
572
573   /* HNA IPv6 */
574   if(h6)
575     {
576       printf("HNA6 entries:\n");
577       while(h6)
578         {
579           printf("\t%s/%d\n", (char *)inet_ntop(AF_INET6, &h6->net.v6, ipv6_buf, sizeof(ipv6_buf)), h6->prefix_len);
580           h6 = h6->next;
581         }
582     }
583 }
584
585
586
587
588 struct if_config_options *
589 find_if_rule_by_name(struct if_config_options *io, char *name)
590 {
591
592   while(io)
593     {
594       if(strcmp(io->name, name) == 0)
595         return io;
596       io = io->next;
597     }
598   return NULL;
599 }