summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2014-08-24 01:00:45 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2014-08-24 01:00:45 +0200
commita04bcf247f4be7e3da4fe3895200f0b9709fc0bb (patch)
tree5e749b81799bb82a751ed632d91b801abe624008 /src
parentad4999488eadac3a10de99caf50b732af8b771b9 (diff)
downloadfastd-a04bcf247f4be7e3da4fe3895200f0b9709fc0bb.tar
fastd-a04bcf247f4be7e3da4fe3895200f0b9709fc0bb.zip
Merge peer config into peer structure
With this refactoring, the structure fastd_peer_config_t is merged into fastd_peer_t, and fastd_remote_config_t into fastd_remote_t. This also means we now create peers directly when reading their configurations, which significantly simplifies the whole reload process, and prepares for some future optimizations like a key hash table. Note: This commit is too big, but I couldn't come up with a nice way to split it into smaller pieces...
Diffstat (limited to 'src')
-rw-r--r--src/config.c156
-rw-r--r--src/config.h4
-rw-r--r--src/config.y87
-rw-r--r--src/fastd.c53
-rw-r--r--src/fastd.h39
-rw-r--r--src/log.c27
-rw-r--r--src/options.c6
-rw-r--r--src/peer.c257
-rw-r--r--src/peer.h72
-rw-r--r--src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c51
-rw-r--r--src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h12
-rw-r--r--src/protocols/ec25519_fhmqvc/handshake.c104
-rw-r--r--src/protocols/ec25519_fhmqvc/util.c20
-rw-r--r--src/receive.c2
-rw-r--r--src/resolve.c6
-rw-r--r--src/types.h4
16 files changed, 369 insertions, 531 deletions
diff --git a/src/config.c b/src/config.c
index 842e6cc..98f99a7 100644
--- a/src/config.c
+++ b/src/config.c
@@ -75,9 +75,7 @@ static void default_config(void) {
/** Handles the configuration of a handshake protocol */
void fastd_config_protocol(const char *name) {
- if (!strcmp(name, "ec25519-fhmqvc"))
- conf.protocol = &fastd_protocol_ec25519_fhmqvc;
- else
+ if (strcmp(name, conf.protocol->name))
exit_error("config error: protocol `%s' not supported", name);
}
@@ -189,7 +187,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(fastd_peer_config_t **peers, fastd_peer_group_t *group, const char *dir) {
+static void read_peer_dir(fastd_peer_group_t *group, const char *dir) {
DIR *dirh = opendir(".");
if (dirh) {
@@ -221,18 +219,16 @@ static void read_peer_dir(fastd_peer_config_t **peers, fastd_peer_group_t *group
continue;
}
- fastd_peer_config_t *peer = fastd_peer_config_new(group);
+ fastd_peer_t *peer = fastd_new0(fastd_peer_t);
peer->name = fastd_strdup(result->d_name);
peer->config_source_dir = dir;
- 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_free(peer);
+ if (!fastd_config_read(result->d_name, group, peer, 0)) {
+ fastd_peer_free(peer);
+ continue;
}
+
+ fastd_peer_add(peer);
}
if (closedir(dirh) < 0)
@@ -245,13 +241,13 @@ static void read_peer_dir(fastd_peer_config_t **peers, fastd_peer_group_t *group
}
/** Reads all configured peer directories for a peer grup */
-static void read_peer_dirs(fastd_peer_config_t **peers, fastd_peer_group_t *group) {
+static void read_peer_dirs(fastd_peer_group_t *group) {
char *oldcwd = get_current_dir_name();
fastd_string_stack_t *dir;
for (dir = group->peer_dirs; dir; dir = dir->next) {
if (!chdir(dir->str))
- read_peer_dir(peers, group, dir->str);
+ read_peer_dir(group, dir->str);
else
pr_error("change from directory `%s' to `%s' failed: %s", oldcwd, dir->str, strerror(errno));
}
@@ -282,7 +278,7 @@ void fastd_config_add_peer_dir(fastd_peer_group_t *group, const char *dir) {
}
/** Reads and processes a configuration file */
-bool fastd_config_read(const char *filename, fastd_peer_group_t *peer_group, fastd_peer_config_t *peer_config, int depth) {
+bool fastd_config_read(const char *filename, fastd_peer_group_t *peer_group, fastd_peer_t *peer, int depth) {
if (depth >= MAX_CONFIG_DEPTH)
exit_error("maximum config include depth exceeded");
@@ -327,15 +323,18 @@ bool fastd_config_read(const char *filename, fastd_peer_group_t *peer_group, fas
YYLTYPE loc = {1, 0, 1, 0};
fastd_parser_state_t state = {
.peer_group = peer_group,
- .peer = peer_config,
+ .peer = peer,
.filename = filename,
.depth = depth+1,
};
- if (peer_config)
+ if (peer) {
token = START_PEER_CONFIG;
- else
+ peer->group = peer_group;
+ }
+ else {
token = peer_group->parent ? START_PEER_GROUP_CONFIG : START_CONFIG;
+ }
int parse_ret = fastd_config_push_parse(ps, token, &token_val, &loc, &state);
@@ -377,17 +376,6 @@ bool fastd_config_read(const char *filename, fastd_peer_group_t *peer_group, fas
return ret;
}
-/** Gathers some information about the configured peers */
-static void assess_peers(void) {
- conf.has_floating = false;
-
- fastd_peer_config_t *peer;
- for (peer = ctx.peer_configs; peer; peer = peer->next) {
- if (fastd_peer_config_is_floating(peer))
- conf.has_floating = true;
- }
-}
-
/** Loads information about the configured user and group */
static void configure_user(void) {
conf.uid = getuid();
@@ -531,7 +519,7 @@ static void config_check_base(void) {
if (conf.peer_group->children)
exit_error("config error: in TUN mode peer groups can't be used");
- if (ctx.peer_configs && ctx.peer_configs->next)
+ if (VECTOR_LEN(ctx.peers) != 1)
exit_error("config error: in TUN mode exactly one peer must be configured");
}
@@ -551,11 +539,11 @@ void fastd_config_check(void) {
config_check_base();
if (conf.mode == MODE_TUN) {
- if (!ctx.peer_configs)
+ if (!VECTOR_LEN(ctx.peers))
exit_error("config error: in TUN mode exactly one peer must be configured");
}
- if (!ctx.peer_configs && !has_peer_group_peer_dirs(conf.peer_group))
+ if (!VECTOR_LEN(ctx.peers) && !has_peer_group_peer_dirs(conf.peer_group))
exit_error("config error: neither fixed peers nor peer dirs have been configured");
if (!conf.method_list) {
@@ -571,98 +559,74 @@ void fastd_config_check(void) {
void fastd_config_verify(void) {
config_check_base();
configure_methods();
-
- fastd_peer_config_t *peer;
- for (peer = ctx.peer_configs; peer; peer = peer->next)
- conf.protocol->peer_verify(peer);
}
/** 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);
+static void peer_dirs_read_peer_group(fastd_peer_group_t *group) {
+ read_peer_dirs(group);
fastd_peer_group_t *child;
for (child = group->children; child; child = child->next)
- peer_dirs_read_peer_group(peers, child);
+ peer_dirs_read_peer_group(child);
}
-/** Deletes peer configs that have disappeared from a peer dir on reconfiguration */
-static void peer_dirs_handle_old_peers(fastd_peer_config_t **old_peers, fastd_peer_config_t **new_peers) {
- fastd_peer_config_t **peer, **next, **new_peer, **new_next;
- for (peer = old_peers; *peer; peer = next) {
- next = &(*peer)->next;
-
- /* don't touch statically configured peers */
- if (!(*peer)->config_source_dir)
- continue;
-
- /* search for each peer in the list of new peers */
- for (new_peer = new_peers; *new_peer; new_peer = new_next) {
- new_next = &(*new_peer)->next;
+/** Initializes the configured peers */
+static void configure_peers(void) {
+ ctx.has_floating = false;
- if (((*peer)->config_source_dir == (*new_peer)->config_source_dir) && strequal((*peer)->name, (*new_peer)->name)) {
- if (fastd_peer_config_equal(*peer, *new_peer)) {
- pr_verbose("peer `%s' unchanged", (*peer)->name);
+ ssize_t i;
+ for (i = VECTOR_LEN(ctx.peers)-1; i >= 0; i--) {
+ fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
- fastd_peer_config_t *free_peer = *new_peer;
- *new_peer = *new_next;
- fastd_peer_config_free(free_peer);
- peer = NULL;
- }
- else {
- pr_verbose("peer `%s' changed, resetting", (*peer)->name);
- new_peer = NULL;
- }
-
- break;
- }
+ if (peer->config_state == CONFIG_STATIC) {
+ /* The peer hasn't been touched since the last run of init_peers(), so its definition must have disappeared */
+ fastd_peer_delete(peer);
+ continue;
}
- /* no new peer was found, or the old one has changed */
- if (peer && (!new_peer || !*new_peer)) {
- pr_verbose("removing peer `%s'", (*peer)->name);
+ if (fastd_peer_is_dynamic(peer))
+ continue;
- fastd_peer_config_t *free_peer = *peer;
- *peer = *next;
- next = peer;
+ if (peer->config_state != CONFIG_DISABLED && !conf.protocol->check_peer(peer))
+ peer->config_state = CONFIG_DISABLED;
- fastd_peer_config_purge(free_peer);
+ if (peer->config_state == CONFIG_DISABLED) {
+ fastd_peer_reset(peer);
+ continue;
}
- }
-}
-/** Adds new peer configs on reconfiguration */
-static void peer_dirs_handle_new_peers(fastd_peer_config_t **peers, fastd_peer_config_t *new_peers) {
- fastd_peer_config_t *peer;
- for (peer = new_peers; peer; peer = peer->next) {
- if (peer->next)
- continue;
+ if (fastd_peer_is_floating(peer))
+ ctx.has_floating = true;
- peer->next = *peers;
- *peers = new_peers;
- return;
+ peer->config_state = CONFIG_STATIC;
+
+ if (!fastd_peer_is_established(peer))
+ fastd_peer_reset(peer);
}
}
/** Refreshes the peer configurations from the configured peer dirs */
void fastd_config_load_peer_dirs(void) {
- fastd_peer_config_t *new_peers = NULL;
- peer_dirs_read_peer_group(&new_peers, conf.peer_group);
+ size_t i;
+ for (i = 0; i < VECTOR_LEN(ctx.peers); i++) {
+ fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
- peer_dirs_handle_old_peers(&ctx.peer_configs, &new_peers);
- peer_dirs_handle_new_peers(&ctx.peer_configs, new_peers);
+ if (fastd_peer_is_dynamic(peer))
+ continue;
- assess_peers();
+ /* Reset all peers' config states */
+ if (!peer->config_source_dir)
+ peer->config_state = CONFIG_NEW;
+ else if (peer->config_state == CONFIG_DISABLED)
+ peer->config_state = CONFIG_STATIC;
+ }
+
+ peer_dirs_read_peer_group(conf.peer_group);
+ configure_peers();
}
/** Frees all resources used by the global configuration */
void fastd_config_release(void) {
- while (ctx.peer_configs) {
- fastd_peer_config_t *peer = ctx.peer_configs, *next = peer->next;
- fastd_peer_config_free(peer);
- ctx.peer_configs = next;
- }
-
while (conf.bind_addrs) {
fastd_bind_address_t *next = conf.bind_addrs->next;
free(conf.bind_addrs->bindtodev);
diff --git a/src/config.h b/src/config.h
index f4e1de5..b076266 100644
--- a/src/config.h
+++ b/src/config.h
@@ -38,7 +38,7 @@
/** 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 */
+ fastd_peer_t *peer; /**< The peer currently being loaded */
const char *const filename; /**< The filename of the currently parsed file */
const int depth; /**< The include depth */
@@ -54,7 +54,7 @@ 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);
+bool fastd_config_read(const char *filename, fastd_peer_group_t *peer_group, fastd_peer_t *peer, 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);
diff --git a/src/config.y b/src/config.y
index 9b5d13d..44fc59f 100644
--- a/src/config.y
+++ b/src/config.y
@@ -203,7 +203,7 @@ statement: peer_group_statement
;
peer_group_statement:
- TOK_PEER peer '{' peer_conf '}'
+ TOK_PEER peer '{' peer_conf '}' peer_after
| TOK_PEER TOK_GROUP peer_group '{' peer_group_config '}' peer_group_after
| TOK_PEER TOK_LIMIT peer_limit ';'
| TOK_INCLUDE include ';'
@@ -422,15 +422,17 @@ on_verify: sync_def_async TOK_STRING {
;
peer: TOK_STRING {
- fastd_peer_config_t *peer = fastd_peer_config_new(state->peer_group);
- peer->name = fastd_strdup($1->str);
- peer->next = ctx.peer_configs;
-
- ctx.peer_configs = peer;
- state->peer = peer;
+ state->peer = fastd_new0(fastd_peer_t);
+ state->peer->name = fastd_strdup($1->str);
+ state->peer->group = state->peer_group;
}
;
+peer_after: {
+ if (!fastd_peer_add(state->peer))
+ YYERROR;
+ }
+
peer_conf: peer_conf peer_statement
|
;
@@ -442,59 +444,51 @@ peer_statement: TOK_REMOTE peer_remote ';'
;
peer_remote: TOK_ADDR4 port {
- fastd_remote_config_t **remote = &state->peer->remotes;
- while (*remote)
- remote = &(*remote)->next;
+ fastd_remote_t remote = {};
- *remote = fastd_new0(fastd_remote_config_t);
+ remote.address.in.sin_family = AF_INET;
+ remote.address.in.sin_addr = $1;
+ remote.address.in.sin_port = htons($2);
+ fastd_peer_address_simplify(&remote.address);
- (*remote)->address.in.sin_family = AF_INET;
- (*remote)->address.in.sin_addr = $1;
- (*remote)->address.in.sin_port = htons($2);
- fastd_peer_address_simplify(&(*remote)->address);
+ VECTOR_ADD(state->peer->remotes, remote);
}
| TOK_ADDR6 port {
- fastd_remote_config_t **remote = &state->peer->remotes;
- while (*remote)
- remote = &(*remote)->next;
+ fastd_remote_t remote = {};
- *remote = fastd_new0(fastd_remote_config_t);
+ remote.address.in6.sin6_family = AF_INET6;
+ remote.address.in6.sin6_addr = $1;
+ remote.address.in6.sin6_port = htons($2);
+ fastd_peer_address_simplify(&remote.address);
- (*remote)->address.in6.sin6_family = AF_INET6;
- (*remote)->address.in6.sin6_addr = $1;
- (*remote)->address.in6.sin6_port = htons($2);
- fastd_peer_address_simplify(&(*remote)->address);
+ VECTOR_ADD(state->peer->remotes, remote);
}
| TOK_ADDR6_SCOPED port {
char addrbuf[INET6_ADDRSTRLEN];
size_t addrlen;
- fastd_remote_config_t **remote = &state->peer->remotes;
- while (*remote)
- remote = &(*remote)->next;
inet_ntop(AF_INET6, &$1.addr, addrbuf, sizeof(addrbuf));
addrlen = strlen(addrbuf);
- *remote = fastd_new0(fastd_remote_config_t);
+ fastd_remote_t remote = {};
+ remote.hostname = fastd_alloc(addrlen + strlen($1.ifname) + 2);
+ memcpy(remote.hostname, addrbuf, addrlen);
+ remote.hostname[addrlen] = '%';
+ strcpy(remote.hostname+addrlen+1, $1.ifname);
- (*remote)->hostname = fastd_alloc(addrlen + strlen($1.ifname) + 2);
- memcpy((*remote)->hostname, addrbuf, addrlen);
- (*remote)->hostname[addrlen] = '%';
- strcpy((*remote)->hostname+addrlen+1, $1.ifname);
+ remote.address.sa.sa_family = AF_INET6;
+ remote.address.in.sin_port = htons($2);
- (*remote)->address.sa.sa_family = AF_INET6;
- (*remote)->address.in.sin_port = htons($2);
+ VECTOR_ADD(state->peer->remotes, remote);
}
| maybe_af TOK_STRING port {
- fastd_remote_config_t **remote = &state->peer->remotes;
- while (*remote)
- remote = &(*remote)->next;
+ fastd_remote_t remote = {};
- *remote = fastd_new0(fastd_remote_config_t);
+ remote.hostname = fastd_strdup($2->str);
+ remote.address.sa.sa_family = $1;
+ remote.address.in.sin_port = htons($3);
- (*remote)->hostname = fastd_strdup($2->str);
- (*remote)->address.sa.sa_family = $1;
- (*remote)->address.in.sin_port = htons($3);
+ VECTOR_ADD(state->peer->remotes, remote);
}
;
@@ -504,7 +498,8 @@ peer_float: boolean {
;
peer_key: TOK_STRING {
- free(state->peer->key); state->peer->key = fastd_strdup($1->str);
+ free(state->peer->key);
+ state->peer->key = conf.protocol->read_key($1->str);
}
;
@@ -541,14 +536,14 @@ forward: boolean { conf.forward = $1; }
include: TOK_PEER TOK_STRING maybe_as {
- fastd_peer_config_t *peer = fastd_peer_config_new(state->peer_group);
- if ($3)
- peer->name = fastd_strdup($3->str);
+ fastd_peer_t *peer = fastd_new0(fastd_peer_t);
+ peer->name = fastd_strdup(fastd_string_stack_get($3));
+
if (!fastd_config_read($2->str, state->peer_group, peer, state->depth))
YYERROR;
- peer->next = ctx.peer_configs;
- ctx.peer_configs = peer;
+ if (!fastd_peer_add(peer))
+ YYERROR;
}
| TOK_PEERS TOK_FROM TOK_STRING {
fastd_config_add_peer_dir(state->peer_group, $3->str);
diff --git a/src/fastd.c b/src/fastd.c
index 589a293..0f74984 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -199,51 +199,6 @@ static inline void on_post_down(void) {
fastd_shell_command_exec(&conf.on_post_down, NULL);
}
-/**
- Initializes the peers
-
- Is called after each reconfiguration to remove old peers and add new ones.
-*/
-static void init_peers(void) {
- fastd_peer_config_t *peer_conf;
- for (peer_conf = ctx.peer_configs; peer_conf; peer_conf = peer_conf->next) {
- conf.protocol->peer_configure(peer_conf);
-
- if (peer_conf->config_state == CONFIG_NEW)
- fastd_peer_add(peer_conf);
- }
-
- size_t i;
- for (i = 0; i < VECTOR_LEN(ctx.peers);) {
- fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
-
- if (fastd_peer_is_dynamic(peer)) {
- if (!conf.protocol->peer_check_dynamic(peer)) {
- fastd_peer_delete(peer);
- continue;
- }
- }
- else {
- fastd_peer_config_state_t state = conf.protocol->peer_check(peer->config) ? CONFIG_STATIC : CONFIG_DISABLED;
- if (state != peer->config->config_state) {
- if (peer->config->config_state != CONFIG_NEW)
- pr_info("peer %P is %s now.", peer, (state == CONFIG_DISABLED) ? "disabled" : "enabled");
-
- peer->config->config_state = state;
- fastd_peer_reset(peer);
- }
- }
-
- i++;
- }
-}
-
-/** Removes all peers */
-static void delete_peers(void) {
- while (VECTOR_LEN(ctx.peers))
- fastd_peer_delete(VECTOR_INDEX(ctx.peers, VECTOR_LEN(ctx.peers)-1));
-}
-
/** Dumps statistics and the list of known peers to the logs */
static void dump_state(void) {
pr_info("TX stats: %U packet(s), %U byte(s); dropped: %U packet(s), %U byte(s); error: %U packet(s), %U byte(s)",
@@ -584,7 +539,6 @@ static inline void init(int argc, char *argv[]) {
set_user();
fastd_config_load_peer_dirs();
- init_peers();
}
@@ -629,7 +583,6 @@ static inline void handle_signals(void) {
pr_info("reconfigure triggered");
fastd_config_load_peer_dirs();
- init_peers();
}
if (dump) {
@@ -653,6 +606,12 @@ static inline void run(void) {
handle_signals();
}
+/** Removes all peers */
+static void delete_peers(void) {
+ while (VECTOR_LEN(ctx.peers))
+ fastd_peer_delete(VECTOR_INDEX(ctx.peers, VECTOR_LEN(ctx.peers)-1));
+}
+
/**
Performs cleanup of resources used by fastd
diff --git a/src/fastd.h b/src/fastd.h
index 9b1dc29..ea30045 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -68,20 +68,7 @@ struct fastd_protocol {
const char *name;
/** Performs one-time initialization tasks for the protocol */
- fastd_protocol_config_t* (*init)(void);
-
- /** Does some basic checks for the validity of a peer configuration */
- void (*peer_verify)(fastd_peer_config_t *peer_conf);
-
- /** Initializes protocol-specific parts of a peer configuration */
- void (*peer_configure)(fastd_peer_config_t *peer_conf);
-
- /** Checks if a peer configuration is valid and a connection may be established */
- bool (*peer_check)(fastd_peer_config_t *peer_conf);
-
- /** Checks if a dynamic peer is valid and a connection may be established */
- bool (*peer_check_dynamic)(fastd_peer_t *peer);
-
+ fastd_protocol_config_t * (*init)(void);
/** Sends a handshake to the given peer */
void (*handshake_init)(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer);
@@ -101,16 +88,27 @@ struct fastd_protocol {
/** Sends a payload data packet to the given peer */
void (*send)(fastd_peer_t *peer, fastd_buffer_t buffer);
+
/** Initializes the protocol state for a peer */
void (*init_peer_state)(fastd_peer_t *peer);
/** Resets the protocol state for a peer (resets active sessions etc.) */
void (*reset_peer_state)(fastd_peer_t *peer);
-
/** Frees the protocol state for a peer */
void (*free_peer_state)(fastd_peer_t *peer);
+
+ /** Initializes protocol-specific parts of a peer configuration */
+ fastd_protocol_key_t * (*read_key)(const char *key);
+
+ /** Checks a peer after reading its configuration */
+ bool (*check_peer)(const fastd_peer_t *peer);
+
+ /** Searches a peer identified by a specific key */
+ fastd_peer_t * (*find_peer)(const fastd_protocol_key_t *key);
+
+
/** Generates a new keypair and outputs it */
void (*generate_key)(void);
@@ -206,8 +204,6 @@ struct fastd_config {
fastd_peer_group_t *peer_group; /**< The root peer group configuration */
- bool has_floating; /**< Specifies if any of the configured peers have floating remotes */
-
fastd_protocol_config_t *protocol_config; /**< The protocol-specific configuration */
fastd_shell_command_t on_pre_up; /**< The command to execute before the initialization of the tunnel interface */
@@ -241,8 +237,6 @@ struct fastd_context {
struct timespec now; /**< The current monotonous timestamp */
- fastd_peer_config_t *peer_configs; /**< The configured peers */
-
uint64_t next_peer_id; /**< An monotonously increasing ID peers are identified with in some components */
VECTOR(fastd_peer_t*) peers; /**< The currectly active peers */
@@ -256,6 +250,8 @@ struct fastd_context {
VECTOR(struct pollfd) pollfds; /**< The vector of pollfds for all file descriptors */
#endif
+ bool has_floating; /**< Specifies if any of the configured peers have floating remotes */
+
uint32_t peer_addr_ht_seed; /**< The hash seed used for peer_addr_ht */
VECTOR(fastd_peer_t*) *peer_addr_ht; /**< An array of hash buckets for the peer hash table */
@@ -425,6 +421,11 @@ static inline fastd_string_stack_t* fastd_string_stack_push(fastd_string_stack_t
return ret;
}
+/** Gets the head of string stack (or NULL if the stack is NULL) */
+static inline const char * fastd_string_stack_get(const fastd_string_stack_t *stack) {
+ return stack ? stack->str : NULL;
+}
+
/** Frees a whole string stack */
static inline void fastd_string_stack_free(fastd_string_stack_t *str) {
while (str) {
diff --git a/src/log.c b/src/log.c
index 122b322..f6b6d2d 100644
--- a/src/log.c
+++ b/src/log.c
@@ -93,16 +93,18 @@ static size_t snprint_peer_address(char *buffer, size_t size, const fastd_peer_a
/** Creates a string representation of a peer */
static size_t snprint_peer_str(char *buffer, size_t size, const fastd_peer_t *peer) {
- if (peer->config->name) {
- return snprintf_safe(buffer, size, "<%s>", peer->config->name);
- }
- else {
- char buf[65];
- if (conf.protocol->describe_peer(peer, buf, sizeof(buf)))
- return snprintf_safe(buffer, size, "{%s}", buf);
- else
- return snprintf_safe(buffer, size, "(null)");
+ if (peer) {
+ if (peer->name) {
+ return snprintf_safe(buffer, size, "<%s>", peer->name);
+ }
+ else {
+ char buf[65];
+ if (conf.protocol->describe_peer(peer, buf, sizeof(buf)))
+ return snprintf_safe(buffer, size, "{%s}", buf);
+ }
}
+
+ return snprintf_safe(buffer, size, "(null)");
}
/** vsnprintf-like function using different conversion specifiers */
@@ -166,12 +168,7 @@ static int fastd_vsnprintf(char *buffer, size_t size, const char *format, va_lis
break;
case 'P':
- p = va_arg(ap, const fastd_peer_t*);
-
- if (p)
- buffer += snprint_peer_str(buffer, buffer_end-buffer, (const fastd_peer_t*)p);
- else
- buffer += snprintf_safe(buffer, buffer_end-buffer, "(null)");
+ buffer += snprint_peer_str(buffer, buffer_end-buffer, va_arg(ap, const fastd_peer_t*));
break;
case 'I':
diff --git a/src/options.c b/src/options.c
index e3cf78a..1e7764d 100644
--- a/src/options.c
+++ b/src/options.c
@@ -117,14 +117,12 @@ static void option_config(const char *arg) {
/** Handles the --config-peer option */
static void option_config_peer(const char *arg) {
- fastd_peer_config_t *peer = fastd_peer_config_new(conf.peer_group);
+ fastd_peer_t *peer = fastd_new0(fastd_peer_t);
if(!fastd_config_read(arg, conf.peer_group, peer, 0))
exit(1);
- peer->next = ctx.peer_configs;
- ctx.peer_configs = peer;
-
+ fastd_peer_add(peer);
}
/** Handles the --config-peer-dir option */
diff --git a/src/peer.c b/src/peer.c
index 1ae7b3c..34f7bf7 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -42,7 +42,7 @@ void fastd_peer_set_shell_env(fastd_shell_env_t *env, const fastd_peer_t *peer,
/* both INET6_ADDRSTRLEN and IFNAMESIZE already include space for the zero termination, so there is no need to add space for the '%' here. */
char buf[INET6_ADDRSTRLEN+IF_NAMESIZE];
- fastd_shell_env_set(env, "PEER_NAME", peer ? peer->config->name : NULL);
+ fastd_shell_env_set(env, "PEER_NAME", peer ? peer->name : NULL);
switch(local_addr ? local_addr->sa.sa_family : AF_UNSPEC) {
case AF_INET:
@@ -293,7 +293,7 @@ static inline bool is_group_in(const fastd_peer_group_t *group1, const fastd_pee
/** Checks if a peer lies in a peer group */
static bool is_peer_in_group(const fastd_peer_t *peer, const fastd_peer_group_t *group) {
- return is_group_in(fastd_peer_get_group(peer), group);
+ return is_group_in(peer->group, group);
}
/**
@@ -304,11 +304,6 @@ static bool is_peer_in_group(const fastd_peer_t *peer, const fastd_peer_group_t
After a call to reset_peer a peer must be deleted by delete_peer or re-initialized by setup_peer.
*/
static void reset_peer(fastd_peer_t *peer) {
- if (peer->state == STATE_INACTIVE)
- return;
-
- pr_debug("resetting peer %P", peer);
-
if (fastd_peer_is_established(peer)) {
on_disestablish(peer);
pr_info("connection with %P disestablished.", peer);
@@ -348,7 +343,7 @@ static void reset_peer(fastd_peer_t *peer) {
*/
static void init_handshake(fastd_peer_t *peer) {
unsigned delay = 0;
- if (has_group_config_constraints(fastd_peer_get_group(peer)))
+ if (has_group_config_constraints(peer->group))
delay = fastd_rand(0, 3000);
peer->state = STATE_HANDSHAKE;
@@ -371,7 +366,7 @@ void fastd_peer_handle_resolve(fastd_peer_t *peer, fastd_remote_t *remote, size_
/** Checks if a remote contains a hostname instead of a static IP address */
static inline bool has_remote_hostname(const fastd_remote_t *remote) {
- return remote->config->hostname;
+ return remote->hostname;
}
/** Initializes a peer */
@@ -395,13 +390,15 @@ static void setup_peer(fastd_peer_t *peer) {
peer->establish_handshake_timeout = ctx.now;
+#ifdef WITH_DYNAMIC_PEERS
+ peer->verify_timeout = ctx.now;
+ peer->verify_valid_timeout = ctx.now;
+#endif
+
if (!fastd_peer_is_enabled(peer))
/* Keep the peer in STATE_INACTIVE */
return;
- if (!peer->protocol_state)
- conf.protocol->init_peer_state(peer);
-
fastd_remote_t *next_remote = fastd_peer_get_next_remote(peer);
if (next_remote) {
next_remote->current_address = 0;
@@ -420,68 +417,42 @@ static void setup_peer(fastd_peer_t *peer) {
}
}
-/** Frees a peer */
-static void delete_peer(fastd_peer_t *peer) {
- pr_debug("deleting peer %P", peer);
-
- size_t i = peer_index(peer);
- VECTOR_DELETE(ctx.peers, i);
- fastd_poll_delete_peer(i);
-
- fastd_peer_hashtable_remove(peer);
+/**
+ Frees a peer
- conf.protocol->free_peer_state(peer);
+ If the peer has already been added to the peer list,
+ use fastd_peer_delete() instead.
+*/
+void fastd_peer_free(fastd_peer_t *peer) {
+ free(peer->key);
- if (fastd_peer_is_dynamic(peer))
- fastd_peer_config_free(peer->config);
+ size_t i;
+ for (i = 0; i < VECTOR_LEN(peer->remotes); i++) {
+ fastd_remote_t *remote = &VECTOR_INDEX(peer->remotes, i);
- for (i = 0; i < VECTOR_LEN(peer->remotes); i++)
- free(VECTOR_INDEX(peer->remotes, i).addresses);
+ free(remote->addresses);
+ free(remote->hostname);
+ }
VECTOR_FREE(peer->remotes);
+ free(peer->name);
free(peer);
}
+/** Deletes a peer */
+static void delete_peer(fastd_peer_t *peer) {
+ pr_verbose("deleting peer %P", peer);
-/** Allocates a new peer config */
-fastd_peer_config_t* fastd_peer_config_new(fastd_peer_group_t *group) {
- fastd_peer_config_t *peer = fastd_new0(fastd_peer_config_t);
- peer->group = group;
-
- return peer;
-}
-
-/** Frees a peer config (which must not be referenced anywhere) */
-void fastd_peer_config_free(fastd_peer_config_t *peer) {
- while (peer->remotes) {
- fastd_remote_config_t *remote = peer->remotes;
- peer->remotes = remote->next;
+ size_t i = peer_index(peer);
+ VECTOR_DELETE(ctx.peers, i);
+ fastd_poll_delete_peer(i);
- free(remote->hostname);
- free(remote);
- }
+ conf.protocol->free_peer_state(peer);
- free(peer->name);
- free(peer->key);
- free(peer->protocol_config);
- free(peer);
+ fastd_peer_free(peer);
}
-/** 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;
- for (i = 0; i < VECTOR_LEN(ctx.peers); i++) {
- fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
-
- if (peer->config == config) {
- fastd_peer_delete(peer);
- break;
- }
- }
-
- fastd_peer_config_free(config);
-}
/** Checks if two fastd_peer_address_t are equal */
bool fastd_peer_address_equal(const fastd_peer_address_t *addr1, const fastd_peer_address_t *addr2) {
@@ -556,8 +527,10 @@ bool fastd_peer_owns_address(const fastd_peer_t *peer, const fastd_peer_address_
if (fastd_peer_is_floating(peer))
return false;
- fastd_remote_config_t *remote;
- for (remote = peer->config->remotes; remote; remote = remote->next) {
+ size_t i;
+ for (i = 0; i < VECTOR_LEN(peer->remotes); i++) {
+ fastd_remote_t *remote = &VECTOR_INDEX(peer->remotes, i);
+
if (remote->hostname)
continue;
@@ -643,43 +616,13 @@ bool fastd_peer_claim_address(fastd_peer_t *new_peer, fastd_socket_t *sock, cons
return true;
}
-/** Checks if two remote configs are equivalent */
-static bool remote_configs_equal(const fastd_remote_config_t *remote1, const fastd_remote_config_t *remote2) {
- if (!remote1 && !remote2)
- return true;
-
- if (!remote1 || !remote2)
- return false;
-
- if (!fastd_peer_address_equal(&remote1->address, &remote2->address))
- return false;
-
- if (!strequal(remote1->hostname, remote2->hostname))
- return false;
-
- return remote_configs_equal(remote1->next, remote2->next);
-}
-
-/** Checks if two peer configs are equivalent */
-bool fastd_peer_config_equal(const fastd_peer_config_t *peer1, const fastd_peer_config_t *peer2) {
- if (peer1->group != peer2->group)
- return false;
-
- if(peer1->floating != peer2->floating)
- return false;
-
- if (!remote_configs_equal(peer1->remotes, peer2->remotes))
- return false;
-
- if (!strequal(peer1->key, peer2->key))
- return false;
-
- return true;
-}
-
/** Resets and re-initializes a peer */
void fastd_peer_reset(fastd_peer_t *peer) {
- reset_peer(peer);
+ if (peer->state != STATE_INACTIVE) {
+ pr_debug("resetting peer %P", peer);
+ reset_peer(peer);
+ }
+
setup_peer(peer);
}
@@ -709,7 +652,7 @@ bool fastd_peer_may_connect(fastd_peer_t *peer) {
const fastd_peer_group_t *group;
- for (group = fastd_peer_get_group(peer); group; group = group->parent) {
+ for (group = peer->group; group; group = group->parent) {
if (group->max_connections < 0)
continue;
@@ -720,53 +663,111 @@ bool fastd_peer_may_connect(fastd_peer_t *peer) {
return true;
}
-/** Create a new peer */
-fastd_peer_t* fastd_peer_add(fastd_peer_config_t *peer_conf) {
- fastd_peer_t *peer = fastd_new0(fastd_peer_t);
+/** Checks if two peer configurations are equivalent (exept for the name) */
+static inline bool peer_configs_equal(const fastd_peer_t *peer1, const fastd_peer_t *peer2) {
+ if (peer1->group != peer2->group)
+ return false;
- peer->id = ctx.next_peer_id++;
+ if (peer1->floating != peer2->floating)
+ return false;
- if (peer_conf) {
- peer->config = peer_conf;
+ if (VECTOR_LEN(peer1->remotes) != VECTOR_LEN(peer2->remotes))
+ return false;
- fastd_remote_config_t *remote_config;
- for (remote_config = peer_conf->remotes; remote_config; remote_config = remote_config->next) {
- fastd_remote_t remote = {.config = remote_config};
+ size_t i;
+ for (i = 0; i < VECTOR_LEN(peer1->remotes); i++) {
+ const fastd_remote_t *remote1 = &VECTOR_INDEX(peer1->remotes, i), *remote2 = &VECTOR_INDEX(peer2->remotes, i);
- if (!remote_config->hostname) {
- remote.n_addresses = 1;
- remote.addresses = fastd_new(fastd_peer_address_t);
- remote.addresses[0] = remote_config->address;
- }
+ if (!fastd_peer_address_equal(&remote1->address, &remote2->address))
+ return false;
- VECTOR_ADD(peer->remotes, remote);
- }
+ if (!strequal(remote1->hostname, remote2->hostname))
+ return false;
+ }
- pr_verbose("adding peer %P (group `%s')", peer, fastd_peer_get_group(peer)->name);
+ return true;
+}
+
+/** Replaces a peer with a new configuration */
+static void replace_peer(fastd_peer_t *old, fastd_peer_t *new) {
+ reset_peer(old);
+
+ new->id = old->id;
+
+ new->protocol_state = old->protocol_state;
+ old->protocol_state = NULL;
+
+ fastd_peer_t tmp = *old;
+ *old = *new;
+ *new = tmp;
+
+ fastd_peer_free(new);
+}
+
+/** Adds a new peer */
+bool fastd_peer_add(fastd_peer_t *peer) {
+ if (!peer->key) {
+ pr_warn("no valid key configured for peer %P", peer);
+ goto error;
}
- else {
-#ifdef WITH_DYNAMIC_PEERS
- if (!fastd_shell_command_isset(&conf.on_verify))
- exit_bug("tried to add dynamic peer without on-verify command");
- peer->config = fastd_peer_config_new(conf.peer_group);
- peer->config->config_state = CONFIG_DYNAMIC;
+ fastd_peer_t *other = conf.protocol->find_peer(peer->key);
+ if (other) {
+ if (peer->config_state != CONFIG_NEW)
+ exit_bug("tried to replace with active peer");
+
+ switch (other->config_state) {
+ case CONFIG_NEW:
+ case CONFIG_DISABLED:
+ pr_warn("duplicate key used by peers %P and %P, disabling both", peer, other);
+ other->config_state = CONFIG_DISABLED;
+ goto error;
+
+ case CONFIG_STATIC:
+ if (!strequal(other->name, peer->name))
+ pr_verbose("peer %P has been renamed to %P", other, peer);
+
+ if (peer_configs_equal(other, peer)) {
+ free(other->name);
+ other->name = peer->name;
+ peer->name = NULL;
- peer->verify_timeout = ctx.now;
- peer->verify_valid_timeout = ctx.now;
+ fastd_peer_free(peer);
- pr_debug("adding dynamic peer");
-#else
- exit_bug("dynamic peers not supported");
+ pr_verbose("peer %P is unchanged", other);
+ other->config_state = CONFIG_NEW;
+
+ return true;
+ }
+
+ pr_verbose("peer %P has changed, resetting...", peer);
+
+ replace_peer(other, peer);
+ return true;
+
+#ifdef WITH_DYNAMIC_PEERS
+ case CONFIG_DYNAMIC:
+ pr_verbose("dynamic peer %P is now configured as %P", other, peer);
+ replace_peer(other, peer);
+ return true;
#endif
+ }
}
- setup_peer(peer);
+ peer->id = ctx.next_peer_id++;
VECTOR_ADD(ctx.peers, peer);
fastd_poll_add_peer();
- return peer;
+ conf.protocol->init_peer_state(peer);
+
+ pr_verbose("adding peer %P", peer);
+
+ return true;
+
+ error:
+ fastd_peer_free(peer);
+ return false;
}
/** Prints a debug message when no handshake could be sent because the current remote didn't resolve successfully */
diff --git a/src/peer.h b/src/peer.h
index f1187d8..3ddead4 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -46,7 +46,7 @@ typedef enum fastd_peer_state {
/** The config state of a peer */
typedef enum fastd_peer_config_state {
- CONFIG_NEW = 0, /**< The peer is configured statically, but has been not been enabled yet */
+ CONFIG_NEW = 0, /**< The peer is configured statically, but has not been enabled yet */
CONFIG_STATIC, /**< The peer is configured statically */
CONFIG_DISABLED, /**< The peer is configured statically, but has been disabled because of a configuration error */
#ifdef WITH_DYNAMIC_PEERS
@@ -54,11 +54,11 @@ typedef enum fastd_peer_config_state {
#endif
} fastd_peer_config_state_t;
-/** Dynamic state of a peer */
+/** A peer's configuration and state */
struct fastd_peer {
uint64_t id; /**< A unique ID assigned to each peer */
- fastd_peer_config_t *config; /**< The peer's fastd_peer_config_t */
+ char *name; /**< The peer's name */
/** The socket used by the peer. This can either be a common bound socket or a
dynamic, unbound socket that is used exclusively by this peer */
@@ -66,12 +66,17 @@ struct fastd_peer {
fastd_peer_address_t local_address; /**< The local address used to communicate with this peer */
fastd_peer_address_t address; /**< The peers current address */
+ fastd_peer_config_state_t config_state; /**< Specifies the way this peer was configured and if it is enabled */
fastd_peer_state_t state; /**< The peer's state */
+
struct timespec timeout; /**< The timeout after which the peer is reset */
struct timespec keepalive_timeout; /**< The timeout after which a keepalive is sent to the peer */
+ const fastd_peer_group_t *group; /**< The peer group the peer belongs to */
+
VECTOR(fastd_remote_t) remotes; /**< The vector of the peer's remotes */
ssize_t next_remote; /**< An index into the field remotes or -1 */
+ bool floating; /**< Specifies if the peer has any floating remotes */
struct timespec next_handshake; /**< The time of the next handshake */
fastd_dlist_head_t handshake_entry; /**< Entry in the handshake queue */
@@ -84,35 +89,17 @@ struct fastd_peer {
struct timespec establish_handshake_timeout; /**< A timeout during which all handshakes for this peer will be ignored after a new connection has been established */
+ const char *config_source_dir; /**< The directory this peer's configuration was loaded from */
+
#ifdef WITH_DYNAMIC_PEERS
struct timespec verify_timeout; /**< Specifies the minimum time after which on-verify may be run again */
struct timespec verify_valid_timeout; /**< Specifies how long a peer stays valid after a successful on-verify run */
#endif
+ fastd_protocol_key_t *key; /**< The peer's public key */
fastd_protocol_peer_state_t *protocol_state; /**< Protocol-specific peer state */
};
-/**
- Static configuration of a peer
-
- Peer configurations are kept in a linked list.
-*/
-struct fastd_peer_config {
- fastd_peer_config_t *next; /**< The next peer configuration */
-
- fastd_peer_config_state_t config_state; /**< Specifies the way this peer was configured and if it is enabled */
-
- const char *config_source_dir; /**< The directory this peer's configuration was loaded from */
-
- char *name; /**< The peer's name */
-
- fastd_remote_config_t *remotes; /**< A linked list of the peer's remote entries */
- char *key; /**< The peer's public key */
- bool floating; /**< Specifies if the peer has any floating remotes */
- const fastd_peer_group_t *group; /**< The peer group the peer belongs to */
-
- fastd_protocol_peer_config_t *protocol_config; /**< The protocol-specific configuration of the peer */
-};
/**
A group of peers
@@ -138,9 +125,10 @@ struct fastd_peer_eth_addr {
struct timespec timeout; /**< Timeout after which the address entry will be purged */
};
-/** A resolved remote entry */
+/** A remote entry */
struct fastd_remote {
- fastd_remote_config_t *config; /**< The remote's configuration */
+ char *hostname; /**< The hostname or NULL */
+ fastd_peer_address_t address; /**< The address; if hostname is set only sin.sin_port is used */
size_t n_addresses; /**< The size of the \e addresses array */
size_t current_address; /**< The index of the remote the next handshake will be sent to */
@@ -149,14 +137,6 @@ struct fastd_remote {
struct timespec last_resolve_timeout; /**< Timeout before the remote must not be resolved again */
};
-/** An address or hostname entry associated with a peer */
-struct fastd_remote_config {
- fastd_remote_config_t *next; /**< The next remote for the peer */
-
- char *hostname; /**< The hostname or NULL */
- fastd_peer_address_t address; /**< The address; if hostname is set only sin.sin_port is used */
-};
-
bool fastd_peer_address_equal(const fastd_peer_address_t *addr1, const fastd_peer_address_t *addr2);
void fastd_peer_address_simplify(fastd_peer_address_t *addr);
@@ -176,14 +156,10 @@ static inline uint16_t fastd_peer_address_get_port(const fastd_peer_address_t *a
}
}
-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_purge(fastd_peer_config_t *config);
-bool fastd_peer_config_equal(const fastd_peer_config_t *peer1, const fastd_peer_config_t *peer2);
-
+bool fastd_peer_add(fastd_peer_t *peer);
void fastd_peer_reset(fastd_peer_t *peer);
void fastd_peer_delete(fastd_peer_t *peer);
-fastd_peer_t* fastd_peer_add(fastd_peer_config_t *peer_conf);
+void fastd_peer_free(fastd_peer_t *peer);
void fastd_peer_set_established(fastd_peer_t *peer);
bool fastd_peer_may_connect(fastd_peer_t *peer);
void fastd_peer_handle_resolve(fastd_peer_t *peer, fastd_remote_t *remote, size_t n_addresses, const fastd_peer_address_t *addresses);
@@ -228,20 +204,15 @@ static inline bool fastd_peer_handshake_scheduled(fastd_peer_t *peer) {
return fastd_dlist_linked(&peer->handshake_entry);
}
-/** Checks if a peer config has floating remotes (or no remotes at all) */
-static inline bool fastd_peer_config_is_floating(const fastd_peer_config_t *config) {
- return (!config->remotes || config->floating);
-}
-
/** Checks if a peer is floating (is has at least one floating remote or no remotes at all) */
static inline bool fastd_peer_is_floating(const fastd_peer_t *peer) {
- return fastd_peer_config_is_floating(peer->config);
+ return (!VECTOR_LEN(peer->remotes) || peer->floating);
}
/** Checks if a peer is not statically configured, but added after a on-verify run */
static inline bool fastd_peer_is_dynamic(const fastd_peer_t *peer UNUSED) {
#ifdef WITH_DYNAMIC_PEERS
- return peer->config->config_state == CONFIG_DYNAMIC;
+ return peer->config_state == CONFIG_DYNAMIC;
#else
return false;
#endif
@@ -249,7 +220,7 @@ static inline bool fastd_peer_is_dynamic(const fastd_peer_t *peer UNUSED) {
/** Checks if a peer is enabled */
static inline bool fastd_peer_is_enabled(const fastd_peer_t *peer) {
- switch (peer->config->config_state) {
+ switch (peer->config_state) {
case CONFIG_STATIC:
#ifdef WITH_DYNAMIC_PEERS
case CONFIG_DYNAMIC:
@@ -279,11 +250,6 @@ static inline bool fastd_peer_is_established(const fastd_peer_t *peer) {
}
}
-/** Returns the peer's peer group */
-static inline const fastd_peer_group_t * fastd_peer_get_group(const fastd_peer_t *peer) {
- return peer->config->group;
-}
-
/** Signals that a valid packet was received from the peer */
static inline void fastd_peer_seen(fastd_peer_t *peer) {
peer->timeout = fastd_in_seconds(PEER_STALE_TIME);
diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c
index d952a5e..080c555 100644
--- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c
+++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c
@@ -74,37 +74,26 @@ static fastd_protocol_config_t* protocol_init(void) {
return protocol_config;
}
-/** Checks if a peer configuration is valid */
-static void protocol_peer_verify(fastd_peer_config_t *peer_conf) {
- if (!peer_conf->key)
- exit_error("no key configured for peer `%s'", peer_conf->name);
-
- aligned_int256_t key;
- if (!read_key(key.u8, peer_conf->key))
- exit_error("invalid key configured for peer `%s'", peer_conf->name);
-}
-
-/** Initializes the protocol-specific peer configuration */
-static void protocol_peer_configure(fastd_peer_config_t *peer_conf) {
- if (peer_conf->protocol_config)
- return;
+/** Parses a peer's key */
+static fastd_protocol_key_t * protocol_read_key(const char *key) {
+ fastd_protocol_key_t *ret = fastd_new(fastd_protocol_key_t);
- if (!peer_conf->key) {
- pr_warn("no key configured for `%s', disabling peer", peer_conf->name);
- return;
+ if (!read_key(ret->key.u8, key)) {
+ free(ret);
+ return NULL;
}
- aligned_int256_t key;
- if (!read_key(key.u8, peer_conf->key)) {
- pr_warn("invalid key configured for `%s', disabling peer", peer_conf->name);
- return;
- }
+ return ret;
+}
- peer_conf->protocol_config = fastd_new(fastd_protocol_peer_config_t);
- peer_conf->protocol_config->public_key = key;
+/** Checks if a peer is configured using our own key */
+static bool protocol_check_peer(const fastd_peer_t *peer) {
+ if (memcmp(conf.protocol_config->key.public.u8, peer->key->key.u8, PUBLICKEYBYTES) == 0) {
+ pr_verbose("found own key as %P, ignoring peer", peer);
+ return false;
+ }
- if (memcmp(&peer_conf->protocol_config->public_key, &conf.protocol_config->key.public, PUBLICKEYBYTES) == 0)
- pr_debug("found own key as `%s', ignoring peer", peer_conf->name);
+ return true;
}
/** Checks if the current session with a peer is valid and resets the connection if not */
@@ -215,11 +204,6 @@ const fastd_protocol_t fastd_protocol_ec25519_fhmqvc = {
.name = "ec25519-fhmqvc",
.init = protocol_init,
- .peer_verify = protocol_peer_verify,
- .peer_configure = protocol_peer_configure,
-
- .peer_check = fastd_protocol_ec25519_fhmqvc_peer_check,
- .peer_check_dynamic = fastd_protocol_ec25519_fhmqvc_peer_check_dynamic,
.handshake_init = fastd_protocol_ec25519_fhmqvc_handshake_init,
.handshake_handle = fastd_protocol_ec25519_fhmqvc_handshake_handle,
@@ -234,8 +218,13 @@ const fastd_protocol_t fastd_protocol_ec25519_fhmqvc = {
.reset_peer_state = fastd_protocol_ec25519_fhmqvc_reset_peer_state,
.free_peer_state = fastd_protocol_ec25519_fhmqvc_free_peer_state,
+ .read_key = protocol_read_key,
+ .check_peer = protocol_check_peer,
+ .find_peer = fastd_protocol_ec25519_fhmqvc_find_peer,
+
.generate_key = fastd_protocol_ec25519_fhmqvc_generate_key,
.show_key = fastd_protocol_ec25519_fhmqvc_show_key,
+
.set_shell_env = fastd_protocol_ec25519_fhmqvc_set_shell_env,
.describe_peer = fastd_protocol_ec25519_fhmqvc_describe_peer,
};
diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h
index 529dd15..55696c1 100644
--- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h
+++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h
@@ -65,9 +65,9 @@ struct fastd_protocol_config {
keypair_t key; /**< The own keypair */
};
-/** The protocol-specific peer configuration */
-struct fastd_protocol_peer_config {
- aligned_int256_t public_key; /**< The peer's public key */
+/** A peer's public key */
+struct fastd_protocol_key {
+ aligned_int256_t key; /**< The peer's public key */
};
/** Session state */
@@ -101,9 +101,6 @@ struct fastd_protocol_peer_state {
};
-bool fastd_protocol_ec25519_fhmqvc_peer_check(fastd_peer_config_t *peer_conf);
-bool fastd_protocol_ec25519_fhmqvc_peer_check_dynamic(fastd_peer_t *peer);
-
void fastd_protocol_ec25519_fhmqvc_maintenance(void);
void fastd_protocol_ec25519_fhmqvc_init_peer_state(fastd_peer_t *peer);
void fastd_protocol_ec25519_fhmqvc_reset_peer_state(fastd_peer_t *peer);
@@ -118,8 +115,11 @@ void fastd_protocol_ec25519_fhmqvc_handle_verify_return(fastd_peer_t *peer, fast
void fastd_protocol_ec25519_fhmqvc_send_empty(fastd_peer_t *peer, protocol_session_t *session);
+fastd_peer_t * fastd_protocol_ec25519_fhmqvc_find_peer(const fastd_protocol_key_t *key);
+
void fastd_protocol_ec25519_fhmqvc_generate_key(void);
void fastd_protocol_ec25519_fhmqvc_show_key(void);
+
void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const fastd_peer_t *peer);
bool fastd_protocol_ec25519_fhmqvc_describe_peer(const fastd_peer_t *peer, char *buf, size_t len);
diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c
index 86f9f9e..8f468cd 100644
--- a/src/protocols/ec25519_fhmqvc/handshake.c
+++ b/src/protocols/ec25519_fhmqvc/handshake.c
@@ -277,7 +277,7 @@ static bool update_shared_handshake_key(const fastd_peer_t *peer, const handshak
bool compat = !conf.secure_handshakes;
if (!make_shared_handshake_key(&handshake_key->key.secret, false,
- &peer->config->protocol_config->public_key,
+ &peer->key->key,
&conf.protocol_config->key.public,
peer_handshake_key,
&handshake_key->key.public,
@@ -315,7 +315,7 @@ static void respond_handshake(const fastd_socket_t *sock, const fastd_peer_addre
fastd_buffer_t buffer = fastd_handshake_new_reply(2, method, true, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
- fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->config->protocol_config->public_key);
+ fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->key->key);
fastd_handshake_add(&buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, &handshake_key->key.public);
fastd_handshake_add(&buffer, RECORD_RECIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key);
@@ -344,7 +344,7 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l
fastd_sha256_t shared_handshake_key, shared_handshake_key_compat;
if (!make_shared_handshake_key(&handshake_key->key.secret, true,
&conf.protocol_config->key.public,
- &peer->config->protocol_config->public_key,
+ &peer->key->key,
&handshake_key->key.public,
peer_handshake_key,
&sigma,
@@ -361,7 +361,7 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l
valid = fastd_hmacsha256_verify(mac, shared_handshake_key.w, handshake->tlv_data, handshake->tlv_len);
}
else {
- valid = fastd_hmacsha256_blocks_verify(handshake->records[RECORD_T].data, shared_handshake_key_compat.w, peer->config->protocol_config->public_key.u32, peer_handshake_key->u32, NULL);
+ valid = fastd_hmacsha256_blocks_verify(handshake->records[RECORD_T].data, shared_handshake_key_compat.w, peer->key->key.u32, peer_handshake_key->u32, NULL);
}
if (!valid) {
@@ -370,13 +370,13 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l
}
if (!establish(peer, method, sock, local_addr, remote_addr, true, &handshake_key->key.public, peer_handshake_key, &conf.protocol_config->key.public,
- &peer->config->protocol_config->public_key, &sigma, compat ? NULL : shared_handshake_key.w, handshake_key->serial))
+ &peer->key->key, &sigma, compat ? NULL : shared_handshake_key.w, handshake_key->serial))
return;
fastd_buffer_t buffer = fastd_handshake_new_reply(3, method, false, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
- fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->config->protocol_config->public_key);
+ fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->key->key);
fastd_handshake_add(&buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, &handshake_key->key.public);
fastd_handshake_add(&buffer, RECORD_RECIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key);
@@ -415,7 +415,7 @@ static void handle_finish_handshake(fastd_socket_t *sock, const fastd_peer_addre
valid = fastd_hmacsha256_verify(mac, peer->protocol_state->shared_handshake_key.w, handshake->tlv_data, handshake->tlv_len);
}
else {
- valid = fastd_hmacsha256_blocks_verify(handshake->records[RECORD_T].data, peer->protocol_state->shared_handshake_key_compat.w, peer->config->protocol_config->public_key.u32, peer_handshake_key->u32, NULL);
+ valid = fastd_hmacsha256_blocks_verify(handshake->records[RECORD_T].data, peer->protocol_state->shared_handshake_key_compat.w, peer->key->key.u32, peer_handshake_key->u32, NULL);
}
if (!valid) {
@@ -423,14 +423,14 @@ static void handle_finish_handshake(fastd_socket_t *sock, const fastd_peer_addre
return;
}
- establish(peer, method, sock, local_addr, remote_addr, false, peer_handshake_key, &handshake_key->key.public, &peer->config->protocol_config->public_key,
+ establish(peer, method, sock, local_addr, remote_addr, false, peer_handshake_key, &handshake_key->key.public, &peer->key->key,
&conf.protocol_config->key.public, &peer->protocol_state->sigma, compat ? NULL : peer->protocol_state->shared_handshake_key.w, handshake_key->serial);
clear_shared_handshake_key(peer);
}
-/** Searches the peer a public key belongs to */
-static fastd_peer_t* find_sender_key(const fastd_peer_address_t *address, const unsigned char key[PUBLICKEYBYTES]) {
+/** Searches the peer a public key belongs to, optionally restricting matches to a specific sender address */
+static fastd_peer_t * find_key(const uint8_t key[PUBLICKEYBYTES], const fastd_peer_address_t *address) {
errno = 0;
fastd_peer_t *ret = NULL;
@@ -439,10 +439,13 @@ static fastd_peer_t* find_sender_key(const fastd_peer_address_t *address, const
for (i = 0; i < VECTOR_LEN(ctx.peers); i++) {
fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
- if (!fastd_peer_is_enabled(peer))
+ if (address && !fastd_peer_is_enabled(peer))
continue;
- if (memcmp(&peer->config->protocol_config->public_key, key, PUBLICKEYBYTES) == 0) {
+ if (memcmp(&peer->key->key, key, PUBLICKEYBYTES) == 0) {
+ if (!address)
+ return peer;
+
if (!fastd_peer_matches_address(peer, address)) {
errno = EPERM;
return NULL;
@@ -464,15 +467,20 @@ static fastd_peer_t* find_sender_key(const fastd_peer_address_t *address, const
return ret;
}
+/** Searches the peer a public key belongs to (including disabled peers) */
+fastd_peer_t * fastd_protocol_ec25519_fhmqvc_find_peer(const fastd_protocol_key_t *key) {
+ return find_key(key->key.u8, NULL);
+}
+
/** Checks if a key matches a peer and searches the correct peer if it doesn't */
-static fastd_peer_t* match_sender_key(const fastd_socket_t *sock, const fastd_peer_address_t *address, fastd_peer_t *peer, const unsigned char key[PUBLICKEYBYTES]) {
+static fastd_peer_t * match_sender_key(const fastd_socket_t *sock, const fastd_peer_address_t *address, fastd_peer_t *peer, const uint8_t key[PUBLICKEYBYTES]) {
errno = 0;
if (sock->peer && peer != sock->peer)
exit_bug("packet without correct peer set on dynamic socket");
if (peer) {
- if (memcmp(&peer->config->protocol_config->public_key, key, PUBLICKEYBYTES) == 0)
+ if (memcmp(&peer->key->key, key, PUBLICKEYBYTES) == 0)
return peer;
if (fastd_peer_owns_address(peer, address)) {
@@ -481,41 +489,7 @@ static fastd_peer_t* match_sender_key(const fastd_socket_t *sock, const fastd_pe
}
}
- return find_sender_key(address, key);
-}
-
-/** Counts how many peers with a key are configured */
-static size_t key_count(const unsigned char key[PUBLICKEYBYTES]) {
- size_t ret = 0;
-
- fastd_peer_config_t *p;
- for (p = ctx.peer_configs; p; p = p->next) {
- if (!p->protocol_config)
- continue;
-
- if (memcmp(&p->protocol_config->public_key, key, PUBLICKEYBYTES) == 0)
- ret++;
- }
-
- return ret;
-}
-
-/** Validates a peer config */
-bool fastd_protocol_ec25519_fhmqvc_peer_check(fastd_peer_config_t *peer_conf) {
- if (!peer_conf->protocol_config)
- return false;
-
- if (memcmp(&peer_conf->protocol_config->public_key, &conf.protocol_config->key.public, PUBLICKEYBYTES) == 0)
- return false;
-
- if (key_count(peer_conf->protocol_config->public_key.u8) > 1) {
- char buf[65];
- hexdump(buf, peer_conf->protocol_config->public_key.u8);
- pr_warn("more than one peer is configured with key %s, disabling %s", buf, peer_conf->name);
- return false;
- }
-
- return true;
+ return find_key(key, address);
}
/** Sends an initial handshake (type 1) to a peer */
@@ -527,7 +501,7 @@ void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fa
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
if (peer) {
- fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->config->protocol_config->public_key);
+ fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->key->key);
pr_verbose("sending handshake to %P[%I]...", peer, remote_addr);
}
@@ -543,18 +517,6 @@ void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fa
fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer);
}
-/** Checks if a dynamic peer (added after an on-verify command) can stay after new peers have been configured */
-bool fastd_protocol_ec25519_fhmqvc_peer_check_dynamic(fastd_peer_t *peer) {
- if (key_count(peer->config->protocol_config->public_key.u8)) {
- char buf[65];
- hexdump(buf, peer->config->protocol_config->public_key.u8);
- pr_info("key %s is configured now, deleting dynamic peer.", buf);
- return false;
- }
-
- return true;
-}
-
#ifdef WITH_DYNAMIC_PEERS
@@ -576,15 +538,25 @@ static fastd_peer_t * add_dynamic(fastd_socket_t *sock, const fastd_peer_address
return NULL;
}
- if (key_count(key)) {
+ if (memcmp(&conf.protocol_config->key.public, key, PUBLICKEYBYTES) == 0) {
+ pr_debug("ignoring handshake from %I (used our own key)", addr);
+ return NULL;
+ }
+
+ if (find_key(key, NULL)) {
pr_debug("ignoring handshake from %I (disabled key)", addr);
return NULL;
}
- fastd_peer_t *peer = fastd_peer_add(NULL);
+ fastd_peer_t *peer = fastd_new0(fastd_peer_t);
+ peer->group = conf.peer_group;
+ peer->config_state = CONFIG_DYNAMIC;
+
+ peer->key = fastd_new(fastd_protocol_key_t);
+ memcpy(&peer->key->key, key, PUBLICKEYBYTES);
- peer->config->protocol_config = fastd_new(fastd_protocol_peer_config_t);
- memcpy(&peer->config->protocol_config->public_key, key, PUBLICKEYBYTES);
+ if (!fastd_peer_add(peer))
+ exit_bug("failed to add dynamic peer");
/* Ugly hack */
peer->protocol_state->last_serial--;
diff --git a/src/protocols/ec25519_fhmqvc/util.c b/src/protocols/ec25519_fhmqvc/util.c
index c716916..f34f709 100644
--- a/src/protocols/ec25519_fhmqvc/util.c
+++ b/src/protocols/ec25519_fhmqvc/util.c
@@ -80,8 +80,8 @@ void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const f
hexdump(buf, conf.protocol_config->key.public.u8);
fastd_shell_env_set(env, "LOCAL_KEY", buf);
- if (peer && peer->config->protocol_config) {
- hexdump(buf, peer->config->protocol_config->public_key.u8);
+ if (peer) {
+ hexdump(buf, peer->key->key.u8);
fastd_shell_env_set(env, "PEER_KEY", buf);
}
else {
@@ -97,14 +97,12 @@ void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const f
public key.
*/
bool fastd_protocol_ec25519_fhmqvc_describe_peer(const fastd_peer_t *peer, char *buf, size_t len) {
- if (peer && peer->config->protocol_config) {
- char dumpbuf[65];
-
- hexdump(dumpbuf, peer->config->protocol_config->public_key.u8);
- snprintf(buf, len, "%.16s", dumpbuf);
- return true;
- }
- else {
+ if (!peer->key)
return false;
- }
+
+ char dumpbuf[65];
+ hexdump(dumpbuf, peer->key->key.u8);
+ snprintf(buf, len, "%.16s", dumpbuf);
+
+ return true;
}
diff --git a/src/receive.c b/src/receive.c
index 7b00f2c..10f70e7 100644
--- a/src/receive.c
+++ b/src/receive.c
@@ -150,7 +150,7 @@ static inline void handle_socket_receive_known(fastd_socket_t *sock, const fastd
/** Determines if packets from known addresses are accepted */
static inline bool allow_unknown_peers(void) {
- return conf.has_floating || fastd_allow_verify();
+ return ctx.has_floating || fastd_allow_verify();
}
/** Handles a packet received from an unknown address */
diff --git a/src/resolve.c b/src/resolve.c
index df48fec..048c1b3 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -121,7 +121,7 @@ void fastd_resolve_peer(fastd_peer_t *peer, fastd_remote_t *remote) {
return;
}
- pr_verbose("resolving host `%s' for peer %P...", remote->config->hostname, peer);
+ pr_verbose("resolving host `%s' for peer %P...", remote->hostname, peer);
remote->last_resolve_timeout = fastd_in_seconds(MIN_RESOLVE_INTERVAL);
@@ -129,8 +129,8 @@ void fastd_resolve_peer(fastd_peer_t *peer, fastd_remote_t *remote) {
arg->peer_id = peer->id;
arg->remote = remote - VECTOR_DATA(peer->remotes);
- arg->hostname = fastd_strdup(remote->config->hostname);
- arg->constraints = remote->config->address;
+ arg->hostname = fastd_strdup(remote->hostname);
+ arg->constraints = remote->address;
pthread_t thread;
if ((errno = pthread_create(&thread, &ctx.detached_thread, resolve_peer, arg)) != 0) {
diff --git a/src/types.h b/src/types.h
index 3ab03a6..927d707 100644
--- a/src/types.h
+++ b/src/types.h
@@ -82,11 +82,9 @@ typedef union fastd_peer_address fastd_peer_address_t;
typedef struct fastd_bind_address fastd_bind_address_t;
typedef struct fastd_socket fastd_socket_t;
typedef struct fastd_peer_group fastd_peer_group_t;
-typedef struct fastd_peer_config fastd_peer_config_t;
typedef struct fastd_eth_addr fastd_eth_addr_t;
typedef struct fastd_peer fastd_peer_t;
typedef struct fastd_peer_eth_addr fastd_peer_eth_addr_t;
-typedef struct fastd_remote_config fastd_remote_config_t;
typedef struct fastd_remote fastd_remote_t;
typedef struct fastd_stats fastd_stats_t;
typedef struct fastd_handshake_timeout fastd_handshake_timeout_t;
@@ -124,7 +122,7 @@ typedef union fastd_block128 {
/* May be defined by the protocol/method/crypto implementations however they like */
typedef struct fastd_protocol_config fastd_protocol_config_t;
typedef struct fastd_protocol_state fastd_protocol_state_t;
-typedef struct fastd_protocol_peer_config fastd_protocol_peer_config_t;
+typedef struct fastd_protocol_key fastd_protocol_key_t;
typedef struct fastd_protocol_peer_state fastd_protocol_peer_state_t;
typedef struct fastd_method fastd_method_t;