Get rid of some duplicate code for calling shell commands

This commit is contained in:
Matthias Schiffer 2013-02-25 04:48:11 +01:00
parent b3ba14d473
commit 698ede3ce4
5 changed files with 110 additions and 147 deletions

View file

@ -26,6 +26,7 @@ add_executable(fastd
queue.c queue.c
random.c random.c
resolve.c resolve.c
shell.c
task.c task.c
protocol_ec25519_fhmqvc.c protocol_ec25519_fhmqvc.c
${FLEX_fastd_config_lex_OUTPUTS} ${FLEX_fastd_config_lex_OUTPUTS}

View file

@ -563,56 +563,18 @@ void fastd_handle_receive(fastd_context_t *ctx, fastd_peer_t *peer, fastd_buffer
} }
} }
static void on_up(fastd_context_t *ctx) { static inline void on_up(fastd_context_t *ctx) {
if (!ctx->conf->on_up) if (!ctx->conf->on_up)
return; return;
char *cwd = get_current_dir_name(); fastd_shell_exec(ctx, NULL, ctx->conf->on_up, ctx->conf->on_up_dir, NULL);
if (!chdir(ctx->conf->on_up_dir)) {
setenv("INTERFACE", ctx->ifname, 1);
int ret = system(ctx->conf->on_up);
if (WIFSIGNALED(ret))
pr_error(ctx, "on-up command exited with signal %i", WTERMSIG(ret));
else if(ret)
pr_warn(ctx, "on-up command exited with status %i", WEXITSTATUS(ret));
if (chdir(cwd))
pr_error(ctx, "can't chdir to `%s': %s", cwd, strerror(errno));
}
else {
pr_error(ctx, "can't chdir to `%s': %s", ctx->conf->on_up_dir, strerror(errno));
}
free(cwd);
} }
static void on_down(fastd_context_t *ctx) { static inline void on_down(fastd_context_t *ctx) {
if (!ctx->conf->on_down) if (!ctx->conf->on_down)
return; return;
char *cwd = get_current_dir_name(); fastd_shell_exec(ctx, NULL, ctx->conf->on_down, ctx->conf->on_down_dir, NULL);
if(!chdir(ctx->conf->on_down_dir)) {
setenv("INTERFACE", ctx->ifname, 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));
if (chdir(cwd))
pr_error(ctx, "can't chdir to `%s': %s", cwd, strerror(errno));
}
else {
pr_error(ctx, "can't chdir to `%s': %s", ctx->conf->on_down_dir, strerror(errno));
}
free(cwd);
} }
static fastd_peer_group_t* init_peer_group(const fastd_peer_group_config_t *config, fastd_peer_group_t *parent) { static fastd_peer_group_t* init_peer_group(const fastd_peer_group_config_t *config, fastd_peer_group_t *parent) {

View file

@ -327,6 +327,8 @@ void fastd_reconfigure(fastd_context_t *ctx, fastd_config_t *conf);
void fastd_cap_init(fastd_context_t *ctx); void fastd_cap_init(fastd_context_t *ctx);
void fastd_cap_drop(fastd_context_t *ctx); void fastd_cap_drop(fastd_context_t *ctx);
bool fastd_shell_exec(fastd_context_t *ctx, const fastd_peer_t *peer, const char *command, const char *dir, int *ret);
void fastd_random_bytes(fastd_context_t *ctx, void *buffer, size_t len, bool secure); void fastd_random_bytes(fastd_context_t *ctx, void *buffer, size_t len, bool secure);
static inline int fastd_rand(fastd_context_t *ctx, int min, int max) { static inline int fastd_rand(fastd_context_t *ctx, int min, int max) {

View file

@ -32,118 +32,18 @@
#include <arpa/inet.h> #include <arpa/inet.h>
static void on_establish(fastd_context_t *ctx, fastd_peer_t *peer) { static inline void on_establish(fastd_context_t *ctx, const fastd_peer_t *peer) {
if (!ctx->conf->on_establish) if (!ctx->conf->on_establish)
return; return;
char *cwd = get_current_dir_name(); fastd_shell_exec(ctx, peer, ctx->conf->on_establish, ctx->conf->on_establish_dir, NULL);
if(!chdir(ctx->conf->on_establish_dir)) {
setenv("INTERFACE", ctx->ifname, 1);
char buf[INET6_ADDRSTRLEN];
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));
if(chdir(cwd))
pr_error(ctx, "can't chdir to `%s': %s", cwd, strerror(errno));
}
else {
pr_error(ctx, "can't chdir to `%s': %s", ctx->conf->on_establish_dir, strerror(errno));
}
free(cwd);
} }
static void on_disestablish(fastd_context_t *ctx, fastd_peer_t *peer) { static inline void on_disestablish(fastd_context_t *ctx, const fastd_peer_t *peer) {
if (!ctx->conf->on_disestablish) if (!ctx->conf->on_disestablish)
return; return;
char *cwd = get_current_dir_name(); fastd_shell_exec(ctx, peer, ctx->conf->on_disestablish, ctx->conf->on_disestablish_dir, NULL);
if(!chdir(ctx->conf->on_disestablish_dir)) {
setenv("INTERFACE", ctx->ifname, 1);
char buf[INET6_ADDRSTRLEN];
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));
if(chdir(cwd))
pr_error(ctx, "can't chdir to `%s': %s", cwd, strerror(errno));
}
else {
pr_error(ctx, "can't chdir to `%s': %s", ctx->conf->on_disestablish_dir, strerror(errno));
}
free(cwd);
} }
static inline void free_socket(fastd_context_t *ctx, fastd_peer_t *peer) { static inline void free_socket(fastd_context_t *ctx, fastd_peer_t *peer) {
@ -159,7 +59,7 @@ static inline void free_socket(fastd_context_t *ctx, fastd_peer_t *peer) {
} }
} }
static bool has_group_config_constraints(const fastd_peer_group_config_t *group) { static inline bool has_group_config_constraints(const fastd_peer_group_config_t *group) {
for (; group; group = group->parent) { for (; group; group = group->parent) {
if (group->max_connections) if (group->max_connections)
return true; return true;

98
src/shell.c Normal file
View file

@ -0,0 +1,98 @@
/*
Copyright (c) 2012-2013, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _GNU_SOURCE
#include "peer.h"
#include <arpa/inet.h>
bool fastd_shell_exec(fastd_context_t *ctx, const fastd_peer_t *peer, const char *command, const char *dir, int *ret) {
int result = -1;
bool ok = false;
char *cwd = get_current_dir_name();
if(!chdir(dir)) {
setenv("INTERFACE", ctx->ifname, 1);
char buf[INET6_ADDRSTRLEN];
if (peer && peer->config && peer->config->name)
setenv("PEER_NAME", peer->config->name, 1);
else
unsetenv("PEER_NAME");
switch(peer ? peer->address.sa.sa_family : AF_UNSPEC) {
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");
}
result = system(command);
if (ret) {
*ret = result;
ok = true;
}
else {
if (WIFSIGNALED(result))
pr_error(ctx, "command exited with signal %i", WTERMSIG(result));
else if (result)
pr_warn(ctx, "command exited with status %i", WEXITSTATUS(ret));
else
ok = true;
}
if(chdir(cwd))
pr_error(ctx, "can't chdir to `%s': %s", cwd, strerror(errno));
}
else {
pr_error(ctx, "can't chdir to `%s': %s", dir, strerror(errno));
}
free(cwd);
return ok;
}