NEWS about eap-dynamic plugin added
[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 "ipsec-parser.h"
24
25 #define YYERROR_VERBOSE
26 #define ERRSTRING_LEN   256
27
28 /**
29  * Bison
30  */
31 static char parser_errstring[ERRSTRING_LEN+1];
32
33 extern void yyerror(const char *s);
34 extern int yylex (void);
35 extern void _parser_y_error(char *b, int size, const char *s);
36
37 /**
38  * Static Globals
39  */
40 static int _save_errors_;
41 static config_parsed_t *_parser_cfg;
42 static kw_list_t **_parser_kw, *_parser_kw_last;
43 static char errbuf[ERRSTRING_LEN+1];
44
45 /**
46  * Gperf
47  */
48 extern kw_entry_t *in_word_set (char *str, unsigned int len);
49
50 %}
51
52 %union { char *s; };
53 %token EQUAL FIRST_SPACES EOL CONFIG SETUP CONN CA INCLUDE FILE_VERSION
54 %token <s> STRING
55
56 %%
57
58 /*
59  * Config file
60  */
61
62 config_file:
63         config_file section_or_include
64         | /* NULL */
65         ;
66
67 section_or_include:
68         FILE_VERSION STRING EOL
69         {
70                 free($2);
71         }
72         | CONFIG SETUP EOL
73         {
74                 _parser_kw = &(_parser_cfg->config_setup);
75                 _parser_kw_last = NULL;
76         } kw_section
77         | CONN STRING EOL
78         {
79                 section_list_t *section = malloc_thing(section_list_t);
80
81                 section->name = strdupnull($2);
82                 section->kw = NULL;
83                 section->next = NULL;
84                 _parser_kw = &(section->kw);
85                 if (!_parser_cfg->conn_first)
86                         _parser_cfg->conn_first = section;
87                 if (_parser_cfg->conn_last)
88                         _parser_cfg->conn_last->next = section;
89                 _parser_cfg->conn_last = section;
90                 _parser_kw_last = NULL;
91                 free($2);
92         } kw_section
93         | CA STRING EOL
94         {
95                 section_list_t *section = malloc_thing(section_list_t);
96                 section->name = strdupnull($2);
97                 section->kw = NULL;
98                 section->next = NULL;
99                 _parser_kw = &(section->kw);
100                 if (!_parser_cfg->ca_first)
101                         _parser_cfg->ca_first = section;
102                 if (_parser_cfg->ca_last)
103                         _parser_cfg->ca_last->next = section;
104                 _parser_cfg->ca_last = section;
105                 _parser_kw_last = NULL;
106                 free($2);
107         } kw_section
108         | INCLUDE STRING
109         {
110                 extern void _parser_y_include (const char *f);
111                 _parser_y_include($2);
112                 free($2);
113         } EOL
114         | EOL
115         ;
116
117 kw_section:
118         FIRST_SPACES statement_kw EOL kw_section
119         |
120         ;
121
122 statement_kw:
123         STRING EQUAL STRING
124         {
125                 kw_list_t  *new;
126                 kw_entry_t *entry = in_word_set($1, strlen($1));
127
128                 if (entry == NULL)
129                 {
130                         snprintf(errbuf, ERRSTRING_LEN, "unknown keyword '%s'", $1);
131                         yyerror(errbuf);
132                 }
133                 else if (_parser_kw)
134                 {
135                         new = (kw_list_t *)malloc_thing(kw_list_t);
136                         new->entry = entry;
137                         new->value = strdupnull($3);
138                         new->next = NULL;
139                         if (_parser_kw_last)
140                                 _parser_kw_last->next = new;
141                         _parser_kw_last = new;
142                         if (!*_parser_kw)
143                                 *_parser_kw = new;
144                 }
145                 free($1);
146                 free($3);
147         }
148         | STRING EQUAL
149           {
150                 free($1);
151           }
152         |
153         ;
154
155 %%
156
157 void yyerror(const char *s)
158 {
159         if (_save_errors_)
160                 _parser_y_error(parser_errstring, ERRSTRING_LEN, s);
161 }
162
163 config_parsed_t *parser_load_conf(const char *file)
164 {
165         config_parsed_t *cfg = NULL;
166         int err = 0;
167         FILE *f;
168
169         extern void _parser_y_init(const char *f);
170         extern void _parser_y_fini(void);
171         extern FILE *yyin;
172
173         memset(parser_errstring, 0, ERRSTRING_LEN+1);
174
175         cfg = (config_parsed_t *)malloc_thing(config_parsed_t);
176         if (cfg)
177         {
178                 memset(cfg, 0, sizeof(config_parsed_t));
179                 f = fopen(file, "r");
180                 if (f)
181                 {
182                         yyin = f;
183                         _parser_y_init(file);
184                         _save_errors_ = 1;
185                         _parser_cfg = cfg;
186
187                         if (yyparse() !=0 )
188                         {
189                                 if (parser_errstring[0] == '\0')
190                                 {
191                                         snprintf(parser_errstring, ERRSTRING_LEN, "Unknown error...");
192                                 }
193                                 _save_errors_ = 0;
194                                 while (yyparse() != 0);
195                                 err++;
196                         }
197                         else if (parser_errstring[0] != '\0')
198                         {
199                                 err++;
200                         }
201                         else
202                         {
203                                 /**
204                                  * Config valid
205                                  */
206                         }
207
208                         fclose(f);
209                 }
210                 else
211                 {
212                         snprintf(parser_errstring, ERRSTRING_LEN, "can't load file '%s'", file);
213                         err++;
214                 }
215         }
216         else
217         {
218                 snprintf(parser_errstring, ERRSTRING_LEN, "can't allocate memory");
219                 err++;
220         }
221
222         if (err)
223         {
224                 DBG1(DBG_APP, "%s", parser_errstring);
225
226                 if (cfg)
227                         parser_free_conf(cfg);
228                 cfg = NULL;
229         }
230
231         _parser_y_fini();
232         return cfg;
233 }
234
235 static void parser_free_kwlist(kw_list_t *list)
236 {
237         kw_list_t *elt;
238
239         while (list)
240         {
241                 elt = list;
242                 list = list->next;
243                 free(elt->value);
244                 free(elt);
245         }
246 }
247
248 void parser_free_conf(config_parsed_t *cfg)
249 {
250         section_list_t *sec;
251         if (cfg)
252         {
253                 parser_free_kwlist(cfg->config_setup);
254                 while (cfg->conn_first)
255                 {
256                         sec = cfg->conn_first;
257                         cfg->conn_first = cfg->conn_first->next;
258                         free(sec->name);
259                         parser_free_kwlist(sec->kw);
260                         free(sec);
261                 }
262                 while (cfg->ca_first)
263                 {
264                         sec = cfg->ca_first;
265                         cfg->ca_first = cfg->ca_first->next;
266                         free(sec->name);
267                         parser_free_kwlist(sec->kw);
268                         free(sec);
269                 }
270                 free(cfg);
271         }
272 }