summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-04-16 07:29:55 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-04-16 07:29:55 +0200
commit872e0dfa86417e89022f84ac78b2d90236cb97d4 (patch)
tree640c04570466a9cf2d06eece32fdb5c07afde6cb
parent3a87d747a015b2ff2150ed163ad56b1bc677e6b0 (diff)
downloadfastd-872e0dfa86417e89022f84ac78b2d90236cb97d4.tar
fastd-872e0dfa86417e89022f84ac78b2d90236cb97d4.zip
Lots of fixes and improvements on the resolver code
-rw-r--r--src/config.c18
-rw-r--r--src/fastd.c80
-rw-r--r--src/fastd.h8
-rw-r--r--src/peer.c25
-rw-r--r--src/peer.h8
-rw-r--r--src/protocol_ec25519_fhmqvc.c29
-rw-r--r--src/resolve.c23
7 files changed, 127 insertions, 64 deletions
diff --git a/src/config.c b/src/config.c
index e7c8640..d581ccf 100644
--- a/src/config.c
+++ b/src/config.c
@@ -292,20 +292,32 @@ static void count_peers(fastd_context *ctx, fastd_config *conf) {
conf->n_floating = 0;
conf->n_v4 = 0;
conf->n_v6 = 0;
+ conf->n_dynamic = 0;
+ conf->n_dynamic_v4 = 0;
+ conf->n_dynamic_v6 = 0;
fastd_peer_config *peer;
for (peer = conf->peers; peer; peer = peer->next) {
switch (peer->address.sa.sa_family) {
case AF_UNSPEC:
- conf->n_floating++;
+ if (peer->hostname)
+ conf->n_dynamic++;
+ else
+ conf->n_floating++;
break;
case AF_INET:
- conf->n_v4++;
+ if (peer->hostname)
+ conf->n_dynamic_v4++;
+ else
+ conf->n_v4++;
break;
case AF_INET6:
- conf->n_v6++;
+ if (peer->hostname)
+ conf->n_dynamic_v6++;
+ else
+ conf->n_v6++;
break;
default:
diff --git a/src/fastd.c b/src/fastd.c
index 59e5c54..ee7f03a 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -55,6 +55,9 @@ static void on_terminate(int signo) {
}
static void on_sigusr1(int signo, siginfo_t *siginfo, void *context) {
+ if (siginfo->si_code != SI_QUEUE || !siginfo->si_value.sival_ptr)
+ return;
+
fastd_resolve_return *ret = siginfo->si_value.sival_ptr;
ret->next = ret->ctx->resolve_returns;
@@ -133,10 +136,10 @@ static void init_sockets(fastd_context *ctx) {
struct sockaddr_in6 addr_in6 = ctx->conf->bind_addr_in6;
if (addr_in.sin_family == AF_UNSPEC && addr_in6.sin6_family == AF_UNSPEC) {
- if (ctx->conf->n_floating || ctx->conf->peer_dirs || ctx->conf->n_v4)
+ if (ctx->conf->peer_dirs || ctx->conf->n_floating || ctx->conf->n_v4 || ctx->conf->n_dynamic || ctx->conf->n_dynamic_v4)
addr_in.sin_family = AF_INET;
- if (ctx->conf->n_floating || ctx->conf->peer_dirs || ctx->conf->n_v6)
+ if (ctx->conf->peer_dirs || ctx->conf->n_floating || ctx->conf->n_v6 || ctx->conf->n_dynamic || ctx->conf->n_dynamic_v6)
addr_in6.sin6_family = AF_INET6;
}
@@ -362,13 +365,15 @@ static void delete_peers(fastd_context *ctx) {
}
}
-static void update_time(fastd_context *ctx) {
+static inline 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);
+static inline void send_handshake(fastd_context *ctx, fastd_peer *peer) {
+ if (peer->address.sa.sa_family != AF_UNSPEC) {
+ pr_debug(ctx, "sending handshake to %P...", peer);
+ ctx->conf->protocol->handshake_init(ctx, peer);
+ }
fastd_task_schedule_handshake(ctx, peer, fastd_rand(ctx, 17500, 22500));
}
@@ -379,7 +384,7 @@ static void handle_tasks(fastd_context *ctx) {
switch (task->type) {
case TASK_HANDSHAKE:
if (task->peer->state == STATE_RESOLVE)
- fastd_resolve_peer_handshake(ctx, task->peer);
+ fastd_resolve_peer(ctx, task->peer->config);
else
send_handshake(ctx, task->peer);
break;
@@ -516,7 +521,9 @@ static void handle_socket(fastd_context *ctx, int sockfd) {
fastd_buffer_free(buffer);
}
}
- else if(ctx->conf->n_floating) {
+ else if(ctx->conf->n_floating || ctx->conf->n_dynamic ||
+ (recvaddr.sa.sa_family == AF_INET && ctx->conf->n_dynamic_v4) ||
+ (recvaddr.sa.sa_family == AF_INET6 && ctx->conf->n_dynamic_v6)) {
switch (packet_type) {
case PACKET_DATA:
peer = fastd_peer_add_temp(ctx, (fastd_peer_address*)&recvaddr);
@@ -570,25 +577,51 @@ static void handle_input(fastd_context *ctx) {
handle_socket(ctx, ctx->sock6fd);
}
+static void cleanup_peers(fastd_context *ctx) {
+ fastd_peer *peer, *next;
+
+ for (peer = ctx->peers; peer; peer = next) {
+ next = peer->next;
+
+ if (fastd_peer_is_temporary(peer)) {
+ if (timespec_diff(&ctx->now, &peer->seen) > ctx->conf->peer_stale_time_temp*1000)
+ fastd_peer_reset(ctx, peer);
+ }
+ else if (fastd_peer_is_established(peer)) {
+ if (timespec_diff(&ctx->now, &peer->seen) > ctx->conf->peer_stale_time*1000)
+ fastd_peer_reset(ctx, peer);
+ }
+ }
+}
+
+static void cleanup_peer_with_address(fastd_context *ctx, const fastd_peer_address *addr) {
+ fastd_peer *peer;
+ for (peer = ctx->peers; peer; peer = peer->next) {
+ if (fastd_peer_is_temporary(peer) && fastd_peer_addr_equal(&peer->address, addr)) {
+ fastd_peer_reset(ctx, peer);
+ return;
+ }
+ }
+}
+
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)
+ if (!peer->config)
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))
+ if (!fastd_peer_config_matches_dynamic(peer->config, &ctx->resolve_returns->constraints))
continue;
+ cleanup_peer_with_address(ctx, &ctx->resolve_returns->addr);
peer->address = ctx->resolve_returns->addr;
- send_handshake(ctx, peer);
+
+ if (peer->state == STATE_RESOLVE)
+ send_handshake(ctx, peer);
break;
}
@@ -599,23 +632,6 @@ static void handle_resolv_returns(fastd_context *ctx) {
}
}
-static void cleanup_peers(fastd_context *ctx) {
- fastd_peer *peer, *next;
-
- for (peer = ctx->peers; peer; peer = next) {
- next = peer->next;
-
- if (fastd_peer_is_temporary(peer)) {
- if (timespec_diff(&ctx->now, &peer->seen) > ctx->conf->peer_stale_time_temp*1000)
- fastd_peer_reset(ctx, peer);
- }
- else if (fastd_peer_is_established(peer)) {
- if (timespec_diff(&ctx->now, &peer->seen) > ctx->conf->peer_stale_time*1000)
- fastd_peer_reset(ctx, peer);
- }
- }
-}
-
static void maintenance(fastd_context *ctx) {
cleanup_peers(ctx);
diff --git a/src/fastd.h b/src/fastd.h
index c778b19..1fa4d17 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -103,8 +103,7 @@ struct _fastd_resolve_return {
fastd_context *ctx;
char *hostname;
- sa_family_t af;
- uint16_t port;
+ fastd_peer_address constraints;
fastd_peer_address addr;
};
@@ -139,6 +138,9 @@ struct _fastd_config {
unsigned n_floating;
unsigned n_v4;
unsigned n_v6;
+ unsigned n_dynamic;
+ unsigned n_dynamic_v4;
+ unsigned n_dynamic_v6;
fastd_protocol_config *protocol_config;
@@ -188,7 +190,7 @@ 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_resolve_peer(fastd_context *ctx, const fastd_peer_config *peer);
void fastd_printf(const fastd_context *ctx, const char *format, ...);
diff --git a/src/peer.c b/src/peer.c
index 1a6ddd9..1ad4c7f 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -251,7 +251,7 @@ void fastd_peer_config_purge(fastd_context *ctx, fastd_peer_config *conf) {
fastd_peer_config_free(conf);
}
-static bool fastd_peer_addr_equal(const fastd_peer_address *addr1, const fastd_peer_address *addr2) {
+bool fastd_peer_addr_equal(const fastd_peer_address *addr1, const fastd_peer_address *addr2) {
if (addr1->sa.sa_family != addr2->sa.sa_family)
return false;
@@ -330,9 +330,6 @@ fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *peer_conf) {
fastd_peer* fastd_peer_add_temp(fastd_context *ctx, const fastd_peer_address *address) {
fastd_peer *peer = add_peer(ctx);
- if (!ctx->conf->n_floating)
- exit_bug(ctx, "tried to add a temporary peer with no floating remotes defined");
-
peer->config = NULL;
peer->address = *address;
peer->state = STATE_TEMP;
@@ -409,6 +406,26 @@ const fastd_eth_addr* fastd_get_dest_address(const fastd_context *ctx, fastd_buf
}
}
+bool fastd_peer_config_matches_dynamic(const fastd_peer_config *config, const fastd_peer_address *addr) {
+ if (!config->hostname)
+ return false;
+
+ if (config->address.sa.sa_family != AF_UNSPEC &&
+ config->address.sa.sa_family != addr->sa.sa_family)
+ return false;
+
+ if (addr->sa.sa_family == AF_INET6) {
+ if (config->address.in.sin_port != addr->in6.sin6_port)
+ return false;
+ }
+ else {
+ if (config->address.in.sin_port != addr->in.sin_port)
+ return false;
+ }
+
+ return true;
+}
+
static inline int fastd_eth_addr_cmp(const fastd_eth_addr *addr1, const fastd_eth_addr *addr2) {
return memcmp(addr1->data, addr2->data, ETH_ALEN);
}
diff --git a/src/peer.h b/src/peer.h
index 7521799..f8b0f84 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -67,6 +67,8 @@ struct _fastd_peer_eth_addr {
};
+bool fastd_peer_addr_equal(const fastd_peer_address *addr1, const fastd_peer_address *addr2);
+
fastd_peer_config* fastd_peer_config_new(fastd_context *ctx, fastd_config *conf);
void fastd_peer_config_free(fastd_peer_config *peer);
void fastd_peer_config_delete(fastd_context *ctx, fastd_config *conf);
@@ -87,10 +89,16 @@ static inline bool fastd_peer_config_is_floating(const fastd_peer_config *config
return (config->hostname == NULL && config->address.sa.sa_family == AF_UNSPEC);
}
+bool fastd_peer_config_matches_dynamic(const fastd_peer_config *config, const fastd_peer_address *addr);
+
static inline bool fastd_peer_is_floating(const fastd_peer *peer) {
return (peer->config && fastd_peer_config_is_floating(peer->config));
}
+static inline bool fastd_peer_is_dynamic(const fastd_peer *peer) {
+ return (peer->config && peer->config->hostname);
+}
+
static inline bool fastd_peer_is_waiting(const fastd_peer *peer) {
return (peer->state == STATE_WAIT);
}
diff --git a/src/protocol_ec25519_fhmqvc.c b/src/protocol_ec25519_fhmqvc.c
index b4dab07..93fd9c4 100644
--- a/src/protocol_ec25519_fhmqvc.c
+++ b/src/protocol_ec25519_fhmqvc.c
@@ -245,10 +245,6 @@ static void protocol_handshake_init(fastd_context *ctx, fastd_peer *peer) {
fastd_send_handshake(ctx, peer, buffer);
}
-static inline bool has_field(const fastd_handshake *handshake, uint8_t type, size_t length) {
- return (handshake->records[type].length == length);
-}
-
static void respond_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) {
pr_debug(ctx, "responding handshake with %P...", peer);
@@ -454,20 +450,27 @@ static void handle_finish_handshake(fastd_context *ctx, fastd_peer *peer, const
&peer->protocol_state->accepting_handshake->sigma);
}
-static inline const fastd_peer_config* match_sender_key(fastd_context *ctx, const fastd_peer *peer, const unsigned char key[32]) {
+static inline const fastd_peer_config* match_sender_key(fastd_context *ctx, fastd_peer *peer, const unsigned char key[32]) {
if (peer->config) {
if (memcmp(peer->config->protocol_config->public_key.p, key, PUBLICKEYBYTES) == 0)
return peer->config;
}
- if (fastd_peer_is_temporary(peer) || fastd_peer_is_floating(peer)) {
+ if (fastd_peer_is_temporary(peer) || fastd_peer_is_floating(peer) || fastd_peer_is_dynamic(peer)) {
fastd_peer_config *config;
for (config = ctx->conf->peers; config; config = config->next) {
- if (!fastd_peer_config_is_floating(config))
+ if (!fastd_peer_config_is_floating(config) && !fastd_peer_config_matches_dynamic(config, &peer->address))
continue;
- if (memcmp(config->protocol_config->public_key.p, key, PUBLICKEYBYTES) == 0)
- return config;
+ if (memcmp(config->protocol_config->public_key.p, key, PUBLICKEYBYTES) == 0) {
+ if (fastd_peer_config_is_floating(config)) {
+ return config;
+ }
+ else { /* matches dynamic */
+ fastd_resolve_peer(ctx, config);
+ return NULL;
+ }
+ }
}
}
@@ -484,6 +487,10 @@ static void kill_handshakes(fastd_context *ctx, fastd_peer *peer) {
peer->protocol_state->accepting_handshake = NULL;
}
+static inline bool has_field(const fastd_handshake *handshake, uint8_t type, size_t length) {
+ return (handshake->records[type].length == length);
+}
+
static void protocol_handshake_handle(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) {
init_peer_state(ctx, peer);
@@ -493,6 +500,10 @@ static void protocol_handshake_handle(fastd_context *ctx, fastd_peer *peer, cons
}
const fastd_peer_config *peer_config = match_sender_key(ctx, peer, handshake->records[RECORD_SENDER_KEY].data);
+ if (!peer_config) {
+ pr_debug(ctx, "ignoring handshake from %P (unknown key or unresolved host)", peer);
+ return;
+ }
if (handshake->type > 1 && !has_field(handshake, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES)) {
pr_debug(ctx, "received handshake reply without receipient key from %P", peer);
diff --git a/src/resolve.c b/src/resolve.c
index 1fbb1bf..6afea91 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -38,12 +38,11 @@ typedef struct _resolv_arg {
fastd_context *ctx;
pthread_t master_thread;
char *hostname;
- sa_family_t af;
- uint16_t port;
+ fastd_peer_address constraints;
} resolv_arg;
-static void* fastd_resolve_peer_handshake_do(void *varg) {
+static void* resolve_peer(void *varg) {
resolv_arg *arg = varg;
struct addrinfo hints;
@@ -52,10 +51,10 @@ static void* fastd_resolve_peer_handshake_do(void *varg) {
bool error = false;
char portstr[6];
- snprintf(portstr, 6, "%u", arg->port);
+ snprintf(portstr, 6, "%u", ntohs(arg->constraints.in.sin_port));
memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = arg->af;
+ hints.ai_family = arg->constraints.sa.sa_family;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;
@@ -79,8 +78,7 @@ static void* fastd_resolve_peer_handshake_do(void *varg) {
ret->ctx = arg->ctx;
ret->hostname = arg->hostname;
- ret->af = arg->af;
- ret->port = arg->port;
+ ret->constraints = arg->constraints;
if (!error) {
pr_debug(arg->ctx, "Resolved host `%s' successfully", arg->hostname);
@@ -101,19 +99,18 @@ static void* fastd_resolve_peer_handshake_do(void *varg) {
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);
+void fastd_resolve_peer(fastd_context *ctx, const fastd_peer_config *peer) {
+ pr_debug(ctx, "Resolving host `%s' for peer `%s'...", peer->hostname, peer->name);
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);
+ arg->hostname = strdup(peer->hostname);
+ arg->constraints = peer->address;
pthread_t thread;
- if (pthread_create(&thread, NULL, fastd_resolve_peer_handshake_do, arg) != 0) {
+ if (pthread_create(&thread, NULL, resolve_peer, arg) != 0) {
pr_error_errno(ctx, "unable to create resolver thread");
free(arg->hostname);
free(arg);