diff options
Diffstat (limited to 'src/starter/parser.y')
-rw-r--r-- | src/starter/parser.y | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/src/starter/parser.y b/src/starter/parser.y new file mode 100644 index 000000000..db984fae3 --- /dev/null +++ b/src/starter/parser.y @@ -0,0 +1,283 @@ +%{ +/* strongSwan config file parser (parser.y) + * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * RCSID $Id: parser.y,v 1.6 2006/01/17 23:43:36 as Exp $ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <freeswan.h> + +#include "../pluto/constants.h" +#include "../pluto/defs.h" +#include "../pluto/log.h" +#include "parser.h" + +#define YYERROR_VERBOSE +#define ERRSTRING_LEN 256 + +/** + * Bison + */ +static char parser_errstring[ERRSTRING_LEN+1]; + +extern void yyerror(const char *s); +extern int yylex (void); +extern void _parser_y_error(char *b, int size, const char *s); + +/** + * Static Globals + */ +static int _save_errors_; +static config_parsed_t *_parser_cfg; +static kw_list_t **_parser_kw, *_parser_kw_last; +static char errbuf[ERRSTRING_LEN+1]; + +/** + * Gperf + */ +extern kw_entry_t *in_word_set (char *str, unsigned int len); + +%} + +%union { char *s; }; +%token EQUAL FIRST_SPACES EOL CONFIG SETUP CONN CA INCLUDE FILE_VERSION +%token <s> STRING + +%% + +/* + * Config file + */ + +config_file: + config_file section_or_include + | /* NULL */ + ; + +section_or_include: + FILE_VERSION STRING EOL + { + free($2); + } + | CONFIG SETUP EOL + { + _parser_kw = &(_parser_cfg->config_setup); + _parser_kw_last = NULL; + } kw_section + | CONN STRING EOL + { + section_list_t *section = (section_list_t *)alloc_thing(section_list_t + , "section_list_t"); + + section->name = clone_str($2, "conn section name"); + section->kw = NULL; + section->next = NULL; + _parser_kw = &(section->kw); + if (!_parser_cfg->conn_first) + _parser_cfg->conn_first = section; + if (_parser_cfg->conn_last) + _parser_cfg->conn_last->next = section; + _parser_cfg->conn_last = section; + _parser_kw_last = NULL; + free($2); + } kw_section + | CA STRING EOL + { + section_list_t *section = (section_list_t *)alloc_thing(section_list_t + , "section_list_t"); + section->name = clone_str($2, "ca section name"); + section->kw = NULL; + section->next = NULL; + _parser_kw = &(section->kw); + if (!_parser_cfg->ca_first) + _parser_cfg->ca_first = section; + if (_parser_cfg->ca_last) + _parser_cfg->ca_last->next = section; + _parser_cfg->ca_last = section; + _parser_kw_last = NULL; + free($2); + } kw_section + | INCLUDE STRING + { + extern void _parser_y_include (const char *f); + _parser_y_include($2); + free($2); + } EOL + | EOL + ; + +kw_section: + FIRST_SPACES statement_kw EOL kw_section + | + ; + +statement_kw: + STRING EQUAL STRING + { + kw_list_t *new; + kw_entry_t *entry = in_word_set($1, strlen($1)); + + if (entry == NULL) + { + snprintf(errbuf, ERRSTRING_LEN, "unknown keyword '%s'", $1); + yyerror(errbuf); + } + else if (_parser_kw) + { + new = (kw_list_t *)alloc_thing(kw_list_t, "kw_list_t"); + new->entry = entry; + new->value = clone_str($3, "kw_list value"); + new->next = NULL; + if (_parser_kw_last) + _parser_kw_last->next = new; + _parser_kw_last = new; + if (!*_parser_kw) + *_parser_kw = new; + } + free($1); + free($3); + } + | STRING EQUAL + { + free($1); + } + | + ; + +%% + +void +yyerror(const char *s) +{ + if (_save_errors_) + _parser_y_error(parser_errstring, ERRSTRING_LEN, s); +} + +config_parsed_t * +parser_load_conf(const char *file) +{ + config_parsed_t *cfg = NULL; + int err = 0; + FILE *f; + + extern void _parser_y_init (const char *f); + extern FILE *yyin; + + memset(parser_errstring, 0, ERRSTRING_LEN+1); + + cfg = (config_parsed_t *)alloc_thing(config_parsed_t, "config_parsed_t"); + if (cfg) + { + memset(cfg, 0, sizeof(config_parsed_t)); + f = fopen(file, "r"); + if (f) + { + yyin = f; + _parser_y_init(file); + _save_errors_ = 1; + _parser_cfg = cfg; + + if (yyparse() !=0 ) + { + if (parser_errstring[0] == '\0') + { + snprintf(parser_errstring, ERRSTRING_LEN, "Unknown error..."); + } + _save_errors_ = 0; + while (yyparse() != 0); + err++; + } + else if (parser_errstring[0] != '\0') + { + err++; + } + else + { + /** + * Config valid + */ + } + + fclose(f); + } + else + { + snprintf(parser_errstring, ERRSTRING_LEN, "can't load file '%s'", file); + err++; + } + } + else + { + snprintf(parser_errstring, ERRSTRING_LEN, "can't allocate memory"); + err++; + } + + if (err) + { + plog("%s", parser_errstring); + + if (cfg) + parser_free_conf(cfg); + cfg = NULL; + } + + return cfg; +} + +static void +parser_free_kwlist(kw_list_t *list) +{ + kw_list_t *elt; + + while (list) + { + elt = list; + list = list->next; + if (elt->value) + pfree(elt->value); + pfree(elt); + } +} + +void +parser_free_conf(config_parsed_t *cfg) +{ + section_list_t *sec; + if (cfg) + { + parser_free_kwlist(cfg->config_setup); + while (cfg->conn_first) + { + sec = cfg->conn_first; + cfg->conn_first = cfg->conn_first->next; + if (sec->name) + pfree(sec->name); + parser_free_kwlist(sec->kw); + pfree(sec); + } + while (cfg->ca_first) + { + sec = cfg->ca_first; + cfg->ca_first = cfg->ca_first->next; + if (sec->name) + pfree(sec->name); + parser_free_kwlist(sec->kw); + pfree(sec); + } + pfree(cfg); + } +} |