summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-04-16 05:23:12 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-04-16 05:23:12 +0200
commit96ec41768b5937e5cf0cd83bf815d365d12d1f93 (patch)
treec56fb1c45db75c32b156b5ceee8758334df69c12
parent037c58ae51a61064d7bb5022715546509328d83f (diff)
downloadfastd-96ec41768b5937e5cf0cd83bf815d365d12d1f93.tar
fastd-96ec41768b5937e5cf0cd83bf815d365d12d1f93.zip
Add support for peers specified by hostnames
-rw-r--r--CMakeLists.txt6
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/config.l5
-rw-r--r--src/config.y61
-rw-r--r--src/fastd.c76
-rw-r--r--src/fastd.h26
-rw-r--r--src/peer.c22
-rw-r--r--src/peer.h9
-rw-r--r--src/printf.c3
-rw-r--r--src/resolve.c123
-rw-r--r--src/types.h4
11 files changed, 291 insertions, 47 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c33c10c..c50ec05 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,6 +6,12 @@ set(CMAKE_MODULE_PATH ${FASTD_SOURCE_DIR})
find_package(BISON 2.5 REQUIRED)
find_package(FLEX REQUIRED)
+set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+find_package(Threads)
+if(NOT CMAKE_USE_PTHREADS_INIT)
+ MESSAGE(FATAL_ERROR "No pthread support found.")
+endif(NOT CMAKE_USE_PTHREADS_INIT)
+
find_package(UECC REQUIRED)
find_package(NaCl REQUIRED)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a700c4c..84f25fe 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -17,12 +17,13 @@ add_executable(fastd
printf.c
queue.c
random.c
+ resolve.c
task.c
protocol_ec25519_fhmqvc.c
${FLEX_fastd_config_lex_OUTPUTS}
${BISON_fastd_config_parse_OUTPUTS}
${METHODS}
)
-target_link_libraries(fastd rt ${UECC_LIBRARY} ${NACL_LIBRARY})
+target_link_libraries(fastd rt ${CMAKE_THREAD_LIBS_INIT} ${UECC_LIBRARY} ${NACL_LIBRARY})
install(TARGETS fastd RUNTIME DESTINATION sbin)
diff --git a/src/config.l b/src/config.l
index f20116c..c05f0e1 100644
--- a/src/config.l
+++ b/src/config.l
@@ -61,7 +61,9 @@ mode { UPDATE_LOCATION; return TOK_MODE; }
protocol { UPDATE_LOCATION; return TOK_PROTOCOL; }
method { UPDATE_LOCATION; return TOK_METHOD; }
peer { UPDATE_LOCATION; return TOK_PEER; }
-address { UPDATE_LOCATION; return TOK_ADDRESS; }
+remote { UPDATE_LOCATION; return TOK_REMOTE; }
+ipv4 { UPDATE_LOCATION; return TOK_IPV4; }
+ipv6 { UPDATE_LOCATION; return TOK_IPV6; }
secret { UPDATE_LOCATION; return TOK_SECRET; }
key { UPDATE_LOCATION; return TOK_KEY; }
include { UPDATE_LOCATION; return TOK_INCLUDE; }
@@ -87,6 +89,7 @@ debug { UPDATE_LOCATION; return TOK_DEBUG; }
peer-to-peer { UPDATE_LOCATION; return TOK_PEER_TO_PEER; }
yes { UPDATE_LOCATION; return TOK_YES; }
no { UPDATE_LOCATION; return TOK_NO; }
+port { UPDATE_LOCATION; return TOK_PORT; }
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} {
UPDATE_LOCATION;
diff --git a/src/config.y b/src/config.y
index b1d68e0..5ef30b6 100644
--- a/src/config.y
+++ b/src/config.y
@@ -38,7 +38,6 @@
#include <fastd.h>
#include <arpa/inet.h>
- #include <unistd.h>
}
%union {
@@ -63,7 +62,9 @@
%token TOK_PROTOCOL
%token TOK_METHOD
%token TOK_PEER
-%token TOK_ADDRESS
+%token TOK_REMOTE
+%token TOK_IPV4
+%token TOK_IPV6
%token TOK_SECRET
%token TOK_KEY
%token TOK_INCLUDE
@@ -89,6 +90,7 @@
%token TOK_PEER_TO_PEER
%token TOK_YES
%token TOK_NO
+%token TOK_PORT
%token <addr> TOK_ADDR
%token <addr6> TOK_ADDR6
@@ -96,9 +98,11 @@
%code {
#include <config.h>
- #include <stdint.h>
#include <peer.h>
+ #include <stdint.h>
+ #include <unistd.h>
+
void fastd_config_error(YYLTYPE *loc, fastd_context *ctx, fastd_config *conf, const char *filename, int depth, char *s);
}
@@ -109,6 +113,7 @@
%type <boolean> boolean
%type <num> maybe_port
%type <str> maybe_as
+%type <num> maybe_af
%%
start: START_CONFIG config
@@ -153,18 +158,18 @@ interface: TOK_STRING { free(conf->ifname); conf->ifname = strdup($1->str); }
bind: TOK_ADDR maybe_port {
conf->bind_addr_in.sin_family = AF_INET;
conf->bind_addr_in.sin_addr = $1;
- conf->bind_addr_in.sin_port = $2;
+ conf->bind_addr_in.sin_port = htons($2);
}
| TOK_ADDR6 maybe_port {
conf->bind_addr_in6.sin6_family = AF_INET6;
conf->bind_addr_in6.sin6_addr = $1;
- conf->bind_addr_in6.sin6_port = $2;
+ conf->bind_addr_in6.sin6_port = htons($2);
}
| TOK_ANY maybe_port {
conf->bind_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
- conf->bind_addr_in.sin_port = $2;
+ conf->bind_addr_in.sin_port = htons($2);
conf->bind_addr_in6.sin6_addr = in6addr_any;
- conf->bind_addr_in6.sin6_port = $2;
+ conf->bind_addr_in6.sin6_port = htons($2);
}
;
@@ -221,7 +226,7 @@ on_establish: TOK_STRING {
}
;
-on_disestablish: TOK_STRING {
+on_disestablish: TOK_STRING {
free(conf->on_disestablish);
free(conf->on_disestablish_dir);
@@ -240,20 +245,33 @@ peer_conf: peer_conf peer_statement
|
;
-peer_statement: TOK_ADDRESS peer_address ';'
+peer_statement: TOK_REMOTE peer_remote ';'
| TOK_KEY peer_key ';'
| TOK_INCLUDE peer_include ';'
;
-peer_address: TOK_ADDR ':' port {
+peer_remote: TOK_ADDR port {
+ free(conf->peers->hostname);
+ conf->peers->hostname = NULL;
+
conf->peers->address.in.sin_family = AF_INET;
conf->peers->address.in.sin_addr = $1;
- conf->peers->address.in.sin_port = $3;
+ conf->peers->address.in.sin_port = htons($2);
}
- | TOK_ADDR6 ':' port {
+ | TOK_ADDR6 port {
+ free(conf->peers->hostname);
+ conf->peers->hostname = NULL;
+
conf->peers->address.in6.sin6_family = AF_INET6;
conf->peers->address.in6.sin6_addr = $1;
- conf->peers->address.in6.sin6_port = $3;
+ conf->peers->address.in6.sin6_port = htons($2);
+ }
+ | maybe_af TOK_STRING port {
+ free(conf->peers->hostname);
+
+ conf->peers->hostname = strdup($2->str);
+ conf->peers->address.sa.sa_family = $1;
+ conf->peers->address.in.sin_port = htons($3);
}
;
@@ -292,7 +310,7 @@ maybe_string: TOK_STRING
| { $$ = NULL; }
;
-maybe_port: ':' port { $$ = $2; }
+maybe_port: port { $$ = $1; }
| { $$ = 0; }
;
@@ -300,16 +318,25 @@ maybe_as: TOK_AS TOK_STRING { $$ = $2; }
| { $$ = NULL; }
;
+maybe_af: TOK_IPV4 { $$ = AF_INET; }
+ | TOK_IPV6 { $$ = AF_INET6; }
+ | { $$ = AF_UNSPEC; }
+ ;
+
boolean: TOK_YES { $$ = true; }
| TOK_NO { $$ = false; }
;
-port: TOK_INTEGER {
- if ($1 < 0 || $1 > 65635) {
+colon_or_port: ':'
+ | TOK_PORT
+ ;
+
+port: colon_or_port TOK_INTEGER {
+ if ($2 < 0 || $2 > 65635) {
fastd_config_error(&@$, ctx, conf, filename, depth, "invalid port");
YYERROR;
}
- $$ = htons($1);
+ $$ = $2;
}
;
%%
diff --git a/src/fastd.c b/src/fastd.c
index 71d0a04..695edaa 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -42,8 +42,8 @@
#include <unistd.h>
-static bool sighup = false;
-static bool terminate = false;
+static volatile bool sighup = false;
+static volatile bool terminate = false;
static void on_sighup(int signo) {
@@ -54,6 +54,13 @@ static void on_terminate(int signo) {
terminate = true;
}
+static void on_sigusr1(int signo, siginfo_t *siginfo, void *context) {
+ fastd_resolve_return *ret = siginfo->si_value.sival_ptr;
+
+ ret->next = ret->ctx->resolve_returns;
+ ret->ctx->resolve_returns = ret;
+}
+
static void init_signals(fastd_context *ctx) {
struct sigaction action;
@@ -72,6 +79,11 @@ static void init_signals(fastd_context *ctx) {
exit_errno(ctx, "sigaction");
if(sigaction(SIGINT, &action, NULL))
exit_errno(ctx, "sigaction");
+
+ action.sa_flags = SA_SIGINFO;
+ action.sa_sigaction = on_sigusr1;
+ if(sigaction(SIGUSR1, &action, NULL))
+ exit_errno(ctx, "sigaction");
}
static void init_tuntap(fastd_context *ctx) {
@@ -111,7 +123,7 @@ static void init_tuntap(fastd_context *ctx) {
static void close_tuntap(fastd_context *ctx) {
if(close(ctx->tunfd))
- warn_errno(ctx, "closing tun/tap: close");
+ pr_warn_errno(ctx, "closing tun/tap: close");
free(ctx->ifname);
}
@@ -154,7 +166,7 @@ static void init_sockets(fastd_context *ctx) {
if ((ctx->sock6fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
if (ctx->sockfd >= 0)
- warn_errno(ctx, "socket");
+ pr_warn_errno(ctx, "socket");
else
exit_errno(ctx, "socket");
}
@@ -177,12 +189,12 @@ static void init_sockets(fastd_context *ctx) {
static void close_sockets(fastd_context *ctx) {
if (ctx->sockfd >= 0) {
if(close(ctx->sockfd))
- warn_errno(ctx, "closing IPv4 socket: close");
+ pr_warn_errno(ctx, "closing IPv4 socket: close");
}
if (ctx->sock6fd >= 0) {
if(close(ctx->sock6fd))
- warn_errno(ctx, "closing IPv6 socket: close");
+ pr_warn_errno(ctx, "closing IPv6 socket: close");
}
}
@@ -238,7 +250,7 @@ void fastd_handle_receive(fastd_context *ctx, fastd_peer *peer, fastd_buffer buf
}
if (write(ctx->tunfd, buffer.data, buffer.len) < 0)
- warn_errno(ctx, "write");
+ pr_warn_errno(ctx, "write");
if (ctx->conf->mode == MODE_TAP && ctx->conf->peer_to_peer) {
const fastd_eth_addr *dest_addr = fastd_get_dest_address(ctx, buffer);
@@ -354,18 +366,25 @@ static void update_time(fastd_context *ctx) {
clock_gettime(CLOCK_MONOTONIC, &ctx->now);
}
+static void send_handshake(fastd_context *ctx, fastd_peer *peer) {
+ pr_debug(ctx, "sending handshake to %P...", peer);
+ ctx->conf->protocol->handshake_init(ctx, peer);
+
+ if (fastd_peer_is_established(peer))
+ fastd_task_schedule_handshake(ctx, peer, fastd_rand(ctx, 10000, 20000));
+ else
+ fastd_task_schedule_handshake(ctx, peer, 20000);
+}
+
static void handle_tasks(fastd_context *ctx) {
fastd_task *task;
while ((task = fastd_task_get(ctx)) != NULL) {
switch (task->type) {
case TASK_HANDSHAKE:
- pr_debug(ctx, "sending handshake to %P...", task->peer);
- ctx->conf->protocol->handshake_init(ctx, task->peer);
-
- if (fastd_peer_is_established(task->peer))
- fastd_task_schedule_handshake(ctx, task->peer, fastd_rand(ctx, 10000, 20000));
+ if (task->peer->state == STATE_RESOLVE)
+ fastd_resolve_peer_handshake(ctx, task->peer);
else
- fastd_task_schedule_handshake(ctx, task->peer, 20000);
+ send_handshake(ctx, task->peer);
break;
case TASK_KEEPALIVE:
@@ -554,6 +573,35 @@ static void handle_input(fastd_context *ctx) {
handle_socket(ctx, ctx->sock6fd);
}
+static void handle_resolv_returns(fastd_context *ctx) {
+ while (ctx->resolve_returns) {
+ fastd_peer *peer;
+ for (peer = ctx->peers; peer; peer = peer->next) {
+ if (peer->state != STATE_RESOLVE)
+ continue;
+
+ if (!strequal(peer->config->hostname, ctx->resolve_returns->hostname))
+ continue;
+
+ if (peer->config->address.sa.sa_family != AF_UNSPEC &&
+ peer->config->address.sa.sa_family != ctx->resolve_returns->addr.sa.sa_family)
+ continue;
+
+ if (peer->config->address.in.sin_port != htons(ctx->resolve_returns->port))
+ continue;
+
+ peer->address = ctx->resolve_returns->addr;
+ send_handshake(ctx, peer);
+ break;
+ }
+
+ fastd_resolve_return *next = ctx->resolve_returns->next;
+ free(ctx->resolve_returns->hostname);
+ free(ctx->resolve_returns);
+ ctx->resolve_returns = next;
+ }
+}
+
static void cleanup_peers(fastd_context *ctx) {
fastd_peer *peer, *next;
@@ -611,6 +659,8 @@ int main(int argc, char *argv[]) {
sighup = false;
fastd_reconfigure(&ctx, &conf);
}
+
+ handle_resolv_returns(&ctx);
}
on_down(&ctx);
diff --git a/src/fastd.h b/src/fastd.h
index 102c2c4..c778b19 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -91,6 +91,24 @@ struct _fastd_method {
bool (*decrypt)(fastd_context *ctx, fastd_method_session_state *session, fastd_buffer *out, fastd_buffer in);
};
+union _fastd_peer_address {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+};
+
+struct _fastd_resolve_return {
+ fastd_resolve_return *next;
+
+ fastd_context *ctx;
+
+ char *hostname;
+ sa_family_t af;
+ uint16_t port;
+
+ fastd_peer_address addr;
+};
+
struct _fastd_config {
fastd_loglevel loglevel;
@@ -156,6 +174,8 @@ struct _fastd_context {
fastd_peer_eth_addr *eth_addr;
unsigned int randseed;
+
+ fastd_resolve_return *resolve_returns;
};
struct _fastd_string_stack {
@@ -163,10 +183,13 @@ struct _fastd_string_stack {
char str[];
};
+
void fastd_send(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer);
void fastd_send_handshake(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer);
void fastd_handle_receive(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer);
+void fastd_resolve_peer_handshake(fastd_context *ctx, fastd_peer *peer);
+
void fastd_printf(const fastd_context *ctx, const char *format, ...);
void fastd_read_peer_dir(fastd_context *ctx, fastd_config *conf, const char *dir);
@@ -216,7 +239,8 @@ static inline int fastd_rand(fastd_context *ctx, int min, int max) {
#define pr_verbose(ctx, args...) pr_log(ctx, LOG_VERBOSE, "Verbose: ", args)
#define pr_debug(ctx, args...) pr_log(ctx, LOG_DEBUG, "DEBUG: ", args)
-#define warn_errno(ctx, message) pr_warn(ctx, "%s: %s", message, strerror(errno))
+#define pr_warn_errno(ctx, message) pr_warn(ctx, "%s: %s", message, strerror(errno))
+#define pr_error_errno(ctx, message) pr_warn(ctx, "%s: %s", message, strerror(errno))
#define exit_fatal(ctx, args...) do { pr_fatal(ctx, args); abort(); } while(0)
#define exit_bug(ctx, message) exit_fatal(ctx, "BUG: %s", message)
#define exit_error(ctx, args...) do { pr_error(ctx, args); exit(1); } while(0)
diff --git a/src/peer.c b/src/peer.c
index 4c85db2..1a6ddd9 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -174,12 +174,16 @@ static inline void reset_peer(fastd_context *ctx, fastd_peer *peer) {
}
static inline void setup_peer(fastd_context *ctx, fastd_peer *peer) {
- if (fastd_peer_is_temporary(peer)) {
- exit_fatal(ctx, "tried to setup temporary peer");
- }
+ if (peer->config->hostname)
+ peer->address.sa.sa_family = AF_UNSPEC;
+ else
+ peer->address = peer->config->address;
+
+ if (peer->config->hostname)
+ peer->state = STATE_RESOLVE;
+ else
+ peer->state = STATE_WAIT;
- peer->address = peer->config->address;
- peer->state = STATE_WAIT;
peer->seen = (struct timespec){0, 0};
if (!fastd_peer_is_floating(peer))
@@ -205,6 +209,7 @@ fastd_peer_config* fastd_peer_config_new(fastd_context *ctx, fastd_config *conf)
fastd_peer_config *peer = malloc(sizeof(fastd_peer_config));
peer->enabled = true;
+ peer->hostname = NULL;
memset(&peer->address, 0, sizeof(fastd_peer_address));
peer->config_source_dir = NULL;
@@ -221,6 +226,7 @@ fastd_peer_config* fastd_peer_config_new(fastd_context *ctx, fastd_config *conf)
void fastd_peer_config_free(fastd_peer_config *peer) {
free(peer->name);
+ free(peer->hostname);
free(peer->key);
free(peer->protocol_config);
free(peer);
@@ -270,6 +276,9 @@ bool fastd_peer_config_equal(const fastd_peer_config *peer1, const fastd_peer_co
if (peer1->enabled != peer2->enabled)
return false;
+ if (!strequal(peer1->hostname, peer2->hostname))
+ return false;
+
if (!fastd_peer_addr_equal(&peer1->address, &peer2->address))
return false;
@@ -311,8 +320,6 @@ fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *peer_conf) {
fastd_peer *peer = add_peer(ctx);
peer->config = peer_conf;
- peer->state = STATE_WAIT;
-
setup_peer(ctx, peer);
pr_debug(ctx, "adding peer %P", peer);
@@ -369,6 +376,7 @@ 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_RESOLVE:
case STATE_WAIT:
peer->state = STATE_ESTABLISHED;
on_establish(ctx, peer);
diff --git a/src/peer.h b/src/peer.h
index 4afa9a1..7521799 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -30,12 +30,6 @@
#include "fastd.h"
-union _fastd_peer_address {
- struct sockaddr sa;
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
-};
-
struct _fastd_peer {
fastd_peer *next;
@@ -59,6 +53,7 @@ struct _fastd_peer_config {
bool enabled;
char *name;
+ char *hostname;
fastd_peer_address address;
char *key;
@@ -89,7 +84,7 @@ const fastd_eth_addr* fastd_get_source_address(const fastd_context *ctx, fastd_b
const fastd_eth_addr* fastd_get_dest_address(const fastd_context *ctx, fastd_buffer buffer);
static inline bool fastd_peer_config_is_floating(const fastd_peer_config *config) {
- return (config->address.sa.sa_family == AF_UNSPEC);
+ return (config->hostname == NULL && config->address.sa.sa_family == AF_UNSPEC);
}
static inline bool fastd_peer_is_floating(const fastd_peer *peer) {
diff --git a/src/printf.c b/src/printf.c
index 7c922c5..c32ebf9 100644
--- a/src/printf.c
+++ b/src/printf.c
@@ -43,6 +43,9 @@ static void print_peer_str(const fastd_context *ctx, const fastd_peer *peer) {
if (peer->config && peer->config->name) {
fprintf(stderr, "%c%s%c", pl, peer->config->name, pr);
}
+ else if (peer->config && peer->config->hostname) {
+ fprintf(stderr, "%c\"%s\"%c", pl, peer->config->hostname, pr);
+ }
else {
switch (peer->address.sa.sa_family) {
case AF_UNSPEC:
diff --git a/src/resolve.c b/src/resolve.c
new file mode 100644
index 0000000..1fbb1bf
--- /dev/null
+++ b/src/resolve.c
@@ -0,0 +1,123 @@
+/*
+ Copyright (c) 2012, 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 "fastd.h"
+#include "peer.h"
+
+#include <netdb.h>
+#include <pthread.h>
+#include <signal.h>
+
+
+typedef struct _resolv_arg {
+ fastd_context *ctx;
+ pthread_t master_thread;
+ char *hostname;
+ sa_family_t af;
+ uint16_t port;
+} resolv_arg;
+
+
+static void* fastd_resolve_peer_handshake_do(void *varg) {
+ resolv_arg *arg = varg;
+
+ struct addrinfo hints;
+ struct addrinfo *res = NULL;
+ int gai_ret;
+ bool error = false;
+
+ char portstr[6];
+ snprintf(portstr, 6, "%u", arg->port);
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = arg->af;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;
+#ifdef AI_IDN
+ hints.ai_flags |= AI_IDN;
+#endif
+
+ gai_ret = getaddrinfo(arg->hostname, portstr, &hints, &res);
+
+ if (gai_ret) {
+ pr_debug(arg->ctx, "Resolving host `%s' failed: %s", arg->hostname, gai_strerror(gai_ret));
+ error = true;
+ }
+ else if (res->ai_addrlen > sizeof(fastd_peer_address)) {
+ pr_warn(arg->ctx, "Resolving host `%s': unsupported address returned", arg->hostname);
+ error = true;
+ }
+
+ fastd_resolve_return *ret = malloc(sizeof(fastd_resolve_return));
+
+ ret->ctx = arg->ctx;
+
+ ret->hostname = arg->hostname;
+ ret->af = arg->af;
+ ret->port = arg->port;
+
+ if (!error) {
+ pr_debug(arg->ctx, "Resolved host `%s' successfully", arg->hostname);
+ memcpy(&ret->addr, res->ai_addr, res->ai_addrlen);
+ }
+ else {
+ ret->addr.sa.sa_family = AF_UNSPEC;
+ }
+
+ union sigval sigval;
+ sigval.sival_ptr = ret;
+ if (pthread_sigqueue(arg->master_thread, SIGUSR1, sigval))
+ exit_errno(arg->ctx, "pthread_sigqueue");
+
+ freeaddrinfo(res);
+ free(arg);
+
+ return NULL;
+}
+
+void fastd_resolve_peer_handshake(fastd_context *ctx, fastd_peer *peer) {
+ pr_debug(ctx, "Resolving host `%s' for peer %P...", peer->config->hostname, peer);
+
+ resolv_arg *arg = malloc(sizeof(resolv_arg));
+
+ arg->ctx = ctx;
+ arg->master_thread = pthread_self();
+ arg->hostname = strdup(peer->config->hostname);
+ arg->af = peer->config->address.sa.sa_family;
+ arg->port = ntohs(peer->config->address.in.sin_port);
+
+ pthread_t thread;
+ if (pthread_create(&thread, NULL, fastd_resolve_peer_handshake_do, arg) != 0) {
+ pr_error_errno(ctx, "unable to create resolver thread");
+ free(arg->hostname);
+ free(arg);
+ }
+
+ pthread_detach(thread);
+}
diff --git a/src/types.h b/src/types.h
index 3808b32..c48cf59 100644
--- a/src/types.h
+++ b/src/types.h
@@ -48,6 +48,7 @@ typedef enum _fastd_mode {
} fastd_mode;
typedef enum _fastd_peer_state {
+ STATE_RESOLVE,
STATE_WAIT,
STATE_TEMP,
STATE_ESTABLISHED,
@@ -72,6 +73,9 @@ typedef struct _fastd_handshake fastd_handshake;
typedef struct _fastd_string_stack fastd_string_stack;
+typedef struct _fastd_resolve_return fastd_resolve_return;
+
+
/* May be defined by the protocol/method however it likes */
typedef struct _fastd_protocol_config fastd_protocol_config;
typedef struct _fastd_protocol_peer_config fastd_protocol_peer_config;