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