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