diff options
-rw-r--r-- | src/fastd.c | 2 | ||||
-rw-r--r-- | src/fastd.h | 8 | ||||
-rw-r--r-- | src/receive.c | 33 | ||||
-rw-r--r-- | src/types.h | 1 |
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; |