From f631c10660c7c0bcdbf793bb1588670fb9ea82e6 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 5 Nov 2012 18:26:55 +0100 Subject: Implement peer groups --- src/config.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- src/config.l | 1 + src/config.y | 13 ++++++++++++ src/fastd.c | 38 +++++++++++++++++++++++++++++++++ src/fastd.h | 27 +++++++++++++++++++++++- src/peer.c | 22 +++++++++++++++++++- src/peer.h | 2 ++ src/types.h | 2 ++ 8 files changed, 164 insertions(+), 9 deletions(-) diff --git a/src/config.c b/src/config.c index 228951e..6dbbe08 100644 --- a/src/config.c +++ b/src/config.c @@ -115,6 +115,8 @@ static void default_config(fastd_config *conf) { #ifdef USE_CRYPTO_GHASH conf->crypto_ghash = fastd_crypto_ghash_default; #endif + + conf->peer_group = calloc(1, sizeof(fastd_peer_group_config)); } static bool config_match(const char *opt, ...) { @@ -240,6 +242,47 @@ void fastd_config_bind_address(fastd_context *ctx, fastd_config *conf, const fas conf->bind_addr_default_v6 = addr; } +void fastd_config_peer_group_push(fastd_context *ctx, fastd_config *conf, const char *name) { + fastd_peer_group_config *group = calloc(1, sizeof(fastd_peer_group_config)); + group->name = strdup(name); + + group->parent = conf->peer_group; + group->next = group->parent->children; + + group->parent->children = group; + + conf->peer_group = group; +} + +void fastd_config_peer_group_pop(fastd_context *ctx, fastd_config *conf) { + conf->peer_group = conf->peer_group->parent; +} + +static void free_peer_group(fastd_peer_group_config *group) { + while (group->children) { + fastd_peer_group_config *next = group->children->next; + free_peer_group(group->children); + group->children = next; + } + + fastd_string_stack_free(group->peer_dirs); + free(group->name); + free(group); +} + +static bool has_peer_group_peer_dirs(const fastd_peer_group_config *group) { + if (group->peer_dirs) + return true; + + const fastd_peer_group_config *child; + for (child = group->children; child; child = child->next) { + if (has_peer_group_peer_dirs(child)) + return true; + } + + return false; +} + bool fastd_config_add_log_file(fastd_context *ctx, fastd_config *conf, const char *name, int level) { char *name2 = strdup(name); char *name3 = strdup(name); @@ -328,10 +371,10 @@ void fastd_read_peer_dir(fastd_context *ctx, fastd_config *conf, const char *dir if (!chdir(dir)) { char *newdir = get_current_dir_name(); - conf->peer_dirs = fastd_string_stack_push(conf->peer_dirs, newdir); + conf->peer_group->peer_dirs = fastd_string_stack_push(conf->peer_group->peer_dirs, newdir); free(newdir); - read_peer_dir(ctx, conf, conf->peer_dirs->str); + read_peer_dir(ctx, conf, conf->peer_group->peer_dirs->str); if(chdir(oldcwd)) pr_error(ctx, "can't chdir to `%s': %s", oldcwd, strerror(errno)); @@ -778,11 +821,11 @@ void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *con if (conf->mode == MODE_TUN) { if (!conf->peers || conf->peers->next) exit_error(ctx, "config error: for tun mode exactly one peer must be configured"); - if (conf->peer_dirs) + if (has_peer_group_peer_dirs(conf->peer_group)) exit_error(ctx, "config error: for tun mode peer directories can't be used"); } - if (!conf->peers && !conf->peer_dirs) + if (!conf->peers && !has_peer_group_peer_dirs(conf->peer_group)) exit_error(ctx, "config error: neither fixed peers nor peer dirs have been configured"); count_peers(ctx, conf); @@ -809,6 +852,16 @@ static void reconfigure_read_peer_dirs(fastd_context *ctx, fastd_config *new_con free(oldcwd); } +static void reconfigure_read_peer_group(fastd_context *ctx, fastd_config *new_conf) { + reconfigure_read_peer_dirs(ctx, new_conf, new_conf->peer_group->peer_dirs); + + fastd_peer_group_config *group; + for (group = new_conf->peer_group->children; group; group = group->next) { + new_conf->peer_group = group; + reconfigure_read_peer_group(ctx, new_conf); + } +} + static void reconfigure_handle_old_peers(fastd_context *ctx, fastd_peer_config **old_peers, fastd_peer_config **new_peers) { fastd_peer_config **peer, **next, **new_peer, **new_next; for (peer = old_peers; *peer; peer = next) { @@ -879,9 +932,10 @@ void fastd_reconfigure(fastd_context *ctx, fastd_config *conf) { pr_info(ctx, "reconfigure triggered"); fastd_config temp_conf; + temp_conf.peer_group = conf->peer_group; temp_conf.peers = NULL; - reconfigure_read_peer_dirs(ctx, &temp_conf, conf->peer_dirs); + reconfigure_read_peer_group(ctx, &temp_conf); reconfigure_handle_old_peers(ctx, &conf->peers, &temp_conf.peers); reconfigure_reset_waiting(ctx); @@ -895,8 +949,6 @@ void fastd_config_release(fastd_context *ctx, fastd_config *conf) { while (conf->peers) fastd_peer_config_delete(ctx, conf); - fastd_string_stack_free(conf->peer_dirs); - while (conf->log_files) { fastd_log_file *next = conf->log_files->next; free(conf->log_files->filename); @@ -911,6 +963,8 @@ void fastd_config_release(fastd_context *ctx, fastd_config *conf) { conf->bind_addrs = next; } + free_peer_group(conf->peer_group); + free(conf->ifname); free(conf->secret); free(conf->on_up); diff --git a/src/config.l b/src/config.l index 9e82239..e8d5584 100644 --- a/src/config.l +++ b/src/config.l @@ -100,6 +100,7 @@ float { TOKEN(TOK_FLOAT); } crypto { TOKEN(TOK_CRYPTO); } use { TOKEN(TOK_USE); } default { TOKEN(TOK_DEFAULT); } +group { TOKEN(TOK_GROUP); } [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} { UPDATE_LOCATION; diff --git a/src/config.y b/src/config.y index 5bf374e..e3c8f82 100644 --- a/src/config.y +++ b/src/config.y @@ -99,6 +99,7 @@ %token TOK_CRYPTO %token TOK_USE %token TOK_DEFAULT +%token TOK_GROUP %token TOK_ADDR4 %token TOK_ADDR6 @@ -150,6 +151,7 @@ statement: TOK_LOG log ';' | TOK_ON TOK_ESTABLISH on_establish ';' | TOK_ON TOK_DISESTABLISH on_disestablish ';' | TOK_PEER peer '{' peer_conf '}' + | TOK_PEER TOK_GROUP peer_group '{' config '}' peer_group_after | TOK_FORWARD forward ';' | TOK_INCLUDE include ';' ; @@ -363,6 +365,17 @@ peer_include: TOK_STRING { ; +peer_group: TOK_STRING { + fastd_config_peer_group_push(ctx, conf, $1->str); + } + ; + +peer_group_after: + { + fastd_config_peer_group_pop(ctx, conf); + } + ; + forward: boolean { conf->forward = $1; } ; diff --git a/src/fastd.c b/src/fastd.c index f121e49..d81f949 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -557,6 +557,42 @@ static void on_down(fastd_context *ctx) { free(cwd); } +static fastd_peer_group* init_peer_group(const fastd_peer_group_config *config, fastd_peer_group *parent) { + fastd_peer_group *ret = calloc(1, sizeof(fastd_peer_group)); + + ret->conf = config; + ret->parent = parent; + + fastd_peer_group **children = &ret->children; + fastd_peer_group_config *child_config; + + for (child_config = config->children; child_config; child_config = child_config->next) { + *children = init_peer_group(child_config, ret); + children = &(*children)->next; + } + + return ret; +} + +static void init_peer_groups(fastd_context *ctx) { + ctx->peer_group = init_peer_group(ctx->conf->peer_group, NULL); +} + +static void free_peer_group(fastd_peer_group *group) { + while (group->children) { + fastd_peer_group *child = group->children; + group->children = group->children->next; + + free_peer_group(child); + } + + free(group); +} + +static void delete_peer_groups(fastd_context *ctx) { + free_peer_group(ctx->peer_group); +} + static void init_peers(fastd_context *ctx) { fastd_peer_config *peer_conf; for (peer_conf = ctx->conf->peers; peer_conf; peer_conf = peer_conf->next) { @@ -962,6 +998,7 @@ int main(int argc, char *argv[]) { init_tuntap(&ctx); + init_peer_groups(&ctx); init_peers(&ctx); if (conf.daemon) { @@ -1009,6 +1046,7 @@ int main(int argc, char *argv[]) { on_down(&ctx); delete_peers(&ctx); + delete_peer_groups(&ctx); close_tuntap(&ctx); close_sockets(&ctx); diff --git a/src/fastd.h b/src/fastd.h index 9779de8..38af9cc 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -144,6 +144,28 @@ struct _fastd_socket { fastd_peer *peer; }; +struct _fastd_peer_group_config { + fastd_peer_group_config *next; + fastd_peer_group_config *parent; + fastd_peer_group_config *children; + + char *name; + fastd_string_stack *peer_dirs; + + /* contraints */ + unsigned max_connections; +}; + +struct _fastd_peer_group { + fastd_peer_group *next; + fastd_peer_group *parent; + fastd_peer_group *children; + + const fastd_peer_group_config *conf; + + unsigned n_connections; +}; + struct _fastd_config { int log_stderr_level; int log_syslog_level; @@ -187,7 +209,7 @@ struct _fastd_config { const fastd_crypto_ghash *crypto_ghash; #endif - fastd_string_stack *peer_dirs; + fastd_peer_group_config *peer_group; fastd_peer_config *peers; unsigned n_floating; @@ -229,6 +251,7 @@ struct _fastd_context { struct timespec now; unsigned n_peers; + fastd_peer_group *peer_group; fastd_peer *peers; fastd_queue task_queue; @@ -284,6 +307,8 @@ bool fastd_config_method(fastd_context *ctx, fastd_config *conf, const char *nam bool fastd_config_crypto(fastd_context *ctx, fastd_config *conf, const char *alg, const char *impl); bool fastd_config_add_log_file(fastd_context *ctx, fastd_config *conf, const char *name, int level); void fastd_config_bind_address(fastd_context *ctx, fastd_config *conf, const fastd_peer_address *address, const char *bindtodev, bool default_v4, bool default_v6); +void fastd_config_peer_group_push(fastd_context *ctx, fastd_config *conf, const char *name); +void fastd_config_peer_group_pop(fastd_context *ctx, fastd_config *conf); void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *const argv[]); void fastd_reconfigure(fastd_context *ctx, fastd_config *conf); void fastd_config_release(fastd_context *ctx, fastd_config *conf); diff --git a/src/peer.c b/src/peer.c index 97c21ed..117d51a 100644 --- a/src/peer.c +++ b/src/peer.c @@ -259,6 +259,7 @@ fastd_peer_config* fastd_peer_config_new(fastd_context *ctx, fastd_config *conf) peer->name = NULL; peer->key = NULL; + peer->group = conf->peer_group; peer->protocol_config = NULL; peer->next = conf->peers; @@ -358,6 +359,9 @@ bool fastd_peer_claim_address(fastd_context *ctx, fastd_peer *new_peer, fastd_so } bool fastd_peer_config_equal(const fastd_peer_config *peer1, const fastd_peer_config *peer2) { + if (peer1->group != peer2->group) + return false; + if (!strequal(peer1->hostname, peer2->hostname)) return false; @@ -385,6 +389,21 @@ void fastd_peer_delete(fastd_context *ctx, fastd_peer *peer) { delete_peer(ctx, peer); } +static inline fastd_peer_group* find_peer_group(fastd_peer_group *group, const fastd_peer_group_config *config) { + if (group->conf == config) + return group; + + fastd_peer_group *child; + for (child = group->children; child; child = child->next) { + fastd_peer_group *ret = find_peer_group(child, config); + + if (ret) + return ret; + } + + return NULL; +} + fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *peer_conf) { fastd_peer *peer = malloc(sizeof(fastd_peer)); @@ -392,11 +411,12 @@ fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *peer_conf) { ctx->peers = peer; peer->config = peer_conf; + peer->group = find_peer_group(ctx->peer_group, peer_conf->group); peer->protocol_state = NULL; peer->sock = NULL; setup_peer(ctx, peer); - pr_verbose(ctx, "adding peer %P", peer); + pr_verbose(ctx, "adding peer %P (group `%s')", peer, peer->group->conf->name); return peer; } diff --git a/src/peer.h b/src/peer.h index 3e37230..1e2cad0 100644 --- a/src/peer.h +++ b/src/peer.h @@ -34,6 +34,7 @@ struct _fastd_peer { fastd_peer *next; const fastd_peer_config *config; + fastd_peer_group *group; fastd_socket *sock; fastd_peer_address address; @@ -65,6 +66,7 @@ struct _fastd_peer_config { fastd_peer_address address; bool dynamic_float; char *key; + const fastd_peer_group_config *group; fastd_protocol_peer_config *protocol_config; }; diff --git a/src/types.h b/src/types.h index 13236b6..830c5dc 100644 --- a/src/types.h +++ b/src/types.h @@ -46,6 +46,8 @@ typedef struct _fastd_buffer fastd_buffer; typedef union _fastd_peer_address fastd_peer_address; typedef struct _fastd_bind_address fastd_bind_address; typedef struct _fastd_socket fastd_socket; +typedef struct _fastd_peer_group_config fastd_peer_group_config; +typedef struct _fastd_peer_group fastd_peer_group; typedef struct _fastd_peer_config fastd_peer_config; typedef struct _fastd_eth_addr fastd_eth_addr; typedef struct _fastd_peer fastd_peer; -- cgit v1.2.3