summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-04-05 05:21:58 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-04-05 05:21:58 +0200
commit329d15d50c54a69ce8e2be0865124744c0bf3428 (patch)
tree34734e0ed120a83069738a0a51df9bdd1a664640
parentcbf0166a7f12f71747c495b5ea68ff676c1a7868 (diff)
downloadfastd-329d15d50c54a69ce8e2be0865124744c0bf3428.tar
fastd-329d15d50c54a69ce8e2be0865124744c0bf3428.zip
Implement reconfiguration on SIGHUP
-rw-r--r--src/config.c240
-rw-r--r--src/config.y2
-rw-r--r--src/fastd.c49
-rw-r--r--src/fastd.h14
-rw-r--r--src/peer.c60
-rw-r--r--src/peer.h9
-rw-r--r--src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c87
-rw-r--r--src/protocol_null.c14
8 files changed, 362 insertions, 113 deletions
diff --git a/src/config.c b/src/config.c
index c708609..7725c40 100644
--- a/src/config.c
+++ b/src/config.c
@@ -71,6 +71,7 @@ static void default_config(fastd_config *conf) {
conf->key_valid = 3600; /* 60 minutes */
conf->key_refresh = 3300; /* 55 minutes */
+ conf->peer_dirs = NULL;
conf->peers = NULL;
conf->on_up = NULL;
@@ -96,67 +97,69 @@ static bool config_match(const char *opt, ...) {
return match;
}
-void fastd_read_config_dir(fastd_context *ctx, fastd_config *conf, const char *dir, int depth) {
- if (depth >= MAX_CONFIG_DEPTH)
- exit_error(ctx, "maximum config include depth exceeded");
+static void read_peer_dir(fastd_context *ctx, fastd_config *conf, const char *dir) {
+ DIR *dirh = opendir(".");
- char *oldcwd = get_current_dir_name();
+ if (dirh) {
+ while (true) {
+ struct dirent entry, *result;
+ int ret;
- if (!chdir(dir)) {
- char *newdir = get_current_dir_name();
- conf->peer_dirs = fastd_string_stack_push(conf->peer_dirs, newdir);
- free(newdir);
+ ret = readdir_r(dirh, &entry, &result);
+ if (ret) {
+ pr_error(ctx, "readdir_r: %s", strerror(ret));
+ break;
+ }
- DIR *dirh = opendir(".");
+ if (!result)
+ break;
+ if (result->d_name[0] == '.')
+ continue;
- if (dirh) {
- while (true) {
- struct dirent entry, *result;
- int ret;
+ struct stat statbuf;
+ if (stat(result->d_name, &statbuf)) {
+ pr_warn(ctx, "ignoring file `%s': stat failed: %s", result->d_name, strerror(errno));
+ continue;
+ }
+ if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
+ pr_info(ctx, "ignoring file `%s': no regular file", result->d_name);
+ continue;
+ }
- ret = readdir_r(dirh, &entry, &result);
- if (ret) {
- pr_error(ctx, "readdir_r: %s", strerror(ret));
- break;
- }
+ fastd_peer_config_new(ctx, conf);
+ conf->peers->name = strdup(result->d_name);
+ conf->peers->config_source_dir = dir;
- if (!result)
- break;
- if (result->d_name[0] == '.')
- continue;
+ if (!fastd_read_config(ctx, conf, result->d_name, true, 0)) {
+ pr_warn(ctx, "peer config `%s' will be ignored", result->d_name);
+ fastd_peer_config_delete(ctx, conf);
+ }
+ }
- struct stat statbuf;
- if (stat(result->d_name, &statbuf)) {
- pr_warn(ctx, "ignoring file `%s': stat failed: %s", result->d_name, strerror(errno));
- continue;
- }
- if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
- pr_info(ctx, "ignoring file `%s': no regular file", result->d_name);
- continue;
- }
+ closedir(dirh);
+ }
+ else {
+ pr_error(ctx, "opendir for `%s' failed: %s", dir, strerror(errno));
+ }
+}
- fastd_peer_config_new(ctx, conf);
- conf->peers->name = strdup(result->d_name);
- conf->peers->config_source_dir = conf->peer_dirs->str;
+void fastd_read_peer_dir(fastd_context *ctx, fastd_config *conf, const char *dir) {
+ char *oldcwd = get_current_dir_name();
- if (!fastd_read_config(ctx, conf, result->d_name, true, depth)) {
- pr_warn(ctx, "peer config `%s' will be ignored", result->d_name);
- fastd_peer_config_delete(ctx, conf);
- }
- }
+ if (!chdir(dir)) {
+ char *newdir = get_current_dir_name();
+ conf->peer_dirs = fastd_string_stack_push(conf->peer_dirs, newdir);
+ free(newdir);
- closedir(dirh);
- }
- else {
- pr_error(ctx, "opendir for `%s' failed: %s", dir, strerror(errno));
- }
+ read_peer_dir(ctx, conf, conf->peer_dirs->str);
chdir(oldcwd);
- free(oldcwd);
}
else {
pr_error(ctx, "change from directory `%s' to `%s' failed: %s", oldcwd, dir, strerror(errno));
}
+
+ free(oldcwd);
}
bool fastd_read_config(fastd_context *ctx, fastd_config *conf, const char *filename, bool peer_config, int depth) {
@@ -248,6 +251,32 @@ bool fastd_read_config(fastd_context *ctx, fastd_config *conf, const char *filen
return ret;
}
+static void count_peers(fastd_context *ctx, fastd_config *conf) {
+ conf->n_floating = 0;
+ conf->n_v4 = 0;
+ conf->n_v6 = 0;
+
+ fastd_peer_config *peer;
+ for (peer = conf->peers; peer; peer = peer->next) {
+ switch (peer->address.sa.sa_family) {
+ case AF_UNSPEC:
+ conf->n_floating++;
+ break;
+
+ case AF_INET:
+ conf->n_v4++;
+ break;
+
+ case AF_INET6:
+ conf->n_v6++;
+ break;
+
+ default:
+ exit_bug(ctx, "invalid peer address family");
+ }
+ }
+}
+
#define IF_OPTION(args...) if(config_match(argv[i], args, NULL) && (++i))
#define IF_OPTION_ARG(args...) if(config_match(argv[i], args, NULL) && ({ \
arg = argv[i+1]; \
@@ -309,7 +338,7 @@ void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *con
}
IF_OPTION_ARG("--config-peer-dir") {
- fastd_read_config_dir(ctx, conf, arg, 0);
+ fastd_read_peer_dir(ctx, conf, arg);
continue;
}
@@ -478,35 +507,110 @@ void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *con
exit(0);
}
- conf->n_floating = 0;
- conf->n_v4 = 0;
- conf->n_v6 = 0;
+ 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)
+ exit_error(ctx, "config error: for tun mode peer directories can't be used");
+ }
- for (peer = conf->peers; peer; peer = peer->next) {
- switch (peer->address.sa.sa_family) {
- case AF_UNSPEC:
- conf->n_floating++;
- break;
+ count_peers(ctx, conf);
+}
- case AF_INET:
- conf->n_v4++;
- break;
+static void reconfigure_read_peer_dirs(fastd_context *ctx, fastd_config *new_conf, fastd_string_stack *dirs) {
+ char *oldcwd = get_current_dir_name();
- case AF_INET6:
- conf->n_v6++;
- break;
+ fastd_string_stack *dir;
+ for (dir = dirs; dir; dir = dir->next) {
+ if (!chdir(dir->str))
+ read_peer_dir(ctx, new_conf, dir->str);
+ else
+ pr_error(ctx, "change from directory `%s' to `%s' failed: %s", oldcwd, dir->str, strerror(errno));
+ }
- default:
- exit_bug(ctx, "invalid peer address family");
+ chdir(oldcwd);
+ free(oldcwd);
+}
+
+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) {
+ 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;
+
+ 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_debug(ctx, "peer `%s' unchanged", (*peer)->name);
+
+ fastd_peer_config *free_peer = *new_peer;
+ *new_peer = *new_next;
+ fastd_peer_config_free(free_peer);
+ peer = NULL;
+ }
+ else {
+ pr_debug(ctx, "peer `%s' changed, resetting", (*peer)->name);
+ new_peer = NULL;
+ }
+
+ break;
+ }
+ }
+
+ /* no new peer was found, or the old one has changed */
+ if (peer && (!new_peer || !*new_peer)) {
+ pr_debug(ctx, "removing peer `%s'", (*peer)->name);
+
+ fastd_peer_config *free_peer = *peer;
+ *peer = *next;
+ next = peer;
+
+ fastd_peer_config_purge(ctx, free_peer);
}
}
+}
- 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)
- exit_error(ctx, "config error: for tun mode peer directories can't be used");
+static void reconfigure_reset_waiting(fastd_context *ctx) {
+ fastd_peer *peer;
+ for (peer = ctx->peers; peer; peer = peer->next) {
+ if (fastd_peer_is_waiting(peer))
+ fastd_peer_reset(ctx, peer);
+ }
+}
+
+static void reconfigure_handle_new_peers(fastd_context *ctx, fastd_peer_config **peers, fastd_peer_config *new_peers) {
+ fastd_peer_config *peer, *next;
+ for (peer = new_peers; peer; peer = next) {
+ next = peer->next;
+
+ ctx->conf->protocol->peer_configure(ctx, peer);
+ if (peer->enabled)
+ fastd_peer_add(ctx, peer);
+
+ peer->next = *peers;
+ *peers = peer;
}
+}
+
+void fastd_reconfigure(fastd_context *ctx, fastd_config *conf) {
+ pr_info(ctx, "reconfigure triggered");
+
+ fastd_config temp_conf;
+ temp_conf.peers = NULL;
+
+ reconfigure_read_peer_dirs(ctx, &temp_conf, conf->peer_dirs);
+ reconfigure_handle_old_peers(ctx, &conf->peers, &temp_conf.peers);
+
+ reconfigure_reset_waiting(ctx);
+
+ reconfigure_handle_new_peers(ctx, &conf->peers, temp_conf.peers);
+
+ count_peers(ctx, conf);
- conf->protocol->init(ctx, conf);
}
diff --git a/src/config.y b/src/config.y
index 8b5e49e..332ad77 100644
--- a/src/config.y
+++ b/src/config.y
@@ -250,7 +250,7 @@ include: TOK_PEER TOK_STRING maybe_as {
YYERROR;
}
| TOK_PEERS TOK_FROM TOK_STRING {
- fastd_read_config_dir(ctx, conf, $3->str, depth);
+ fastd_read_peer_dir(ctx, conf, $3->str);
}
| TOK_STRING {
if (!fastd_read_config(ctx, conf, $1->str, false, depth))
diff --git a/src/fastd.c b/src/fastd.c
index 3185186..f38bf60 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -35,12 +35,32 @@
#include <linux/if_tun.h>
#include <net/if.h>
#include <poll.h>
+#include <signal.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
+static bool sighup = false;
+
+
+static void on_sighup(int signo) {
+ sighup = true;
+}
+
+
+static void init_signals(fastd_context *ctx) {
+ struct sigaction action;
+
+ action.sa_handler = on_sighup;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+
+ if(sigaction(SIGHUP, &action, NULL))
+ exit_errno(ctx, "sigaction");
+}
+
static void init_tuntap(fastd_context *ctx) {
struct ifreq ifr;
@@ -161,6 +181,8 @@ static void on_up(fastd_context *ctx) {
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) {
+ ctx->conf->protocol->peer_configure(ctx, peer_conf);
+
if (peer_conf->enabled)
fastd_peer_add(ctx, peer_conf);
}
@@ -280,8 +302,14 @@ static void handle_tun(fastd_context *ctx) {
fastd_buffer buffer = fastd_buffer_alloc(max_len, ctx->conf->protocol->min_encrypt_head_space(ctx), 0);
ssize_t len = read(ctx->tunfd, buffer.data, max_len);
- if (len < 0)
+ if (len < 0) {
+ if (errno == EINTR) {
+ fastd_buffer_free(buffer);
+ return;
+ }
+
exit_errno(ctx, "read");
+ }
buffer.len = len;
@@ -339,7 +367,9 @@ static void handle_socket(fastd_context *ctx, int sockfd) {
ssize_t len = recvmsg(sockfd, &msg, 0);
if (len < 0) {
- pr_warn(ctx, "recvfrom: %s", strerror(errno));
+ if (errno != EINTR)
+ pr_warn(ctx, "recvfrom: %s", strerror(errno));
+
fastd_buffer_free(buffer);
return;
}
@@ -423,8 +453,12 @@ static void handle_input(fastd_context *ctx) {
timeout = 60000; /* call maintenance at least once a minute */
int ret = poll(fds, 3, timeout);
- if (ret < 0)
+ if (ret < 0) {
+ if (errno == EINTR)
+ return;
+
exit_errno(ctx, "poll");
+ }
update_time(ctx);
@@ -470,6 +504,10 @@ int main(int argc, char *argv[]) {
fastd_configure(&ctx, &conf, argc, argv);
ctx.conf = &conf;
+ conf.protocol_config = conf.protocol->init(&ctx);
+
+ init_signals(&ctx);
+
update_time(&ctx);
init_peers(&ctx);
@@ -484,6 +522,11 @@ int main(int argc, char *argv[]) {
handle_input(&ctx);
maintenance(&ctx);
+
+ if (sighup) {
+ sighup = false;
+ fastd_reconfigure(&ctx, &conf);
+ }
}
return 0;
diff --git a/src/fastd.h b/src/fastd.h
index 4a4bd49..f07f108 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -59,7 +59,9 @@ struct _fastd_eth_addr {
struct _fastd_protocol {
const char *name;
- void (*init)(fastd_context *ctx, fastd_config *conf);
+ fastd_protocol_config* (*init)(fastd_context *ctx);
+ void (*peer_configure)(fastd_context *ctx, fastd_peer_config *peer_conf);
+ void (*peer_config_purged)(fastd_context *ctx, fastd_peer_config *peer_conf);
size_t (*max_packet_size)(fastd_context *ctx);
size_t (*min_encrypt_head_space)(fastd_context *ctx);
@@ -140,9 +142,10 @@ struct _fastd_string_stack {
void fastd_printf(const fastd_context *ctx, const char *format, ...);
-void fastd_read_config_dir(fastd_context *ctx, fastd_config *conf, const char *dir, int depth);
+void fastd_read_peer_dir(fastd_context *ctx, fastd_config *conf, const char *dir);
bool fastd_read_config(fastd_context *ctx, fastd_config *conf, const char *filename, bool peer_config, int depth);
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_random_bytes(fastd_context *ctx, void *buffer, size_t len, bool secure);
@@ -265,4 +268,11 @@ static inline int timespec_diff(const struct timespec *tp1, const struct timespe
return ((tp1->tv_sec - tp2->tv_sec))*1000 + (tp1->tv_nsec - tp2->tv_nsec)/1e6;
}
+static inline bool strequal(const char *str1, const char *str2) {
+ if (str1 && str2)
+ return (!strcmp(str1, str2));
+ else
+ return (str1 == str2);
+}
+
#endif /* _FASTD_FASTD_H_ */
diff --git a/src/peer.c b/src/peer.c
index 1a418e8..9bb900b 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -95,16 +95,69 @@ fastd_peer_config* fastd_peer_config_new(fastd_context *ctx, fastd_config *conf)
return peer;
}
-void fastd_peer_config_delete(fastd_context *ctx, fastd_config *conf) {
- fastd_peer_config *peer = conf->peers, *next = peer->next;
-
+void fastd_peer_config_free(fastd_peer_config *peer) {
free(peer->name);
free(peer->key);
+ free(peer->protocol_config);
free(peer);
+}
+void fastd_peer_config_delete(fastd_context *ctx, fastd_config *conf) {
+ fastd_peer_config *peer = conf->peers, *next = peer->next;
+ fastd_peer_config_free(peer);
conf->peers = next;
}
+void fastd_peer_config_purge(fastd_context *ctx, fastd_peer_config *conf) {
+ fastd_peer *peer, *next;
+ for (peer = ctx->peers; peer; peer = next) {
+ next = peer->next;
+
+ if (peer->config == conf) {
+ reset_peer(ctx, peer);
+ delete_peer(ctx, peer);
+ continue;
+ }
+ }
+
+ ctx->conf->protocol->peer_config_purged(ctx, conf);
+ fastd_peer_config_free(conf);
+}
+
+static bool fastd_peer_addr_equal(const fastd_peer_address *addr1, const fastd_peer_address *addr2) {
+ if (addr1->sa.sa_family != addr2->sa.sa_family)
+ return false;
+
+ switch (addr1->sa.sa_family) {
+ case AF_UNSPEC:
+ break;
+
+ case AF_INET:
+ if (addr1->in.sin_addr.s_addr != addr2->in.sin_addr.s_addr)
+ return false;
+ break;
+
+ case AF_INET6:
+ if (!IN6_ARE_ADDR_EQUAL(&addr1->in6.sin6_addr, &addr2->in6.sin6_addr))
+ return false;
+ }
+
+ return true;
+}
+
+bool fastd_peer_config_equal(const fastd_peer_config *peer1, const fastd_peer_config *peer2) {
+ if (peer1->enabled != peer2->enabled)
+ return false;
+
+ if (!fastd_peer_addr_equal(&peer1->address, &peer2->address))
+ return false;
+
+ if (!strequal(peer1->key, peer2->key))
+ return false;
+
+ return true;
+}
+
void fastd_peer_reset(fastd_context *ctx, fastd_peer *peer) {
pr_debug(ctx, "resetting peer %P", peer);
@@ -116,7 +169,6 @@ void fastd_peer_reset(fastd_context *ctx, fastd_peer *peer) {
setup_peer(ctx, peer);
}
-
static fastd_peer* add_peer(fastd_context *ctx) {
fastd_peer *peer = malloc(sizeof(fastd_peer));
diff --git a/src/peer.h b/src/peer.h
index d3b9cfe..94b9026 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -54,7 +54,7 @@ struct _fastd_peer {
struct _fastd_peer_config {
fastd_peer_config *next;
- char *config_source_dir;
+ const char *config_source_dir;
bool enabled;
char *name;
@@ -73,7 +73,10 @@ struct _fastd_peer_eth_addr {
fastd_peer_config* fastd_peer_config_new(fastd_context *ctx, fastd_config *conf);
+void fastd_peer_config_free(fastd_peer_config *peer);
void fastd_peer_config_delete(fastd_context *ctx, fastd_config *conf);
+void fastd_peer_config_purge(fastd_context *ctx, fastd_peer_config *conf);
+bool fastd_peer_config_equal(const fastd_peer_config *peer1, const fastd_peer_config *peer2);
void fastd_peer_reset(fastd_context *ctx, fastd_peer *peer);
fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *conf);
@@ -92,6 +95,10 @@ static inline bool fastd_peer_is_floating(const fastd_peer *peer) {
return (peer->config && fastd_peer_config_is_floating(peer->config));
}
+static inline bool fastd_peer_is_waiting(const fastd_peer *peer) {
+ return (peer->state == STATE_WAIT);
+}
+
static inline bool fastd_peer_is_temporary(const fastd_peer *peer) {
return (peer->state == STATE_TEMP);
}
diff --git a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c b/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
index df94d14..8dbf10e 100644
--- a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
+++ b/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
@@ -191,50 +191,39 @@ static inline bool is_nonce_valid(const uint8_t nonce[NONCEBYTES], const uint8_t
return false;
}
-static void protocol_init(fastd_context *ctx, fastd_config *conf) {
- conf->protocol_config = malloc(sizeof(fastd_protocol_config));
+static fastd_protocol_config* protocol_init(fastd_context *ctx) {
+ fastd_protocol_config *protocol_config = malloc(sizeof(fastd_protocol_config));
- if (!conf->secret)
+ if (!ctx->conf->secret)
exit_error(ctx, "no secret key configured");
- if (!read_key(conf->protocol_config->secret_key.s, conf->secret))
+ if (!read_key(protocol_config->secret_key.s, ctx->conf->secret))
exit_error(ctx, "invalid secret key");
ecc_25519_work work;
- ecc_25519_scalarmult_base(&work, &conf->protocol_config->secret_key);
- ecc_25519_store(&conf->protocol_config->public_key, &work);
+ ecc_25519_scalarmult_base(&work, &protocol_config->secret_key);
+ ecc_25519_store(&protocol_config->public_key, &work);
- fastd_peer_config *peer;
- for (peer = conf->peers; peer; peer = peer->next) {
- ecc_public_key_256 key;
-
- if (!peer->key) {
- pr_warn(ctx, "no key configured for %P, disabling peer", peer);
- peer->enabled = false;
- continue;
- }
+ return protocol_config;
+}
- if (!read_key(key.p, peer->key)) {
- pr_warn(ctx, "invalid key configured for %P, disabling peer", peer);
- peer->enabled = false;
- continue;
- }
+static void protocol_peer_configure(fastd_context *ctx, fastd_peer_config *peer_conf) {
+ ecc_public_key_256 key;
- peer->protocol_config = malloc(sizeof(fastd_protocol_peer_config));
- peer->protocol_config->public_key = key;
+ if (!peer_conf->key) {
+ pr_warn(ctx, "no key configured for `%s', disabling peer", peer_conf->name);
+ peer_conf->enabled = false;
+ return;
}
-}
-
-static size_t protocol_max_packet_size(fastd_context *ctx) {
- return (fastd_max_packet_size(ctx) + NONCEBYTES + crypto_secretbox_xsalsa20poly1305_ZEROBYTES - crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES);
-}
-static size_t protocol_min_encrypt_head_space(fastd_context *ctx) {
- return crypto_secretbox_xsalsa20poly1305_ZEROBYTES;
-}
+ if (!read_key(key.p, peer_conf->key)) {
+ pr_warn(ctx, "invalid key configured for `%s', disabling peer", peer_conf->name);
+ peer_conf->enabled = false;
+ return;
+ }
-static size_t protocol_min_decrypt_head_space(fastd_context *ctx) {
- return (crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES - NONCEBYTES);
+ peer_conf->protocol_config = malloc(sizeof(fastd_protocol_peer_config));
+ peer_conf->protocol_config->public_key = key;
}
static void init_peer_state(fastd_context *ctx, fastd_peer *peer) {
@@ -252,6 +241,38 @@ static inline void free_handshake(protocol_handshake *handshake) {
}
}
+static void protocol_peer_config_purged(fastd_context *ctx, fastd_peer_config *peer_conf) {
+ fastd_peer *peer;
+ for (peer = ctx->peers; peer; peer = peer->next) {
+ if (!peer->protocol_state)
+ continue;
+
+ if (peer->protocol_state->initiating_handshake &&
+ peer->protocol_state->initiating_handshake->peer_config == peer_conf) {
+ free_handshake(peer->protocol_state->initiating_handshake);
+ peer->protocol_state->initiating_handshake = NULL;
+ }
+
+ if (peer->protocol_state->accepting_handshake &&
+ peer->protocol_state->accepting_handshake->peer_config == peer_conf) {
+ free_handshake(peer->protocol_state->accepting_handshake);
+ peer->protocol_state->accepting_handshake = NULL;
+ }
+ }
+}
+
+static size_t protocol_max_packet_size(fastd_context *ctx) {
+ return (fastd_max_packet_size(ctx) + NONCEBYTES + crypto_secretbox_xsalsa20poly1305_ZEROBYTES - crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES);
+}
+
+static size_t protocol_min_encrypt_head_space(fastd_context *ctx) {
+ return crypto_secretbox_xsalsa20poly1305_ZEROBYTES;
+}
+
+static size_t protocol_min_decrypt_head_space(fastd_context *ctx) {
+ return (crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES - NONCEBYTES);
+}
+
static protocol_handshake* new_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_peer_config *peer_config, bool initiate) {
protocol_handshake **handshake;
@@ -825,6 +846,8 @@ const fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305 = {
.name = "ec25519-fhmqvc-xsalsa20-poly1305",
.init = protocol_init,
+ .peer_configure = protocol_peer_configure,
+ .peer_config_purged = protocol_peer_config_purged,
.max_packet_size = protocol_max_packet_size,
.min_encrypt_head_space = protocol_min_encrypt_head_space,
diff --git a/src/protocol_null.c b/src/protocol_null.c
index cc08877..b3c0b17 100644
--- a/src/protocol_null.c
+++ b/src/protocol_null.c
@@ -34,9 +34,17 @@
#include <arpa/inet.h>
-static void protocol_init(fastd_context *ctx, fastd_config *conf) {
- if (conf->n_floating > 1)
+static fastd_protocol_config* protocol_init(fastd_context *ctx) {
+ if (ctx->conf->n_floating > 1)
exit_error(ctx, "with protocol `null' use can't define more than one floating peer");
+
+ return NULL;
+}
+
+static void protocol_peer_configure(fastd_context *ctx, fastd_peer_config *peer_conf) {
+}
+
+static void protocol_peer_config_purged(fastd_context *ctx, fastd_peer_config *peer_conf) {
}
static size_t protocol_max_packet_size(fastd_context *ctx) {
@@ -131,6 +139,8 @@ const fastd_protocol fastd_protocol_null = {
.name = "null",
.init = protocol_init,
+ .peer_configure = protocol_peer_configure,
+ .peer_config_purged = protocol_peer_config_purged,
.max_packet_size = protocol_max_packet_size,
.min_encrypt_head_space = protocol_min_head_space,