summaryrefslogtreecommitdiffstats
path: root/src/peer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/peer.c')
-rw-r--r--src/peer.c120
1 files changed, 118 insertions, 2 deletions
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: