From 4020ee614cfe248010764028902d80b4a9091f7d Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 26 Apr 2014 20:30:05 +0200 Subject: Revise shell command API --- src/fastd.c | 8 +- src/fastd.h | 2 +- src/peer.c | 89 +++++++++++++++++- src/peer.h | 3 + src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h | 2 +- src/protocols/ec25519_fhmqvc/handshake.c | 2 +- src/protocols/ec25519_fhmqvc/util.c | 8 +- src/shell.c | 128 +++++++++++--------------- src/shell.h | 9 +- src/types.h | 1 + 10 files changed, 161 insertions(+), 91 deletions(-) diff --git a/src/fastd.c b/src/fastd.c index c9f03f0..2b08a7e 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -276,19 +276,19 @@ void fastd_handle_receive(fastd_peer_t *peer, fastd_buffer_t buffer) { } static inline void on_pre_up(void) { - fastd_shell_command_exec(&conf.on_pre_up, NULL, NULL, NULL); + fastd_shell_command_exec(&conf.on_pre_up, NULL); } static inline void on_up(void) { - fastd_shell_command_exec(&conf.on_up, NULL, NULL, NULL); + fastd_shell_command_exec(&conf.on_up, NULL); } static inline void on_down(void) { - fastd_shell_command_exec(&conf.on_down, NULL, NULL, NULL); + fastd_shell_command_exec(&conf.on_down, NULL); } static inline void on_post_down(void) { - fastd_shell_command_exec(&conf.on_post_down, NULL, NULL, NULL); + fastd_shell_command_exec(&conf.on_post_down, NULL); } static fastd_peer_group_t* init_peer_group(const fastd_peer_group_config_t *config, fastd_peer_group_t *parent) { diff --git a/src/fastd.h b/src/fastd.h index f12d036..838ce94 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -70,7 +70,7 @@ struct fastd_protocol { void (*generate_key)(void); void (*show_key)(void); - void (*set_shell_env)(const fastd_peer_t *peer); + void (*set_shell_env)(fastd_shell_env_t *env, const fastd_peer_t *peer); bool (*describe_peer)(const fastd_peer_t *peer, char *buf, size_t len); }; diff --git a/src/peer.c b/src/peer.c index 879d3a7..860cf1d 100644 --- a/src/peer.c +++ b/src/peer.c @@ -32,12 +32,88 @@ #include +void fastd_peer_set_shell_env(fastd_shell_env_t *env, const fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr) { + /* both INET6_ADDRSTRLEN and IFNAMESIZE already include space for the zero termination, so there is no need to add space for the '%' here. */ + char buf[INET6_ADDRSTRLEN+IF_NAMESIZE]; + + fastd_shell_env_set(env, "PEER_NAME", (peer && peer->config) ? peer->config->name : NULL); + + switch(local_addr ? local_addr->sa.sa_family : AF_UNSPEC) { + case AF_INET: + inet_ntop(AF_INET, &local_addr->in.sin_addr, buf, sizeof(buf)); + fastd_shell_env_set(env, "LOCAL_ADDRESS", buf); + + snprintf(buf, sizeof(buf), "%u", ntohs(local_addr->in.sin_port)); + fastd_shell_env_set(env, "LOCAL_PORT", buf); + + break; + + case AF_INET6: + inet_ntop(AF_INET6, &local_addr->in6.sin6_addr, buf, sizeof(buf)); + + if (IN6_IS_ADDR_LINKLOCAL(&local_addr->in6.sin6_addr)) { + if (if_indextoname(local_addr->in6.sin6_scope_id, buf+strlen(buf)+1)) + buf[strlen(buf)] = '%'; + } + + fastd_shell_env_set(env, "LOCAL_ADDRESS", buf); + + snprintf(buf, sizeof(buf), "%u", ntohs(local_addr->in6.sin6_port)); + fastd_shell_env_set(env, "LOCAL_PORT", buf); + + break; + + default: + fastd_shell_env_set(env, "LOCAL_ADDRESS", NULL); + fastd_shell_env_set(env, "LOCAL_PORT", NULL); + } + + switch(peer_addr ? peer_addr->sa.sa_family : AF_UNSPEC) { + case AF_INET: + inet_ntop(AF_INET, &peer_addr->in.sin_addr, buf, sizeof(buf)); + fastd_shell_env_set(env, "PEER_ADDRESS", buf); + + snprintf(buf, sizeof(buf), "%u", ntohs(peer_addr->in.sin_port)); + fastd_shell_env_set(env, "PEER_PORT", buf); + + break; + + case AF_INET6: + inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, buf, sizeof(buf)); + + if (IN6_IS_ADDR_LINKLOCAL(&peer_addr->in6.sin6_addr)) { + if (if_indextoname(peer_addr->in6.sin6_scope_id, buf+strlen(buf)+1)) + buf[strlen(buf)] = '%'; + } + + fastd_shell_env_set(env, "PEER_ADDRESS", buf); + + snprintf(buf, sizeof(buf), "%u", ntohs(peer_addr->in6.sin6_port)); + fastd_shell_env_set(env, "PEER_PORT", buf); + + break; + + default: + fastd_shell_env_set(env, "PEER_ADDRESS", NULL); + fastd_shell_env_set(env, "PEER_PORT", NULL); + } + + conf.protocol->set_shell_env(env, peer); +} + +void fastd_peer_exec_shell_command(const fastd_shell_command_t *command, const fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr) { + fastd_shell_env_t *env = fastd_shell_env_alloc(); + fastd_peer_set_shell_env(env, peer, local_addr, peer_addr); + fastd_shell_command_exec(command, env); + fastd_shell_env_free(env); +} + static inline void on_establish(const fastd_peer_t *peer) { - fastd_shell_command_exec(&conf.on_establish, peer, &peer->local_address, &peer->address); + fastd_peer_exec_shell_command(&conf.on_establish, peer, &peer->local_address, &peer->address); } static inline void on_disestablish(const fastd_peer_t *peer) { - fastd_shell_command_exec(&conf.on_disestablish, peer, &peer->local_address, &peer->address); + fastd_peer_exec_shell_command(&conf.on_disestablish, peer, &peer->local_address, &peer->address); } static int peer_id_cmp(fastd_peer_t *const *a, fastd_peer_t *const *b) { @@ -631,8 +707,15 @@ bool fastd_peer_verify_temporary(fastd_peer_t *peer, const fastd_peer_address_t /* TODO: async not supported yet */ + fastd_shell_env_t *env = fastd_shell_env_alloc(); + fastd_peer_set_shell_env(env, peer, local_addr, peer_addr); + int ret; - if (!fastd_shell_command_exec_sync(&conf.on_verify, peer, local_addr, peer_addr, &ret)) + bool ok = fastd_shell_command_exec_sync(&conf.on_verify, env, &ret); + + fastd_shell_env_free(env); + + if (!ok) return false; if (WIFSIGNALED(ret)) { diff --git a/src/peer.h b/src/peer.h index 36a2b10..c7cf603 100644 --- a/src/peer.h +++ b/src/peer.h @@ -139,6 +139,9 @@ void fastd_peer_reset_socket(fastd_peer_t *peer); void fastd_peer_schedule_handshake(fastd_peer_t *peer, int delay); fastd_peer_t* fastd_peer_find_by_id(uint64_t id); +void fastd_peer_set_shell_env(fastd_shell_env_t *env, const fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr); +void fastd_peer_exec_shell_command(const fastd_shell_command_t *command, const fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr); + static inline void fastd_peer_schedule_handshake_default(fastd_peer_t *peer) { fastd_peer_schedule_handshake(peer, fastd_rand(17500, 22500)); } diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h index e7c80e0..fcf9b56 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h @@ -95,7 +95,7 @@ void fastd_protocol_ec25519_fhmqvc_send_empty(fastd_peer_t *peer, protocol_sessi void fastd_protocol_ec25519_fhmqvc_generate_key(void); void fastd_protocol_ec25519_fhmqvc_show_key(void); -void fastd_protocol_ec25519_fhmqvc_set_shell_env(const fastd_peer_t *peer); +void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const fastd_peer_t *peer); bool fastd_protocol_ec25519_fhmqvc_describe_peer(const fastd_peer_t *peer, char *buf, size_t len); diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c index 37c753f..c4177b4 100644 --- a/src/protocols/ec25519_fhmqvc/handshake.c +++ b/src/protocols/ec25519_fhmqvc/handshake.c @@ -524,7 +524,7 @@ void fastd_protocol_ec25519_fhmqvc_handshake_init(const fastd_socket_t *sock, co fastd_handshake_add(&buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, &ctx.protocol_state->handshake_key.key.public); if (!peer || !fastd_peer_is_established(peer)) - fastd_shell_command_exec(&conf.on_connect, peer, (local_addr && local_addr->sa.sa_family) ? local_addr : sock->bound_addr, remote_addr); + fastd_peer_exec_shell_command(&conf.on_connect, peer, (local_addr && local_addr->sa.sa_family) ? local_addr : sock->bound_addr, remote_addr); fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer); } diff --git a/src/protocols/ec25519_fhmqvc/util.c b/src/protocols/ec25519_fhmqvc/util.c index 8d11eeb..a53513f 100644 --- a/src/protocols/ec25519_fhmqvc/util.c +++ b/src/protocols/ec25519_fhmqvc/util.c @@ -64,18 +64,18 @@ void fastd_protocol_ec25519_fhmqvc_show_key(void) { print_hexdump("Public: ", conf.protocol_config->key.public.u8); } -void fastd_protocol_ec25519_fhmqvc_set_shell_env(const fastd_peer_t *peer) { +void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const fastd_peer_t *peer) { char buf[65]; hexdump(buf, conf.protocol_config->key.public.u8); - setenv("LOCAL_KEY", buf, 1); + fastd_shell_env_set(env, "LOCAL_KEY", buf); if (peer && peer->protocol_config) { hexdump(buf, peer->protocol_config->public_key.u8); - setenv("PEER_KEY", buf, 1); + fastd_shell_env_set(env, "PEER_KEY", buf); } else { - unsetenv("PEER_KEY"); + fastd_shell_env_set(env, "PEER_KEY", NULL); } } diff --git a/src/shell.c b/src/shell.c index e35e986..3b2644b 100644 --- a/src/shell.c +++ b/src/shell.c @@ -25,16 +25,48 @@ #include "shell.h" -#include "peer.h" +#include "fastd.h" -#include #include #include -static void shell_command_setenv(pid_t pid, const fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr) { - /* both INET6_ADDRSTRLEN and IFNAMESIZE already include space for the zero termination, so there is no need to add space for the '%' here. */ - char buf[INET6_ADDRSTRLEN+IF_NAMESIZE]; +typedef struct shell_env_entry { + const char *key; + char *value; +} shell_env_entry_t; + + +struct fastd_shell_env { + VECTOR(shell_env_entry_t) entries; +}; + + +fastd_shell_env_t * fastd_shell_env_alloc(void) { + fastd_shell_env_t *env = malloc(sizeof(fastd_shell_env_t)); + VECTOR_ALLOC(env->entries, 0); + + return env; +} + +void fastd_shell_env_set(fastd_shell_env_t *env, const char *key, const char *value) { + shell_env_entry_t entry = {.key = key, .value = value ? strdup(value) : NULL}; + VECTOR_ADD(env->entries, entry); +} + +void fastd_shell_env_free(fastd_shell_env_t *env) { + size_t i; + for (i = 0; i < VECTOR_LEN(env->entries); i++) { + shell_env_entry_t *entry = &VECTOR_INDEX(env->entries, i); + free(entry->value); + } + + VECTOR_FREE(env->entries); + free(env); +} + +static void shell_command_setenv(pid_t pid, const fastd_shell_env_t *env) { + char buf[20]; snprintf(buf, sizeof(buf), "%u", (unsigned)pid); setenv("FASTD_PID", buf, 1); @@ -57,75 +89,21 @@ static void shell_command_setenv(pid_t pid, const fastd_peer_t *peer, const fast snprintf(buf, sizeof(buf), "%u", conf.mtu); setenv("INTERFACE_MTU", buf, 1); - if (peer && peer->config && peer->config->name) - setenv("PEER_NAME", peer->config->name, 1); - else - unsetenv("PEER_NAME"); - - switch(local_addr ? local_addr->sa.sa_family : AF_UNSPEC) { - case AF_INET: - inet_ntop(AF_INET, &local_addr->in.sin_addr, buf, sizeof(buf)); - setenv("LOCAL_ADDRESS", buf, 1); - - snprintf(buf, sizeof(buf), "%u", ntohs(local_addr->in.sin_port)); - setenv("LOCAL_PORT", buf, 1); - - break; - - case AF_INET6: - inet_ntop(AF_INET6, &local_addr->in6.sin6_addr, buf, sizeof(buf)); - - if (IN6_IS_ADDR_LINKLOCAL(&local_addr->in6.sin6_addr)) { - if (if_indextoname(local_addr->in6.sin6_scope_id, buf+strlen(buf)+1)) - buf[strlen(buf)] = '%'; - } - - setenv("LOCAL_ADDRESS", buf, 1); - - snprintf(buf, sizeof(buf), "%u", ntohs(local_addr->in6.sin6_port)); - setenv("LOCAL_PORT", buf, 1); - - break; - - default: - unsetenv("LOCAL_ADDRESS"); - unsetenv("LOCAL_PORT"); - } - - switch(peer_addr ? peer_addr->sa.sa_family : AF_UNSPEC) { - case AF_INET: - inet_ntop(AF_INET, &peer_addr->in.sin_addr, buf, sizeof(buf)); - setenv("PEER_ADDRESS", buf, 1); - - snprintf(buf, sizeof(buf), "%u", ntohs(peer_addr->in.sin_port)); - setenv("PEER_PORT", buf, 1); - - break; - - case AF_INET6: - inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, buf, sizeof(buf)); - - if (IN6_IS_ADDR_LINKLOCAL(&peer_addr->in6.sin6_addr)) { - if (if_indextoname(peer_addr->in6.sin6_scope_id, buf+strlen(buf)+1)) - buf[strlen(buf)] = '%'; - } - - setenv("PEER_ADDRESS", buf, 1); - - snprintf(buf, sizeof(buf), "%u", ntohs(peer_addr->in6.sin6_port)); - setenv("PEER_PORT", buf, 1); + if (!env) + return; - break; + size_t i; + for (i = 0; i < VECTOR_LEN(env->entries); i++) { + shell_env_entry_t *entry = &VECTOR_INDEX(env->entries, i); - default: - unsetenv("PEER_ADDRESS"); - unsetenv("PEER_PORT"); + if (entry->value) + setenv(entry->key, entry->value, 1); + else + unsetenv(entry->key); } - - conf.protocol->set_shell_env(peer); } -static bool shell_command_do_exec(const fastd_shell_command_t *command, const fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr, pid_t *pid_ret) { +static bool shell_command_do_exec(const fastd_shell_command_t *command, const fastd_shell_env_t *env, pid_t *pid_ret) { pid_t parent = getpid(); pid_t pid = fork(); @@ -145,7 +123,7 @@ static bool shell_command_do_exec(const fastd_shell_command_t *command, const fa if (chdir(command->dir)) _exit(126); - shell_command_setenv(parent, peer, local_addr, peer_addr); + shell_command_setenv(parent, env); /* unblock SIGCHLD */ sigset_t set; @@ -157,7 +135,7 @@ static bool shell_command_do_exec(const fastd_shell_command_t *command, const fa _exit(127); } -bool fastd_shell_command_exec_sync(const fastd_shell_command_t *command, const fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr, int *ret) { +bool fastd_shell_command_exec_sync(const fastd_shell_command_t *command, const fastd_shell_env_t *env, int *ret) { if (!fastd_shell_command_isset(command)) return true; @@ -168,7 +146,7 @@ bool fastd_shell_command_exec_sync(const fastd_shell_command_t *command, const f pthread_sigmask(SIG_BLOCK, &set, &oldset); pid_t pid; - if (!shell_command_do_exec(command, peer, local_addr, peer_addr, &pid)) + if (!shell_command_do_exec(command, env, &pid)) return false; int status; @@ -195,12 +173,12 @@ bool fastd_shell_command_exec_sync(const fastd_shell_command_t *command, const f } -void fastd_shell_command_exec(const fastd_shell_command_t *command, const fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr) { +void fastd_shell_command_exec(const fastd_shell_command_t *command, const fastd_shell_env_t *env) { if (!fastd_shell_command_isset(command)) return; if (command->sync) - fastd_shell_command_exec_sync(command, peer, local_addr, peer_addr, NULL); + fastd_shell_command_exec_sync(command, env, NULL); else - shell_command_do_exec(command, peer, local_addr, peer_addr, NULL); + shell_command_do_exec(command, env, NULL); } diff --git a/src/shell.h b/src/shell.h index 30de630..9b66477 100644 --- a/src/shell.h +++ b/src/shell.h @@ -38,6 +38,7 @@ struct fastd_shell_command { bool sync; }; + static inline void fastd_shell_command_unset(fastd_shell_command_t *command) { free(command->command); command->command = NULL; @@ -58,5 +59,9 @@ static inline bool fastd_shell_command_isset(const fastd_shell_command_t *comman return command->command; } -bool fastd_shell_command_exec_sync(const fastd_shell_command_t *command, const fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr, int *ret); -void fastd_shell_command_exec(const fastd_shell_command_t *command, const fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr); +fastd_shell_env_t * fastd_shell_env_alloc(void); +void fastd_shell_env_set(fastd_shell_env_t *env, const char *key, const char *value); +void fastd_shell_env_free(fastd_shell_env_t *env); + +bool fastd_shell_command_exec_sync(const fastd_shell_command_t *command, const fastd_shell_env_t *env, int *ret); +void fastd_shell_command_exec(const fastd_shell_command_t *command, const fastd_shell_env_t *env); diff --git a/src/types.h b/src/types.h index 37560b1..8a80d19 100644 --- a/src/types.h +++ b/src/types.h @@ -132,6 +132,7 @@ typedef struct fastd_lex fastd_lex_t; typedef struct fastd_string_stack fastd_string_stack_t; typedef struct fastd_shell_command fastd_shell_command_t; +typedef struct fastd_shell_env fastd_shell_env_t; typedef struct fastd_async_resolve_return fastd_async_resolve_return_t; -- cgit v1.2.3