summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-04-05 13:17:02 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-04-05 13:17:02 +0200
commit7b2cfb422af6a957aa90e22bd6e9b19f16b30319 (patch)
treeaaa2fd85662309af45ab4fced6b332445bdf0f10
parent329d15d50c54a69ce8e2be0865124744c0bf3428 (diff)
downloadfastd-7b2cfb422af6a957aa90e22bd6e9b19f16b30319.tar
fastd-7b2cfb422af6a957aa90e22bd6e9b19f16b30319.zip
Cleanly shutdown; add on-down command
-rw-r--r--src/config.c32
-rw-r--r--src/config.l1
-rw-r--r--src/config.y15
-rw-r--r--src/fastd.c94
-rw-r--r--src/fastd.h6
-rw-r--r--src/peer.c12
-rw-r--r--src/peer.h1
7 files changed, 141 insertions, 20 deletions
diff --git a/src/config.c b/src/config.c
index 7725c40..0d9a62b 100644
--- a/src/config.c
+++ b/src/config.c
@@ -41,10 +41,10 @@
#include <sys/types.h>
-extern fastd_protocol fastd_protocol_null;
+extern const fastd_protocol fastd_protocol_null;
#ifdef WITH_PROTOCOL_ECFXP
-extern fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
+extern const fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
#endif
@@ -76,6 +76,9 @@ static void default_config(fastd_config *conf) {
conf->on_up = NULL;
conf->on_up_dir = NULL;
+
+ conf->on_down = NULL;
+ conf->on_down_dir = NULL;
}
static bool config_match(const char *opt, ...) {
@@ -493,6 +496,16 @@ void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *con
continue;
}
+ IF_OPTION_ARG("--on-down") {
+ free(conf->on_down);
+ free(conf->on_down_dir);
+
+ conf->on_down = strdup(arg);
+ conf->on_down_dir = get_current_dir_name();
+
+ continue;
+ }
+
IF_OPTION("--generate-key") {
keygen = true;
continue;
@@ -614,3 +627,18 @@ void fastd_reconfigure(fastd_context *ctx, fastd_config *conf) {
count_peers(ctx, conf);
}
+
+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);
+
+ free(conf->ifname);
+ free(conf->secret);
+ free(conf->on_up);
+ free(conf->on_up_dir);
+ free(conf->on_down);
+ free(conf->on_down_dir);
+ free(conf->protocol_config);
+}
diff --git a/src/config.l b/src/config.l
index 49c0117..1de0457 100644
--- a/src/config.l
+++ b/src/config.l
@@ -70,6 +70,7 @@ tap { UPDATE_LOCATION; return TOK_TAP; }
tun { UPDATE_LOCATION; return TOK_TUN; }
on { UPDATE_LOCATION; return TOK_ON; }
up { UPDATE_LOCATION; return TOK_UP; }
+down { UPDATE_LOCATION; return TOK_DOWN; }
peers { UPDATE_LOCATION; return TOK_PEERS; }
from { UPDATE_LOCATION; return TOK_FROM; }
log { UPDATE_LOCATION; return TOK_LOG; }
diff --git a/src/config.y b/src/config.y
index 332ad77..0af0980 100644
--- a/src/config.y
+++ b/src/config.y
@@ -72,6 +72,7 @@
%token TOK_TUN
%token TOK_ON
%token TOK_UP
+%token TOK_DOWN
%token TOK_PEERS
%token TOK_FROM
%token TOK_LOG
@@ -97,10 +98,10 @@
void fastd_config_error(YYLTYPE *loc, fastd_context *ctx, fastd_config *conf, const char *filename, int depth, char *s);
- extern fastd_protocol fastd_protocol_null;
+ extern const fastd_protocol fastd_protocol_null;
#ifdef WITH_PROTOCOL_ECFXP
- extern fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
+ extern const fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
#endif
}
@@ -129,6 +130,7 @@ statement: TOK_LOG log ';'
| TOK_PROTOCOL protocol ';'
| TOK_SECRET secret ';'
| TOK_ON TOK_UP on_up ';'
+ | TOK_ON TOK_DOWN on_down ';'
| TOK_PEER peer '{' peer_conf '}'
| TOK_PEER_TO_PEER peer_to_peer ';'
| TOK_INCLUDE include ';'
@@ -201,6 +203,15 @@ on_up: TOK_STRING {
}
;
+on_down: TOK_STRING {
+ free(conf->on_down);
+ free(conf->on_down_dir);
+
+ conf->on_down = strdup($1->str);
+ conf->on_down_dir = get_current_dir_name();
+ }
+ ;
+
peer: maybe_string {
fastd_peer_config_new(ctx, conf);
conf->peers->name = strdup($1->str);
diff --git a/src/fastd.c b/src/fastd.c
index f38bf60..ca4edb8 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -43,22 +43,35 @@
static bool sighup = false;
+static bool terminate = false;
static void on_sighup(int signo) {
sighup = true;
}
+static void on_terminate(int signo) {
+ terminate = true;
+}
+
static void init_signals(fastd_context *ctx) {
struct sigaction action;
- action.sa_handler = on_sighup;
action.sa_flags = 0;
sigemptyset(&action.sa_mask);
+ action.sa_handler = on_sighup;
if(sigaction(SIGHUP, &action, NULL))
exit_errno(ctx, "sigaction");
+
+ action.sa_handler = on_terminate;
+ if(sigaction(SIGTERM, &action, NULL))
+ exit_errno(ctx, "sigaction");
+ if(sigaction(SIGQUIT, &action, NULL))
+ exit_errno(ctx, "sigaction");
+ if(sigaction(SIGINT, &action, NULL))
+ exit_errno(ctx, "sigaction");
}
static void init_tuntap(fastd_context *ctx) {
@@ -93,10 +106,17 @@ static void init_tuntap(fastd_context *ctx) {
ctx->ifname = strdup(ifr.ifr_name);
- pr_debug(ctx, "Tun/tap device initialized.");
+ pr_debug(ctx, "tun/tap device initialized.");
+}
+
+static void close_tuntap(fastd_context *ctx) {
+ if(close(ctx->tunfd))
+ warn_errno(ctx, "closing tun/tap: close");
+
+ free(ctx->ifname);
}
-static void init_socket(fastd_context *ctx) {
+static void init_sockets(fastd_context *ctx) {
struct sockaddr_in addr_in = ctx->conf->bind_addr_in;
struct sockaddr_in6 addr_in6 = ctx->conf->bind_addr_in6;
@@ -133,7 +153,7 @@ static void init_socket(fastd_context *ctx) {
pr_debug(ctx, "Initializing IPv6 socket...");
if ((ctx->sock6fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
- if (ctx->sockfd > 0)
+ if (ctx->sockfd >= 0)
warn_errno(ctx, "socket");
else
exit_errno(ctx, "socket");
@@ -154,6 +174,18 @@ static void init_socket(fastd_context *ctx) {
}
}
+static void close_sockets(fastd_context *ctx) {
+ if (ctx->sockfd >= 0) {
+ if(close(ctx->sockfd))
+ warn_errno(ctx, "closing IPv4 socket: close");
+ }
+
+ if (ctx->sock6fd >= 0) {
+ if(close(ctx->sock6fd))
+ warn_errno(ctx, "closing IPv6 socket: close");
+ }
+}
+
static void on_up(fastd_context *ctx) {
if (!ctx->conf->on_up)
return;
@@ -178,6 +210,30 @@ static void on_up(fastd_context *ctx) {
free(cwd);
}
+static void on_down(fastd_context *ctx) {
+ if (!ctx->conf->on_down)
+ return;
+
+ char *cwd = get_current_dir_name();
+ chdir(ctx->conf->on_down_dir);
+
+ setenv("INTERFACE", ctx->ifname, 1);
+
+ char buf[6];
+ snprintf(buf, 6, "%u", ctx->conf->mtu);
+ setenv("MTU", buf, 1);
+
+ int ret = system(ctx->conf->on_down);
+
+ if (WIFSIGNALED(ret))
+ pr_error(ctx, "on-down command exited with signal %i", WTERMSIG(ret));
+ else if(ret)
+ pr_warn(ctx, "on-down command exited with status %i", WEXITSTATUS(ret));
+
+ chdir(cwd);
+ free(cwd);
+}
+
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) {
@@ -188,6 +244,15 @@ static void init_peers(fastd_context *ctx) {
}
}
+static void delete_peers(fastd_context *ctx) {
+ fastd_peer *peer, *next;
+ for (peer = ctx->peers; peer; peer = next) {
+ next = peer->next;
+
+ fastd_peer_delete(ctx, peer);
+ }
+}
+
static void update_time(fastd_context *ctx) {
clock_gettime(CLOCK_MONOTONIC, &ctx->now);
}
@@ -500,24 +565,24 @@ int main(int argc, char *argv[]) {
fastd_random_bytes(&ctx, &ctx.randseed, sizeof(ctx.randseed), false);
+ init_signals(&ctx);
+
fastd_config conf;
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);
-
init_tuntap(&ctx);
- init_socket(&ctx);
+ init_sockets(&ctx);
+
+ init_peers(&ctx);
on_up(&ctx);
- while (1) {
+ while (!terminate) {
handle_tasks(&ctx);
handle_input(&ctx);
@@ -529,5 +594,14 @@ int main(int argc, char *argv[]) {
}
}
+ on_down(&ctx);
+
+ delete_peers(&ctx);
+
+ close_sockets(&ctx);
+ close_tuntap(&ctx);
+
+ fastd_config_release(&ctx, &conf);
+
return 0;
}
diff --git a/src/fastd.h b/src/fastd.h
index f07f108..1e78dc7 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -96,7 +96,7 @@ struct _fastd_config {
bool peer_to_peer;
- fastd_protocol *protocol;
+ const fastd_protocol *protocol;
char *secret;
unsigned key_valid;
unsigned key_refresh;
@@ -112,6 +112,9 @@ struct _fastd_config {
char *on_up;
char *on_up_dir;
+
+ char *on_down;
+ char *on_down_dir;
};
struct _fastd_context {
@@ -146,6 +149,7 @@ 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_config_release(fastd_context *ctx, fastd_config *conf);
void fastd_random_bytes(fastd_context *ctx, void *buffer, size_t len, bool secure);
diff --git a/src/peer.c b/src/peer.c
index 9bb900b..3566cfc 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -113,11 +113,8 @@ void fastd_peer_config_purge(fastd_context *ctx, fastd_peer_config *conf) {
for (peer = ctx->peers; peer; peer = next) {
next = peer->next;
- if (peer->config == conf) {
- reset_peer(ctx, peer);
- delete_peer(ctx, peer);
- continue;
- }
+ if (peer->config == conf)
+ fastd_peer_delete(ctx, peer);
}
ctx->conf->protocol->peer_config_purged(ctx, conf);
@@ -169,6 +166,11 @@ void fastd_peer_reset(fastd_context *ctx, fastd_peer *peer) {
setup_peer(ctx, peer);
}
+void fastd_peer_delete(fastd_context *ctx, fastd_peer *peer) {
+ reset_peer(ctx, peer);
+ delete_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 94b9026..4afa9a1 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -79,6 +79,7 @@ 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);
+void fastd_peer_delete(fastd_context *ctx, fastd_peer *peer);
fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *conf);
fastd_peer* fastd_peer_add_temp(fastd_context *ctx, const fastd_peer_address *address);
fastd_peer* fastd_peer_set_established_merge(fastd_context *ctx, fastd_peer *perm_peer, fastd_peer *temp_peer);