summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.c31
-rw-r--r--src/config.l2
-rw-r--r--src/config.y22
-rw-r--r--src/fastd.h6
-rw-r--r--src/peer.c120
5 files changed, 179 insertions, 2 deletions
diff --git a/src/config.c b/src/config.c
index 0d9a62b..f18d975 100644
--- a/src/config.c
+++ b/src/config.c
@@ -79,6 +79,13 @@ static void default_config(fastd_config *conf) {
conf->on_down = NULL;
conf->on_down_dir = NULL;
+
+ conf->on_establish = NULL;
+ conf->on_establish_dir = NULL;
+
+ conf->on_disestablish = NULL;
+ conf->on_disestablish_dir = NULL;
+
}
static bool config_match(const char *opt, ...) {
@@ -506,6 +513,26 @@ void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *con
continue;
}
+ IF_OPTION_ARG("--on-establish") {
+ free(conf->on_establish);
+ free(conf->on_establish_dir);
+
+ conf->on_establish = strdup(arg);
+ conf->on_establish_dir = get_current_dir_name();
+
+ continue;
+ }
+
+ IF_OPTION_ARG("--on-disestablish") {
+ free(conf->on_disestablish);
+ free(conf->on_disestablish_dir);
+
+ conf->on_disestablish = strdup(arg);
+ conf->on_disestablish_dir = get_current_dir_name();
+
+ continue;
+ }
+
IF_OPTION("--generate-key") {
keygen = true;
continue;
@@ -640,5 +667,9 @@ void fastd_config_release(fastd_context *ctx, fastd_config *conf) {
free(conf->on_up_dir);
free(conf->on_down);
free(conf->on_down_dir);
+ free(conf->on_establish);
+ free(conf->on_establish_dir);
+ free(conf->on_disestablish);
+ free(conf->on_disestablish_dir);
free(conf->protocol_config);
}
diff --git a/src/config.l b/src/config.l
index c352a1d..c2f771a 100644
--- a/src/config.l
+++ b/src/config.l
@@ -71,6 +71,8 @@ tun { UPDATE_LOCATION; return TOK_TUN; }
on { UPDATE_LOCATION; return TOK_ON; }
up { UPDATE_LOCATION; return TOK_UP; }
down { UPDATE_LOCATION; return TOK_DOWN; }
+establish { UPDATE_LOCATION; return TOK_ESTABLISH; }
+disestablish { UPDATE_LOCATION; return TOK_DISESTABLISH; }
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 0af0980..ac5f808 100644
--- a/src/config.y
+++ b/src/config.y
@@ -73,6 +73,8 @@
%token TOK_ON
%token TOK_UP
%token TOK_DOWN
+%token TOK_ESTABLISH
+%token TOK_DISESTABLISH
%token TOK_PEERS
%token TOK_FROM
%token TOK_LOG
@@ -131,6 +133,8 @@ statement: TOK_LOG log ';'
| TOK_SECRET secret ';'
| TOK_ON TOK_UP on_up ';'
| TOK_ON TOK_DOWN on_down ';'
+ | TOK_ON TOK_ESTABLISH on_establish ';'
+ | TOK_ON TOK_DISESTABLISH on_disestablish ';'
| TOK_PEER peer '{' peer_conf '}'
| TOK_PEER_TO_PEER peer_to_peer ';'
| TOK_INCLUDE include ';'
@@ -212,6 +216,24 @@ on_down: TOK_STRING {
}
;
+on_establish: TOK_STRING {
+ free(conf->on_establish);
+ free(conf->on_establish_dir);
+
+ conf->on_establish = strdup($1->str);
+ conf->on_establish_dir = get_current_dir_name();
+ }
+ ;
+
+on_disestablish: TOK_STRING {
+ free(conf->on_disestablish);
+ free(conf->on_disestablish_dir);
+
+ conf->on_disestablish = strdup($1->str);
+ conf->on_disestablish_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.h b/src/fastd.h
index 1e78dc7..e3d3b02 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -115,6 +115,12 @@ struct _fastd_config {
char *on_down;
char *on_down_dir;
+
+ char *on_establish;
+ char *on_establish_dir;
+
+ char *on_disestablish;
+ char *on_disestablish_dir;
};
struct _fastd_context {
diff --git a/src/peer.c b/src/peer.c
index 3566cfc..fd8577b 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -29,8 +29,120 @@
#include "peer.h"
#include "task.h"
+#include <arpa/inet.h>
+#include <unistd.h>
+
+
+static void on_establish(fastd_context *ctx, fastd_peer *peer) {
+ if (!ctx->conf->on_establish)
+ return;
+
+ char *cwd = get_current_dir_name();
+ chdir(ctx->conf->on_establish_dir);
+
+ setenv("INTERFACE", ctx->ifname, 1);
+
+ char buf[INET6_ADDRSTRLEN];
+ snprintf(buf, sizeof(buf), "%u", ctx->conf->mtu);
+ setenv("MTU", buf, 1);
+
+ if (peer->config && peer->config->name)
+ setenv("PEER_NAME", peer->config->name, 1);
+ else
+ unsetenv("PEER_NAME");
+
+ switch(peer->address.sa.sa_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &peer->address.in.sin_addr, buf, sizeof(buf));
+ setenv("PEER_ADDRESS", buf, 1);
+
+ snprintf(buf, sizeof(buf), "%u", ntohs(peer->address.in.sin_port));
+ setenv("PEER_PORT", buf, 1);
+
+ break;
+
+ case AF_INET6:
+ inet_ntop(AF_INET6, &peer->address.in6.sin6_addr, buf, sizeof(buf));
+ setenv("PEER_ADDRESS", buf, 1);
+
+ snprintf(buf, sizeof(buf), "%u", ntohs(peer->address.in6.sin6_port));
+ setenv("PEER_PORT", buf, 1);
+
+ break;
+
+ default:
+ unsetenv("PEER_ADDRESS");
+ unsetenv("PEER_PORT");
+ }
+
+ int ret = system(ctx->conf->on_establish);
+
+ if (WIFSIGNALED(ret))
+ pr_error(ctx, "on-establish command exited with signal %i", WTERMSIG(ret));
+ else if(ret)
+ pr_warn(ctx, "on-establish command exited with status %i", WEXITSTATUS(ret));
+
+ chdir(cwd);
+ free(cwd);
+}
+
+static void on_disestablish(fastd_context *ctx, fastd_peer *peer) {
+ if (!ctx->conf->on_disestablish)
+ return;
+
+ char *cwd = get_current_dir_name();
+ chdir(ctx->conf->on_disestablish_dir);
+
+ setenv("INTERFACE", ctx->ifname, 1);
+
+ char buf[INET6_ADDRSTRLEN];
+ snprintf(buf, sizeof(buf), "%u", ctx->conf->mtu);
+ setenv("MTU", buf, 1);
+
+ if (peer->config && peer->config->name)
+ setenv("PEER_NAME", peer->config->name, 1);
+ else
+ unsetenv("PEER_NAME");
+
+ switch(peer->address.sa.sa_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &peer->address.in.sin_addr, buf, sizeof(buf));
+ setenv("PEER_ADDRESS", buf, 1);
+
+ snprintf(buf, sizeof(buf), "%u", ntohs(peer->address.in.sin_port));
+ setenv("PEER_PORT", buf, 1);
+
+ break;
+
+ case AF_INET6:
+ inet_ntop(AF_INET6, &peer->address.in6.sin6_addr, buf, sizeof(buf));
+ setenv("PEER_ADDRESS", buf, 1);
+
+ snprintf(buf, sizeof(buf), "%u", ntohs(peer->address.in6.sin6_port));
+ setenv("PEER_PORT", buf, 1);
+
+ break;
+
+ default:
+ unsetenv("PEER_ADDRESS");
+ unsetenv("PEER_PORT");
+ }
+
+ int ret = system(ctx->conf->on_disestablish);
+
+ if (WIFSIGNALED(ret))
+ pr_error(ctx, "on-disestablish command exited with signal %i", WTERMSIG(ret));
+ else if(ret)
+ pr_warn(ctx, "on-disestablish command exited with status %i", WEXITSTATUS(ret));
+
+ chdir(cwd);
+ free(cwd);
+}
static inline void reset_peer(fastd_context *ctx, fastd_peer *peer) {
+ if (peer->state == STATE_ESTABLISHED)
+ on_disestablish(ctx, peer);
+
ctx->conf->protocol->free_peer_state(ctx, peer);
peer->protocol_state = NULL;
@@ -217,11 +329,13 @@ fastd_peer* fastd_peer_set_established_merge(fastd_context *ctx, fastd_peer *per
ctx->conf->protocol->free_peer_state(ctx, perm_peer);
+ if (perm_peer->state == STATE_ESTABLISHED)
+ on_disestablish(ctx, perm_peer);
+
perm_peer->address = temp_peer->address;
perm_peer->state = STATE_ESTABLISHED;
perm_peer->seen = temp_peer->seen;
perm_peer->protocol_state = temp_peer->protocol_state;
-
temp_peer->protocol_state = NULL;
int i;
@@ -235,6 +349,7 @@ fastd_peer* fastd_peer_set_established_merge(fastd_context *ctx, fastd_peer *per
fastd_peer_reset(ctx, temp_peer);
+ on_establish(ctx, perm_peer);
pr_info(ctx, "Connection with %P established.", perm_peer);
return perm_peer;
@@ -243,8 +358,9 @@ fastd_peer* fastd_peer_set_established_merge(fastd_context *ctx, fastd_peer *per
void fastd_peer_set_established(fastd_context *ctx, fastd_peer *peer) {
switch(peer->state) {
case STATE_WAIT:
- pr_info(ctx, "Connection with %P established.", peer);
peer->state = STATE_ESTABLISHED;
+ on_establish(ctx, peer);
+ pr_info(ctx, "Connection with %P established.", peer);
break;
case STATE_TEMP: