summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.c68
-rw-r--r--src/config.l1
-rw-r--r--src/config.y13
-rw-r--r--src/fastd.c38
-rw-r--r--src/fastd.h27
-rw-r--r--src/peer.c22
-rw-r--r--src/peer.h2
-rw-r--r--src/types.h2
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 <addr4> TOK_ADDR4
%token <addr6> 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;