Add on-establish and on-disestablish commands

This commit is contained in:
Matthias Schiffer 2012-04-05 20:38:30 +02:00
parent 9720307ab4
commit a6a5b5e00e
5 changed files with 179 additions and 2 deletions

View file

@ -79,6 +79,13 @@ static void default_config(fastd_config *conf) {
conf->on_down = NULL; conf->on_down = NULL;
conf->on_down_dir = 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, ...) { 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; 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") { IF_OPTION("--generate-key") {
keygen = true; keygen = true;
continue; continue;
@ -640,5 +667,9 @@ void fastd_config_release(fastd_context *ctx, fastd_config *conf) {
free(conf->on_up_dir); free(conf->on_up_dir);
free(conf->on_down); free(conf->on_down);
free(conf->on_down_dir); 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); free(conf->protocol_config);
} }

View file

@ -71,6 +71,8 @@ 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; } down { UPDATE_LOCATION; return TOK_DOWN; }
establish { UPDATE_LOCATION; return TOK_ESTABLISH; }
disestablish { UPDATE_LOCATION; return TOK_DISESTABLISH; }
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; }

View file

@ -73,6 +73,8 @@
%token TOK_ON %token TOK_ON
%token TOK_UP %token TOK_UP
%token TOK_DOWN %token TOK_DOWN
%token TOK_ESTABLISH
%token TOK_DISESTABLISH
%token TOK_PEERS %token TOK_PEERS
%token TOK_FROM %token TOK_FROM
%token TOK_LOG %token TOK_LOG
@ -131,6 +133,8 @@ statement: TOK_LOG log ';'
| 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_ON TOK_DOWN on_down ';'
| TOK_ON TOK_ESTABLISH on_establish ';'
| TOK_ON TOK_DISESTABLISH on_disestablish ';'
| 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 ';'
@ -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 { 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);

View file

@ -115,6 +115,12 @@ struct _fastd_config {
char *on_down; char *on_down;
char *on_down_dir; char *on_down_dir;
char *on_establish;
char *on_establish_dir;
char *on_disestablish;
char *on_disestablish_dir;
}; };
struct _fastd_context { struct _fastd_context {

View file

@ -29,8 +29,120 @@
#include "peer.h" #include "peer.h"
#include "task.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) { 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); ctx->conf->protocol->free_peer_state(ctx, peer);
peer->protocol_state = NULL; 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); 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->address = temp_peer->address;
perm_peer->state = STATE_ESTABLISHED; perm_peer->state = STATE_ESTABLISHED;
perm_peer->seen = temp_peer->seen; perm_peer->seen = temp_peer->seen;
perm_peer->protocol_state = temp_peer->protocol_state; perm_peer->protocol_state = temp_peer->protocol_state;
temp_peer->protocol_state = NULL; temp_peer->protocol_state = NULL;
int i; 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); fastd_peer_reset(ctx, temp_peer);
on_establish(ctx, perm_peer);
pr_info(ctx, "Connection with %P established.", perm_peer); pr_info(ctx, "Connection with %P established.", perm_peer);
return 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) { void fastd_peer_set_established(fastd_context *ctx, fastd_peer *peer) {
switch(peer->state) { switch(peer->state) {
case STATE_WAIT: case STATE_WAIT:
pr_info(ctx, "Connection with %P established.", peer);
peer->state = STATE_ESTABLISHED; peer->state = STATE_ESTABLISHED;
on_establish(ctx, peer);
pr_info(ctx, "Connection with %P established.", peer);
break; break;
case STATE_TEMP: case STATE_TEMP: