starter: Migrated logging to libstrongswan.
[strongswan.git] / src / starter / parser.y
1 %{
2 /* strongSwan config file parser (parser.y)
3  * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  */
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include <library.h>
21 #include <debug.h>
22
23 #include "../pluto/constants.h"
24 #include "../pluto/defs.h"
25
26 #include "ipsec-parser.h"
27
28 #define YYERROR_VERBOSE
29 #define ERRSTRING_LEN   256
30
31 /**
32  * Bison
33  */
34 static char parser_errstring[ERRSTRING_LEN+1];
35
36 extern void yyerror(const char *s);
37 extern int yylex (void);
38 extern void _parser_y_error(char *b, int size, const char *s);
39
40 /**
41  * Static Globals
42  */
43 static int _save_errors_;
44 static config_parsed_t *_parser_cfg;
45 static kw_list_t **_parser_kw, *_parser_kw_last;
46 static char errbuf[ERRSTRING_LEN+1];
47
48 /**
49  * Gperf
50  */
51 extern kw_entry_t *in_word_set (char *str, unsigned int len);
52
53 %}
54
55 %union { char *s; };
56 %token EQUAL FIRST_SPACES EOL CONFIG SETUP CONN CA INCLUDE FILE_VERSION
57 %token <s> STRING
58
59 %%
60
61 /*
62  * Config file
63  */
64
65 config_file:
66         config_file section_or_include
67         | /* NULL */
68         ;
69
70 section_or_include:
71         FILE_VERSION STRING EOL
72         {
73                 free($2);
74         }
75         | CONFIG SETUP EOL
76         {
77                 _parser_kw = &(_parser_cfg->config_setup);
78                 _parser_kw_last = NULL;
79         } kw_section
80         | CONN STRING EOL
81         {
82                 section_list_t *section = malloc_thing(section_list_t);
83
84                 section->name = clone_str($2);
85                 section->kw = NULL;
86                 section->next = NULL;
87                 _parser_kw = &(section->kw);
88                 if (!_parser_cfg->conn_first)
89                         _parser_cfg->conn_first = section;
90                 if (_parser_cfg->conn_last)
91                         _parser_cfg->conn_last->next = section;
92                 _parser_cfg->conn_last = section;
93                 _parser_kw_last = NULL;
94                 free($2);
95         } kw_section
96         | CA STRING EOL
97         {
98                 section_list_t *section = malloc_thing(section_list_t);
99                 section->name = clone_str($2);
100                 section->kw = NULL;
101                 section->next = NULL;
102                 _parser_kw = &(section->kw);
103                 if (!_parser_cfg->ca_first)
104                         _parser_cfg->ca_first = section;
105                 if (_parser_cfg->ca_last)
106                         _parser_cfg->ca_last->next = section;
107                 _parser_cfg->ca_last = section;
108                 _parser_kw_last = NULL;
109                 free($2);
110         } kw_section
111         | INCLUDE STRING
112         {
113                 extern void _parser_y_include (const char *f);
114                 _parser_y_include($2);
115                 free($2);
116         } EOL
117         | EOL
118         ;
119
120 kw_section:
121         FIRST_SPACES statement_kw EOL kw_section
122         |
123         ;
124
125 statement_kw:
126         STRING EQUAL STRING
127         {
128                 kw_list_t  *new;
129                 kw_entry_t *entry = in_word_set($1, strlen($1));
130
131                 if (entry == NULL)
132                 {
133                         snprintf(errbuf, ERRSTRING_LEN, "unknown keyword '%s'", $1);
134                         yyerror(errbuf);
135                 }
136                 else if (_parser_kw)
137                 {
138                         new = (kw_list_t *)malloc_thing(kw_list_t);
139                         new->entry = entry;
140                         new->value = clone_str($3);
141                         new->next = NULL;
142                         if (_parser_kw_last)
143                                 _parser_kw_last->next = new;
144                         _parser_kw_last = new;
145                         if (!*_parser_kw)
146                                 *_parser_kw = new;
147                 }
148                 free($1);
149                 free($3);
150         }
151         | STRING EQUAL
152           {
153                 free($1);
154           }
155         |
156         ;
157
158 %%
159
160 void yyerror(const char *s)
161 {
162         if (_save_errors_)
163                 _parser_y_error(parser_errstring, ERRSTRING_LEN, s);
164 }
165
166 config_parsed_t *parser_load_conf(const char *file)
167 {
168         config_parsed_t *cfg = NULL;
169         int err = 0;
170         FILE *f;
171
172         extern void _parser_y_init(const char *f);
173         extern void _parser_y_fini(void);
174         extern FILE *yyin;
175
176         memset(parser_errstring, 0, ERRSTRING_LEN+1);
177
178         cfg = (config_parsed_t *)malloc_thing(config_parsed_t);
179         if (cfg)
180         {
181                 memset(cfg, 0, sizeof(config_parsed_t));
182                 f = fopen(file, "r");
183                 if (f)
184                 {
185                         yyin = f;
186                         _parser_y_init(file);
187                         _save_errors_ = 1;
188                         _parser_cfg = cfg;
189
190                         if (yyparse() !=0 )
191                         {
192                                 if (parser_errstring[0] == '\0')
193                                 {
194                                         snprintf(parser_errstring, ERRSTRING_LEN, "Unknown error...");
195                                 }
196                                 _save_errors_ = 0;
197                                 while (yyparse() != 0);
198                                 err++;
199                         }
200                         else if (parser_errstring[0] != '\0')
201                         {
202                                 err++;
203                         }
204                         else
205                         {
206                                 /**
207                                  * Config valid
208                                  */
209                         }
210
211                         fclose(f);
212                 }
213                 else
214                 {
215                         snprintf(parser_errstring, ERRSTRING_LEN, "can't load file '%s'", file);
216                         err++;
217                 }
218         }
219         else
220         {
221                 snprintf(parser_errstring, ERRSTRING_LEN, "can't allocate memory");
222                 err++;
223         }
224
225         if (err)
226         {
227                 DBG1(DBG_APP, "%s", parser_errstring);
228
229                 if (cfg)
230                         parser_free_conf(cfg);
231                 cfg = NULL;
232         }
233
234         _parser_y_fini();
235         return cfg;
236 }
237
238 static void parser_free_kwlist(kw_list_t *list)
239 {
240         kw_list_t *elt;
241
242         while (list)
243         {
244                 elt = list;
245                 list = list->next;
246                 free(elt->value);
247                 free(elt);
248         }
249 }
250
251 void parser_free_conf(config_parsed_t *cfg)
252 {
253         section_list_t *sec;
254         if (cfg)
255         {
256                 parser_free_kwlist(cfg->config_setup);
257                 while (cfg->conn_first)
258                 {
259                         sec = cfg->conn_first;
260                         cfg->conn_first = cfg->conn_first->next;
261                         free(sec->name);
262                         parser_free_kwlist(sec->kw);
263                         free(sec);
264                 }
265                 while (cfg->ca_first)
266                 {
267                         sec = cfg->ca_first;
268                         cfg->ca_first = cfg->ca_first->next;
269                         free(sec->name);
270                         parser_free_kwlist(sec->kw);
271                         free(sec);
272                 }
273                 free(cfg);
274         }
275 }