From 6b139d613ae6fa127bdce1be5c634ed4b53b1efd Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 10 Jun 2014 20:46:52 +0200 Subject: Clean up peer config loading Instead of changing the peer list and peer group in the main conf during (re-)loading, add a parser state which contains this information. --- src/config.c | 88 +++++++++++++++++++++++++++++++---------------------------- src/config.h | 19 ++++++++++--- src/config.y | 59 +++++++++++++++++++++------------------ src/options.c | 12 +++++--- src/peer.c | 15 ++-------- src/peer.h | 3 +- src/types.h | 1 + 7 files changed, 105 insertions(+), 92 deletions(-) diff --git a/src/config.c b/src/config.c index 21c30c4..1e6cff7 100644 --- a/src/config.c +++ b/src/config.c @@ -143,22 +143,22 @@ void fastd_config_bind_address(const fastd_peer_address_t *address, const char * } /** Handles the start of a peer group configuration */ -void fastd_config_peer_group_push(const char *name) { +void fastd_config_peer_group_push(fastd_parser_state_t *state, const char *name) { fastd_peer_group_t *group = calloc(1, sizeof(fastd_peer_group_t)); group->name = strdup(name); group->max_connections = -1; - group->parent = conf.peer_group; + group->parent = state->peer_group; group->next = group->parent->children; group->parent->children = group; - conf.peer_group = group; + state->peer_group = group; } /** Handles the end of a peer group configuration */ -void fastd_config_peer_group_pop(void) { - conf.peer_group = conf.peer_group->parent; +void fastd_config_peer_group_pop(fastd_parser_state_t *state) { + state->peer_group = state->peer_group->parent; } /** Frees a peer group and its children */ @@ -189,7 +189,7 @@ static bool has_peer_group_peer_dirs(const fastd_peer_group_t *group) { } /** Reads and processes all peer definitions in the current directory (which must also be supplied as the argument) */ -static void read_peer_dir(const char *dir) { +static void read_peer_dir(fastd_peer_config_t **peers, fastd_peer_group_t *group, const char *dir) { DIR *dirh = opendir("."); if (dirh) { @@ -221,13 +221,17 @@ static void read_peer_dir(const char *dir) { continue; } - fastd_peer_config_new(); - conf.peers->name = strdup(result->d_name); - conf.peers->config_source_dir = dir; + fastd_peer_config_t *peer = fastd_peer_config_new(group); + peer->name = strdup(result->d_name); + peer->config_source_dir = dir; - if (!fastd_read_config(result->d_name, true, 0)) { + if (fastd_config_read(result->d_name, group, peer, 0)) { + peer->next = *peers; + *peers = peer; + } + else { pr_warn("peer config `%s' will be ignored", result->d_name); - fastd_peer_config_delete(); + fastd_peer_config_free(peer); } } @@ -240,14 +244,14 @@ static void read_peer_dir(const char *dir) { } } -/** Reads all peer configured directories */ -static void read_peer_dirs(void) { +/** Reads all configured peer directories for a peer grup */ +static void read_peer_dirs(fastd_peer_config_t **peers, fastd_peer_group_t *group) { char *oldcwd = get_current_dir_name(); fastd_string_stack_t *dir; - for (dir = conf.peer_group->peer_dirs; dir; dir = dir->next) { + for (dir = group->peer_dirs; dir; dir = dir->next) { if (!chdir(dir->str)) - read_peer_dir(dir->str); + read_peer_dir(peers, group, dir->str); else pr_error("change from directory `%s' to `%s' failed: %s", oldcwd, dir->str, strerror(errno)); } @@ -259,15 +263,15 @@ static void read_peer_dirs(void) { } /** Adds a peer directory to the configuration */ -void fastd_add_peer_dir(const char *dir) { +void fastd_config_add_peer_dir(fastd_peer_group_t *group, const char *dir) { char *oldcwd = get_current_dir_name(); if (!chdir(dir)) { char *newdir = get_current_dir_name(); - conf.peer_group->peer_dirs = fastd_string_stack_push(conf.peer_group->peer_dirs, newdir); + group->peer_dirs = fastd_string_stack_push(group->peer_dirs, newdir); free(newdir); - if(chdir(oldcwd)) + if (chdir(oldcwd)) pr_error("can't chdir to `%s': %s", oldcwd, strerror(errno)); } else { @@ -278,7 +282,7 @@ void fastd_add_peer_dir(const char *dir) { } /** Reads and processes a configuration file */ -bool fastd_read_config(const char *filename, bool peer_config, int depth) { +bool fastd_config_read(const char *filename, fastd_peer_group_t *peer_group, fastd_peer_config_t *peer_config, int depth) { if (depth >= MAX_CONFIG_DEPTH) exit_error("maximum config include depth exceeded"); @@ -321,15 +325,21 @@ bool fastd_read_config(const char *filename, bool peer_config, int depth) { int token; YYSTYPE token_val; YYLTYPE loc = {1, 0, 1, 0}; + fastd_parser_state_t state = { + .peer_group = peer_group, + .peer = peer_config, + .filename = filename, + .depth = depth+1, + }; if (peer_config) token = START_PEER_CONFIG; else - token = conf.peer_group->parent ? START_PEER_GROUP_CONFIG : START_CONFIG; + token = peer_group->parent ? START_PEER_GROUP_CONFIG : START_CONFIG; - int parse_ret = fastd_config_push_parse(ps, token, &token_val, &loc, filename, depth+1); + int parse_ret = fastd_config_push_parse(ps, token, &token_val, &loc, &state); - while(parse_ret == YYPUSH_MORE) { + while (parse_ret == YYPUSH_MORE) { token = fastd_lex(&token_val, &loc, lex); if (token < 0) { @@ -343,7 +353,7 @@ bool fastd_read_config(const char *filename, bool peer_config, int depth) { strings = token_val.str; } - parse_ret = fastd_config_push_parse(ps, token, &token_val, &loc, filename, depth+1); + parse_ret = fastd_config_push_parse(ps, token, &token_val, &loc, &state); } if (parse_ret) @@ -559,17 +569,13 @@ void fastd_config_verify(void) { conf.protocol->peer_verify(peer); } -/** Reads the peer dirs of the current peer group and its children */ -static void peer_dirs_read_peer_group(void) { - read_peer_dirs(); - - fastd_peer_group_t *base = conf.peer_group, *group; - for (group = conf.peer_group->children; group; group = group->next) { - conf.peer_group = group; - peer_dirs_read_peer_group(); - } +/** Reads the peer dirs of a peer group and its children */ +static void peer_dirs_read_peer_group(fastd_peer_config_t **peers, fastd_peer_group_t *group) { + read_peer_dirs(peers, group); - conf.peer_group = base; + fastd_peer_group_t *child; + for (child = group->children; child; child = child->next) + peer_dirs_read_peer_group(peers, child); } /** Deletes peer configs that have disappeared from a peer dir on reconfiguration */ @@ -632,13 +638,8 @@ static void peer_dirs_handle_new_peers(fastd_peer_config_t **peers, fastd_peer_c /** Refreshes the peer configurations from the configured peer dirs */ void fastd_config_load_peer_dirs(void) { - fastd_peer_config_t *old_peers = conf.peers; - conf.peers = NULL; - - peer_dirs_read_peer_group(); - - fastd_peer_config_t *new_peers = conf.peers; - conf.peers = old_peers; + fastd_peer_config_t *new_peers = NULL; + peer_dirs_read_peer_group(&new_peers, conf.peer_group); peer_dirs_handle_old_peers(&conf.peers, &new_peers); peer_dirs_handle_new_peers(&conf.peers, new_peers); @@ -648,8 +649,11 @@ void fastd_config_load_peer_dirs(void) { /** Frees all resources used by the global configuration */ void fastd_config_release(void) { - while (conf.peers) - fastd_peer_config_delete(); + while (conf.peers) { + fastd_peer_config_t *peer = conf.peers, *next = peer->next; + fastd_peer_config_free(peer); + conf.peers = next; + } while (conf.bind_addrs) { fastd_bind_address_t *next = conf.bind_addrs->next; diff --git a/src/config.h b/src/config.h index 3231f6d..f4e1de5 100644 --- a/src/config.h +++ b/src/config.h @@ -35,20 +35,31 @@ #include "fastd.h" +/** State of the config parser */ +struct fastd_parser_state { + fastd_peer_group_t *peer_group; /**< The current peer group */ + fastd_peer_config_t *peer; /**< The peer currently being loaded */ + + const char *const filename; /**< The filename of the currently parsed file */ + const int depth; /**< The include depth */ +}; + + void fastd_config_protocol(const char *name); void fastd_config_method(const char *name); void fastd_config_cipher(const char *name, const char *impl); void fastd_config_mac(const char *name, const char *impl); void fastd_config_bind_address(const fastd_peer_address_t *address, const char *bindtodev, bool default_v4, bool default_v6); -void fastd_config_peer_group_push(const char *name); -void fastd_config_peer_group_pop(void); void fastd_config_release(void); void fastd_config_handle_options(int argc, char *const argv[]); void fastd_config_verify(void); +bool fastd_config_read(const char *filename, fastd_peer_group_t *peer_group, fastd_peer_config_t *peer_config, int depth); +void fastd_config_peer_group_push(fastd_parser_state_t *state, const char *name); +void fastd_config_peer_group_pop(fastd_parser_state_t *state); +void fastd_config_add_peer_dir(fastd_peer_group_t *group, const char *dir); + void fastd_configure(int argc, char *const argv[]); void fastd_config_check(void); void fastd_config_load_peer_dirs(void); -void fastd_add_peer_dir(const char *dir); -bool fastd_read_config(const char *filename, bool peer_config, int depth); diff --git a/src/config.y b/src/config.y index 88d6f53..a2e14e3 100644 --- a/src/config.y +++ b/src/config.y @@ -28,8 +28,7 @@ %define api.push-pull push %name-prefix "fastd_config_" %locations -%parse-param {const char *filename} -%parse-param {int depth} +%parse-param {fastd_parser_state_t *state} %code requires { #include @@ -138,7 +137,7 @@ #include - void fastd_config_error(YYLTYPE *loc, const char *filename, int depth, const char *s); + void fastd_config_error(YYLTYPE *loc, fastd_parser_state_t *state, const char *s); } @@ -349,7 +348,7 @@ packet_mark: TOK_UINT { mtu: TOK_UINT { if ($1 < 576 || $1 > 65535) { - fastd_config_error(&@$, filename, depth, "invalid MTU"); + fastd_config_error(&@$, state, "invalid MTU"); YYERROR; } @@ -416,15 +415,19 @@ on_verify: sync_def_async TOK_STRING { #ifdef WITH_VERIFY fastd_shell_command_set(&conf.on_verify, $2->str, $1); #else - fastd_config_error(&@$, filename, depth, "`on verify' is not supported by this version of fastd"); + fastd_config_error(&@$, state, "`on verify' is not supported by this version of fastd"); YYERROR; #endif } ; peer: TOK_STRING { - fastd_peer_config_new(); - conf.peers->name = strdup($1->str); + fastd_peer_config_t *peer = fastd_peer_config_new(state->peer_group); + peer->name = strdup($1->str); + peer->next = conf.peers; + + conf.peers = peer; + state->peer = peer; } ; @@ -439,7 +442,7 @@ peer_statement: TOK_REMOTE peer_remote ';' ; peer_remote: TOK_ADDR4 port { - fastd_remote_config_t **remote = &conf.peers->remotes; + fastd_remote_config_t **remote = &state->peer->remotes; while (*remote) remote = &(*remote)->next; @@ -451,7 +454,7 @@ peer_remote: TOK_ADDR4 port { fastd_peer_address_simplify(&(*remote)->address); } | TOK_ADDR6 port { - fastd_remote_config_t **remote = &conf.peers->remotes; + fastd_remote_config_t **remote = &state->peer->remotes; while (*remote) remote = &(*remote)->next; @@ -465,7 +468,7 @@ peer_remote: TOK_ADDR4 port { | TOK_ADDR6_SCOPED port { char addrbuf[INET6_ADDRSTRLEN]; size_t addrlen; - fastd_remote_config_t **remote = &conf.peers->remotes; + fastd_remote_config_t **remote = &state->peer->remotes; while (*remote) remote = &(*remote)->next; @@ -483,7 +486,7 @@ peer_remote: TOK_ADDR4 port { (*remote)->address.in.sin_port = htons($2); } | maybe_af TOK_STRING port { - fastd_remote_config_t **remote = &conf.peers->remotes; + fastd_remote_config_t **remote = &state->peer->remotes; while (*remote) remote = &(*remote)->next; @@ -496,40 +499,40 @@ peer_remote: TOK_ADDR4 port { ; peer_float: boolean { - conf.peers->floating = $1; + state->peer->floating = $1; } ; peer_key: TOK_STRING { - free(conf.peers->key); conf.peers->key = strdup($1->str); + free(state->peer->key); state->peer->key = strdup($1->str); } ; peer_include: TOK_STRING { - if (!fastd_read_config($1->str, true, depth)) + if (!fastd_config_read($1->str, state->peer_group, state->peer, state->depth)) YYERROR; } ; peer_group: TOK_STRING { - fastd_config_peer_group_push($1->str); + fastd_config_peer_group_push(state, $1->str); } ; peer_group_after: { - fastd_config_peer_group_pop(); + fastd_config_peer_group_pop(state); } ; peer_limit: TOK_UINT { if ($1 > INT_MAX) { - fastd_config_error(&@$, filename, depth, "invalid peer limit"); + fastd_config_error(&@$, state, "invalid peer limit"); YYERROR; } - conf.peer_group->max_connections = $1; + state->peer_group->max_connections = $1; } ; @@ -538,18 +541,20 @@ forward: boolean { conf.forward = $1; } include: TOK_PEER TOK_STRING maybe_as { - fastd_peer_config_new(); + fastd_peer_config_t *peer = fastd_peer_config_new(state->peer_group); if ($3) - conf.peers->name = strdup($3->str); - - if (!fastd_read_config($2->str, true, depth)) + peer->name = strdup($3->str); + if (!fastd_config_read($2->str, state->peer_group, peer, state->depth)) YYERROR; + + peer->next = conf.peers; + conf.peers = peer; } | TOK_PEERS TOK_FROM TOK_STRING { - fastd_add_peer_dir($3->str); + fastd_config_add_peer_dir(state->peer_group, $3->str); } | TOK_STRING { - if (!fastd_read_config($1->str, false, depth)) + if (!fastd_config_read($1->str, state->peer_group, NULL, state->depth)) YYERROR; } ; @@ -595,7 +600,7 @@ colon_or_port: ':' port: colon_or_port TOK_UINT { if ($2 < 1 || $2 > 65535) { - fastd_config_error(&@$, filename, depth, "invalid port"); + fastd_config_error(&@$, state, "invalid port"); YYERROR; } $$ = $2; @@ -603,6 +608,6 @@ port: colon_or_port TOK_UINT { ; %% -void fastd_config_error(YYLTYPE *loc, const char *filename, int depth UNUSED, const char *s) { - pr_error("config error: %s at %s:%i:%i", s, filename, loc->first_line, loc->first_column); +void fastd_config_error(YYLTYPE *loc, fastd_parser_state_t *state, const char *s) { + pr_error("config error: %s at %s:%i:%i", s, state->filename, loc->first_line, loc->first_column); } diff --git a/src/options.c b/src/options.c index 7ac026e..63115ef 100644 --- a/src/options.c +++ b/src/options.c @@ -111,21 +111,25 @@ static void option_config(const char *arg) { if (!strcmp(arg, "-")) arg = NULL; - if (!fastd_read_config(arg, false, 0)) + if (!fastd_config_read(arg, conf.peer_group, NULL, 0)) exit(1); } /** Handles the --config-peer option */ static void option_config_peer(const char *arg) { - fastd_peer_config_new(); + fastd_peer_config_t *peer = fastd_peer_config_new(conf.peer_group); - if(!fastd_read_config(arg, true, 0)) + if(!fastd_config_read(arg, conf.peer_group, peer, 0)) exit(1); + + peer->next = conf.peers; + conf.peers = peer; + } /** Handles the --config-peer-dir option */ static void option_config_peer_dir(const char *arg) { - fastd_add_peer_dir(arg); + fastd_config_add_peer_dir(conf.peer_group, arg); } diff --git a/src/peer.c b/src/peer.c index fd123f7..5de7831 100644 --- a/src/peer.c +++ b/src/peer.c @@ -431,13 +431,9 @@ static void delete_peer(fastd_peer_t *peer) { /** Allocates a new peer config */ -fastd_peer_config_t* fastd_peer_config_new(void) { +fastd_peer_config_t* fastd_peer_config_new(fastd_peer_group_t *group) { fastd_peer_config_t *peer = calloc(1, sizeof(fastd_peer_config_t)); - - peer->group = conf.peer_group; - - peer->next = conf.peers; - conf.peers = peer; + peer->group = group; return peer; } @@ -458,13 +454,6 @@ void fastd_peer_config_free(fastd_peer_config_t *peer) { free(peer); } -/** Deletes the peer config created last */ -void fastd_peer_config_delete(void) { - fastd_peer_config_t *peer = conf.peers, *next = peer->next; - fastd_peer_config_free(peer); - conf.peers = next; -} - /** Deletes a peer config, and removes the peer assiciated with the peer config */ void fastd_peer_config_purge(fastd_peer_config_t *config) { size_t i; diff --git a/src/peer.h b/src/peer.h index 9da5f3c..7fcb092 100644 --- a/src/peer.h +++ b/src/peer.h @@ -165,9 +165,8 @@ static inline uint16_t fastd_peer_address_get_port(const fastd_peer_address_t *a } } -fastd_peer_config_t* fastd_peer_config_new(void); +fastd_peer_config_t* fastd_peer_config_new(fastd_peer_group_t *group); void fastd_peer_config_free(fastd_peer_config_t *peer); -void fastd_peer_config_delete(void); void fastd_peer_config_purge(fastd_peer_config_t *config); bool fastd_peer_config_equal(const fastd_peer_config_t *peer1, const fastd_peer_config_t *peer2); diff --git a/src/types.h b/src/types.h index d13828c..3ab03a6 100644 --- a/src/types.h +++ b/src/types.h @@ -107,6 +107,7 @@ typedef struct fastd_mac fastd_mac_t; typedef struct fastd_handshake fastd_handshake_t; typedef struct fastd_lex fastd_lex_t; +typedef struct fastd_parser_state fastd_parser_state_t; typedef struct fastd_string_stack fastd_string_stack_t; typedef struct fastd_shell_command fastd_shell_command_t; -- cgit v1.2.3