summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/fastd.c2
-rw-r--r--src/fastd.h8
-rw-r--r--src/receive.c33
-rw-r--r--src/types.h1
4 files changed, 43 insertions, 1 deletions
diff --git a/src/fastd.c b/src/fastd.c
index 5be7a61..7c34720 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -921,6 +921,8 @@ int main(int argc, char *argv[]) {
ctx.next_keepalives = ctx.now;
ctx.next_keepalives.tv_sec += conf.keepalive_interval;
+ ctx.unknown_handshakes[0].timeout = ctx.now;
+
pr_info(&ctx, "fastd " FASTD_VERSION " starting");
fastd_cap_init(&ctx);
diff --git a/src/fastd.h b/src/fastd.h
index d03465d..268c2c7 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -138,6 +138,11 @@ struct fastd_stats {
uint64_t bytes;
};
+struct fastd_handshake_timeout {
+ fastd_peer_address_t address;
+ struct timespec timeout;
+};
+
struct fastd_config {
struct timespec long_ago;
@@ -281,6 +286,9 @@ struct fastd_context {
unsigned int randseed;
+ size_t unknown_handshake_pos;
+ fastd_handshake_timeout_t unknown_handshakes[8];
+
fastd_protocol_state_t *protocol_state;
};
diff --git a/src/receive.c b/src/receive.c
index 472b664..fa45dde 100644
--- a/src/receive.c
+++ b/src/receive.c
@@ -105,6 +105,35 @@ static inline bool allow_unknown_peers(fastd_context_t *ctx) {
return ctx->conf->has_floating || ctx->conf->on_verify;
}
+static inline bool backoff_unknown(fastd_context_t *ctx, const fastd_peer_address_t *addr) {
+ size_t i;
+ for (i = 0; i < array_size(ctx->unknown_handshakes); i++) {
+ const fastd_handshake_timeout_t *t = &ctx->unknown_handshakes[(ctx->unknown_handshake_pos + i) % array_size(ctx->unknown_handshakes)];
+
+ if (!timespec_after(&t->timeout, &ctx->now))
+ break;
+
+ if (fastd_peer_address_equal(addr, &t->address)) {
+ pr_debug2(ctx, "sent a handshake to unknown address %I a short time ago, not sending again", addr);
+ return true;
+ }
+ }
+
+ if (ctx->unknown_handshake_pos == 0)
+ ctx->unknown_handshake_pos = array_size(ctx->unknown_handshakes)-1;
+ else
+ ctx->unknown_handshake_pos--;
+
+ fastd_handshake_timeout_t *t = &ctx->unknown_handshakes[ctx->unknown_handshake_pos];
+
+ t->address = *addr;
+
+ t->timeout = ctx->now;
+ t->timeout.tv_sec += ctx->conf->min_handshake_interval;
+
+ return false;
+}
+
static inline void handle_socket_receive_unknown(fastd_context_t *ctx, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_buffer_t buffer) {
const uint8_t *packet_type = buffer.data;
fastd_buffer_push_head(ctx, &buffer, 1);
@@ -112,7 +141,9 @@ static inline void handle_socket_receive_unknown(fastd_context_t *ctx, fastd_soc
switch (*packet_type) {
case PACKET_DATA:
fastd_buffer_free(buffer);
- ctx->conf->protocol->handshake_init(ctx, sock, local_addr, remote_addr, NULL);
+
+ if (!backoff_unknown(ctx, remote_addr))
+ ctx->conf->protocol->handshake_init(ctx, sock, local_addr, remote_addr, NULL);
break;
case PACKET_HANDSHAKE:
diff --git a/src/types.h b/src/types.h
index acf97c6..17c058c 100644
--- a/src/types.h
+++ b/src/types.h
@@ -106,6 +106,7 @@ typedef struct fastd_peer_eth_addr fastd_peer_eth_addr_t;
typedef struct fastd_remote_config fastd_remote_config_t;
typedef struct fastd_remote fastd_remote_t;
typedef struct fastd_stats fastd_stats_t;
+typedef struct fastd_handshake_timeout fastd_handshake_timeout_t;
typedef struct fastd_log_file fastd_log_file_t;
typedef struct fastd_log_fd fastd_log_fd_t;