mirror of
https://github.com/neocturne/fastd.git
synced 2025-05-14 20:25:08 +02:00
Cleanly shutdown; add on-down command
This commit is contained in:
parent
329d15d50c
commit
7b2cfb422a
7 changed files with 141 additions and 20 deletions
32
src/config.c
32
src/config.c
|
@ -41,10 +41,10 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
extern fastd_protocol fastd_protocol_null;
|
extern const fastd_protocol fastd_protocol_null;
|
||||||
|
|
||||||
#ifdef WITH_PROTOCOL_ECFXP
|
#ifdef WITH_PROTOCOL_ECFXP
|
||||||
extern fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
|
extern const fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,6 +76,9 @@ static void default_config(fastd_config *conf) {
|
||||||
|
|
||||||
conf->on_up = NULL;
|
conf->on_up = NULL;
|
||||||
conf->on_up_dir = NULL;
|
conf->on_up_dir = NULL;
|
||||||
|
|
||||||
|
conf->on_down = NULL;
|
||||||
|
conf->on_down_dir = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool config_match(const char *opt, ...) {
|
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;
|
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") {
|
IF_OPTION("--generate-key") {
|
||||||
keygen = true;
|
keygen = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -614,3 +627,18 @@ void fastd_reconfigure(fastd_context *ctx, fastd_config *conf) {
|
||||||
count_peers(ctx, 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);
|
||||||
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ tap { UPDATE_LOCATION; return TOK_TAP; }
|
||||||
tun { UPDATE_LOCATION; return TOK_TUN; }
|
tun { UPDATE_LOCATION; return TOK_TUN; }
|
||||||
on { UPDATE_LOCATION; return TOK_ON; }
|
on { UPDATE_LOCATION; return TOK_ON; }
|
||||||
up { UPDATE_LOCATION; return TOK_UP; }
|
up { UPDATE_LOCATION; return TOK_UP; }
|
||||||
|
down { UPDATE_LOCATION; return TOK_DOWN; }
|
||||||
peers { UPDATE_LOCATION; return TOK_PEERS; }
|
peers { UPDATE_LOCATION; return TOK_PEERS; }
|
||||||
from { UPDATE_LOCATION; return TOK_FROM; }
|
from { UPDATE_LOCATION; return TOK_FROM; }
|
||||||
log { UPDATE_LOCATION; return TOK_LOG; }
|
log { UPDATE_LOCATION; return TOK_LOG; }
|
||||||
|
|
15
src/config.y
15
src/config.y
|
@ -72,6 +72,7 @@
|
||||||
%token TOK_TUN
|
%token TOK_TUN
|
||||||
%token TOK_ON
|
%token TOK_ON
|
||||||
%token TOK_UP
|
%token TOK_UP
|
||||||
|
%token TOK_DOWN
|
||||||
%token TOK_PEERS
|
%token TOK_PEERS
|
||||||
%token TOK_FROM
|
%token TOK_FROM
|
||||||
%token TOK_LOG
|
%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);
|
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
|
#ifdef WITH_PROTOCOL_ECFXP
|
||||||
extern fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
|
extern const fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +130,7 @@ statement: TOK_LOG log ';'
|
||||||
| TOK_PROTOCOL protocol ';'
|
| TOK_PROTOCOL protocol ';'
|
||||||
| TOK_SECRET secret ';'
|
| TOK_SECRET secret ';'
|
||||||
| TOK_ON TOK_UP on_up ';'
|
| TOK_ON TOK_UP on_up ';'
|
||||||
|
| TOK_ON TOK_DOWN on_down ';'
|
||||||
| TOK_PEER peer '{' peer_conf '}'
|
| TOK_PEER peer '{' peer_conf '}'
|
||||||
| TOK_PEER_TO_PEER peer_to_peer ';'
|
| TOK_PEER_TO_PEER peer_to_peer ';'
|
||||||
| TOK_INCLUDE include ';'
|
| 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 {
|
peer: maybe_string {
|
||||||
fastd_peer_config_new(ctx, conf);
|
fastd_peer_config_new(ctx, conf);
|
||||||
conf->peers->name = strdup($1->str);
|
conf->peers->name = strdup($1->str);
|
||||||
|
|
94
src/fastd.c
94
src/fastd.c
|
@ -43,22 +43,35 @@
|
||||||
|
|
||||||
|
|
||||||
static bool sighup = false;
|
static bool sighup = false;
|
||||||
|
static bool terminate = false;
|
||||||
|
|
||||||
|
|
||||||
static void on_sighup(int signo) {
|
static void on_sighup(int signo) {
|
||||||
sighup = true;
|
sighup = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_terminate(int signo) {
|
||||||
|
terminate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void init_signals(fastd_context *ctx) {
|
static void init_signals(fastd_context *ctx) {
|
||||||
struct sigaction action;
|
struct sigaction action;
|
||||||
|
|
||||||
action.sa_handler = on_sighup;
|
|
||||||
action.sa_flags = 0;
|
action.sa_flags = 0;
|
||||||
sigemptyset(&action.sa_mask);
|
sigemptyset(&action.sa_mask);
|
||||||
|
|
||||||
|
action.sa_handler = on_sighup;
|
||||||
if(sigaction(SIGHUP, &action, NULL))
|
if(sigaction(SIGHUP, &action, NULL))
|
||||||
exit_errno(ctx, "sigaction");
|
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) {
|
static void init_tuntap(fastd_context *ctx) {
|
||||||
|
@ -93,10 +106,17 @@ static void init_tuntap(fastd_context *ctx) {
|
||||||
|
|
||||||
ctx->ifname = strdup(ifr.ifr_name);
|
ctx->ifname = strdup(ifr.ifr_name);
|
||||||
|
|
||||||
pr_debug(ctx, "Tun/tap device initialized.");
|
pr_debug(ctx, "tun/tap device initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_socket(fastd_context *ctx) {
|
static void close_tuntap(fastd_context *ctx) {
|
||||||
|
if(close(ctx->tunfd))
|
||||||
|
warn_errno(ctx, "closing tun/tap: close");
|
||||||
|
|
||||||
|
free(ctx->ifname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_sockets(fastd_context *ctx) {
|
||||||
struct sockaddr_in addr_in = ctx->conf->bind_addr_in;
|
struct sockaddr_in addr_in = ctx->conf->bind_addr_in;
|
||||||
struct sockaddr_in6 addr_in6 = ctx->conf->bind_addr_in6;
|
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...");
|
pr_debug(ctx, "Initializing IPv6 socket...");
|
||||||
|
|
||||||
if ((ctx->sock6fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
if ((ctx->sock6fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||||||
if (ctx->sockfd > 0)
|
if (ctx->sockfd >= 0)
|
||||||
warn_errno(ctx, "socket");
|
warn_errno(ctx, "socket");
|
||||||
else
|
else
|
||||||
exit_errno(ctx, "socket");
|
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) {
|
static void on_up(fastd_context *ctx) {
|
||||||
if (!ctx->conf->on_up)
|
if (!ctx->conf->on_up)
|
||||||
return;
|
return;
|
||||||
|
@ -178,6 +210,30 @@ static void on_up(fastd_context *ctx) {
|
||||||
free(cwd);
|
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) {
|
static void init_peers(fastd_context *ctx) {
|
||||||
fastd_peer_config *peer_conf;
|
fastd_peer_config *peer_conf;
|
||||||
for (peer_conf = ctx->conf->peers; peer_conf; peer_conf = peer_conf->next) {
|
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) {
|
static void update_time(fastd_context *ctx) {
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ctx->now);
|
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);
|
fastd_random_bytes(&ctx, &ctx.randseed, sizeof(ctx.randseed), false);
|
||||||
|
|
||||||
|
init_signals(&ctx);
|
||||||
|
|
||||||
fastd_config conf;
|
fastd_config conf;
|
||||||
fastd_configure(&ctx, &conf, argc, argv);
|
fastd_configure(&ctx, &conf, argc, argv);
|
||||||
ctx.conf = &conf;
|
ctx.conf = &conf;
|
||||||
|
|
||||||
conf.protocol_config = conf.protocol->init(&ctx);
|
conf.protocol_config = conf.protocol->init(&ctx);
|
||||||
|
|
||||||
init_signals(&ctx);
|
|
||||||
|
|
||||||
update_time(&ctx);
|
update_time(&ctx);
|
||||||
|
|
||||||
|
init_tuntap(&ctx);
|
||||||
|
init_sockets(&ctx);
|
||||||
|
|
||||||
init_peers(&ctx);
|
init_peers(&ctx);
|
||||||
|
|
||||||
init_tuntap(&ctx);
|
|
||||||
init_socket(&ctx);
|
|
||||||
|
|
||||||
on_up(&ctx);
|
on_up(&ctx);
|
||||||
|
|
||||||
while (1) {
|
while (!terminate) {
|
||||||
handle_tasks(&ctx);
|
handle_tasks(&ctx);
|
||||||
handle_input(&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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ struct _fastd_config {
|
||||||
|
|
||||||
bool peer_to_peer;
|
bool peer_to_peer;
|
||||||
|
|
||||||
fastd_protocol *protocol;
|
const fastd_protocol *protocol;
|
||||||
char *secret;
|
char *secret;
|
||||||
unsigned key_valid;
|
unsigned key_valid;
|
||||||
unsigned key_refresh;
|
unsigned key_refresh;
|
||||||
|
@ -112,6 +112,9 @@ struct _fastd_config {
|
||||||
|
|
||||||
char *on_up;
|
char *on_up;
|
||||||
char *on_up_dir;
|
char *on_up_dir;
|
||||||
|
|
||||||
|
char *on_down;
|
||||||
|
char *on_down_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _fastd_context {
|
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);
|
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_configure(fastd_context *ctx, fastd_config *conf, int argc, char *const argv[]);
|
||||||
void fastd_reconfigure(fastd_context *ctx, fastd_config *conf);
|
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);
|
void fastd_random_bytes(fastd_context *ctx, void *buffer, size_t len, bool secure);
|
||||||
|
|
||||||
|
|
12
src/peer.c
12
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) {
|
for (peer = ctx->peers; peer; peer = next) {
|
||||||
next = peer->next;
|
next = peer->next;
|
||||||
|
|
||||||
if (peer->config == conf) {
|
if (peer->config == conf)
|
||||||
reset_peer(ctx, peer);
|
fastd_peer_delete(ctx, peer);
|
||||||
delete_peer(ctx, peer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->conf->protocol->peer_config_purged(ctx, conf);
|
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);
|
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) {
|
static fastd_peer* add_peer(fastd_context *ctx) {
|
||||||
fastd_peer *peer = malloc(sizeof(fastd_peer));
|
fastd_peer *peer = malloc(sizeof(fastd_peer));
|
||||||
|
|
||||||
|
|
|
@ -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);
|
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_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(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_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);
|
fastd_peer* fastd_peer_set_established_merge(fastd_context *ctx, fastd_peer *perm_peer, fastd_peer *temp_peer);
|
||||||
|
|
Loading…
Add table
Reference in a new issue