From c6e6c751546124134ed0087bd30a1905a8d4a99d Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 7 Mar 2012 02:12:36 +0100 Subject: Forget old peers and addresses --- src/peer.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 164 insertions(+), 24 deletions(-) (limited to 'src/peer.c') diff --git a/src/peer.c b/src/peer.c index 5cce906..83cc1b0 100644 --- a/src/peer.c +++ b/src/peer.c @@ -25,6 +25,8 @@ */ +#define _GNU_SOURCE + #include "peer.h" #include "task.h" @@ -49,6 +51,66 @@ const fastd_eth_addr* fastd_get_dest_address(const fastd_context *ctx, fastd_buf } } +static inline void reset_peer(fastd_context *ctx, fastd_peer *peer) { + int i, deleted = 0; + for (i = 0; i < ctx->n_eth_addr; i++) { + if (ctx->eth_addr[i].peer == peer) { + deleted++; + } + else if (deleted) { + ctx->eth_addr[i-deleted] = ctx->eth_addr[i]; + } + } + + ctx->n_eth_addr -= deleted; + + fastd_task_delete_peer(ctx, peer); + +} + +static inline void setup_peer(fastd_context *ctx, fastd_peer *peer) { + if (fastd_peer_is_temporary(peer)) { + exit_fatal(ctx, "tried to reset temporary peer"); + } + + peer->address = peer->config->address; + peer->state = STATE_WAIT; + peer->seen = (struct timespec){0, 0}; + + if (!fastd_peer_is_floating(peer)) + fastd_task_schedule_handshake(ctx, peer, 0); +} + +void fastd_peer_reset(fastd_context *ctx, fastd_peer *peer) { + if (is_debug(ctx)) { + char buf[INET6_ADDRSTRLEN] = ""; + + switch (peer->address.sa.sa_family) { + case AF_UNSPEC: + pr_debug(ctx, "resetting peer "); + break; + + case AF_INET: + if (inet_ntop(AF_INET, &peer->address.in.sin_addr, buf, sizeof(buf))) + pr_debug(ctx, "resetting peer %s:%u", buf, ntohs(peer->address.in.sin_port)); + break; + + case AF_INET6: + if (inet_ntop(AF_INET6, &peer->address.in6.sin6_addr, buf, sizeof(buf))) + pr_debug(ctx, "resetting peer [%s]:%u", buf, ntohs(peer->address.in6.sin6_port)); + break; + + default: + exit_bug(ctx, "unsupported address family"); + } + } + + reset_peer(ctx, peer); + setup_peer(ctx, peer); +} + + + static fastd_peer* add_peer(fastd_context *ctx) { fastd_peer *peer = malloc(sizeof(fastd_peer)); @@ -63,26 +125,27 @@ static fastd_peer* add_peer(fastd_context *ctx) { fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *peer_conf) { fastd_peer *peer = add_peer(ctx); + peer->config = peer_conf; - peer->address = peer_conf->address; - peer->state = STATE_WAIT; + + setup_peer(ctx, peer); if (is_debug(ctx)) { char buf[INET6_ADDRSTRLEN] = ""; switch (peer->address.sa.sa_family) { case AF_UNSPEC: - pr_debug(ctx, "added peer "); + pr_debug(ctx, "adding peer "); break; case AF_INET: if (inet_ntop(AF_INET, &peer->address.in.sin_addr, buf, sizeof(buf))) - pr_debug(ctx, "added peer %s:%u", buf, ntohs(peer->address.in.sin_port)); + pr_debug(ctx, "adding peer %s:%u", buf, ntohs(peer->address.in.sin_port)); break; case AF_INET6: if (inet_ntop(AF_INET6, &peer->address.in6.sin6_addr, buf, sizeof(buf))) - pr_debug(ctx, "added peer [%s]:%u", buf, ntohs(peer->address.in6.sin6_port)); + pr_debug(ctx, "adding peer [%s]:%u", buf, ntohs(peer->address.in6.sin6_port)); break; default: @@ -90,9 +153,6 @@ fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *peer_conf) { } } - if (!fastd_peer_is_floating(peer)) - fastd_task_schedule_handshake(ctx, peer, 0); - return peer; } @@ -105,6 +165,7 @@ fastd_peer* fastd_peer_add_temp(fastd_context *ctx, const fastd_peer_address *ad peer->config = NULL; peer->address = *address; peer->state = STATE_TEMP; + peer->seen = ctx->now; if (is_debug(ctx)) { char buf[INET6_ADDRSTRLEN] = ""; @@ -112,12 +173,12 @@ fastd_peer* fastd_peer_add_temp(fastd_context *ctx, const fastd_peer_address *ad switch (peer->address.sa.sa_family) { case AF_INET: if (inet_ntop(AF_INET, &peer->address.in.sin_addr, buf, sizeof(buf))) - pr_debug(ctx, "added peer %s:%u (temporary)", buf, ntohs(peer->address.in.sin_port)); + pr_debug(ctx, "adding peer %s:%u (temporary)", buf, ntohs(peer->address.in.sin_port)); break; case AF_INET6: if (inet_ntop(AF_INET6, &peer->address.in6.sin6_addr, buf, sizeof(buf))) - pr_debug(ctx, "added peer [%s]:%u (temporary)", buf, ntohs(peer->address.in6.sin6_port)); + pr_debug(ctx, "adding peer [%s]:%u (temporary)", buf, ntohs(peer->address.in6.sin6_port)); break; default: @@ -129,10 +190,56 @@ fastd_peer* fastd_peer_add_temp(fastd_context *ctx, const fastd_peer_address *ad } fastd_peer* fastd_peer_merge(fastd_context *ctx, fastd_peer *perm_peer, fastd_peer *temp_peer) { - pr_debug(ctx, "merging peers"); + if (is_debug(ctx)) { + char buf[INET6_ADDRSTRLEN]; + char *str_perm = NULL, *str_temp = NULL; + + switch (perm_peer->address.sa.sa_family) { + case AF_UNSPEC: + str_perm = strdup(""); + break; + + case AF_INET: + if (inet_ntop(AF_INET, &perm_peer->address.in.sin_addr, buf, sizeof(buf))) + asprintf(&str_perm, "%s:%u", buf, ntohs(perm_peer->address.in.sin_port)); + break; + + case AF_INET6: + if (inet_ntop(AF_INET6, &perm_peer->address.in6.sin6_addr, buf, sizeof(buf))) + asprintf(&str_perm, "[%s]:%u", buf, ntohs(perm_peer->address.in.sin_port)); + break; + + default: + exit_bug(ctx, "unsupported address family"); + } + + switch (temp_peer->address.sa.sa_family) { + case AF_UNSPEC: + str_temp = strdup(""); + break; + + case AF_INET: + if (inet_ntop(AF_INET, &temp_peer->address.in.sin_addr, buf, sizeof(buf))) + asprintf(&str_temp, "%s:%u", buf, ntohs(temp_peer->address.in.sin_port)); + break; + + case AF_INET6: + if (inet_ntop(AF_INET6, &temp_peer->address.in6.sin6_addr, buf, sizeof(buf))) + asprintf(&str_temp, "[%s]:%u", buf, ntohs(temp_peer->address.in.sin_port)); + break; + + default: + exit_bug(ctx, "unsupported address family"); + } + + pr_debug(ctx, "merging peer %s into %s", str_temp, str_perm); + free(str_temp); + free(str_perm); + } perm_peer->address = temp_peer->address; perm_peer->state = fastd_peer_is_established(temp_peer) ? STATE_ESTABLISHED : STATE_WAIT; + perm_peer->seen = temp_peer->seen; int i; for (i = 0; i < ctx->n_eth_addr; i++) { @@ -147,18 +254,30 @@ fastd_peer* fastd_peer_merge(fastd_context *ctx, fastd_peer *perm_peer, fastd_pe } void fastd_peer_delete(fastd_context *ctx, fastd_peer *peer) { - int i, deleted = 0; + if (is_debug(ctx)) { + char buf[INET6_ADDRSTRLEN]; - for (i = 0; i < ctx->n_eth_addr; i++) { - if (ctx->eth_addr[i].peer == peer) { - deleted++; - } - else if (deleted) { - ctx->eth_addr[i-deleted] = ctx->eth_addr[i]; + switch (peer->address.sa.sa_family) { + case AF_UNSPEC: + pr_debug(ctx, "deleting peer "); + break; + + case AF_INET: + if (inet_ntop(AF_INET, &peer->address.in.sin_addr, buf, sizeof(buf))) + pr_debug(ctx, "deleting peer %s:%u%s", buf, ntohs(peer->address.in.sin_port), fastd_peer_is_temporary(peer) ? " (temporary)" : ""); + break; + + case AF_INET6: + if (inet_ntop(AF_INET6, &peer->address.in6.sin6_addr, buf, sizeof(buf))) + pr_debug(ctx, "deleting peer [%s]:%u%s", buf, ntohs(peer->address.in6.sin6_port), fastd_peer_is_temporary(peer) ? " (temporary)" : ""); + break; + + default: + exit_bug(ctx, "unsupported address family"); } } - ctx->n_eth_addr -= deleted; + reset_peer(ctx, peer); fastd_peer **cur_peer; for (cur_peer = &ctx->peers; *cur_peer; cur_peer = &(*cur_peer)->next) { @@ -168,8 +287,6 @@ void fastd_peer_delete(fastd_context *ctx, fastd_peer *peer) { } } - fastd_task_delete_peer(ctx, peer); - free(peer); } @@ -182,11 +299,11 @@ static inline int fastd_peer_eth_addr_cmp(const fastd_peer_eth_addr *addr1, cons } static inline fastd_peer_eth_addr* peer_get_by_addr(fastd_context *ctx, const fastd_eth_addr *addr) { - return bsearch(((uint8_t*)addr)-offsetof(fastd_peer_eth_addr, addr), ctx->eth_addr, ctx->n_eth_addr, sizeof(fastd_peer_eth_addr), + return bsearch(container_of(addr, fastd_peer_eth_addr, addr), ctx->eth_addr, ctx->n_eth_addr, sizeof(fastd_peer_eth_addr), (int (*)(const void *, const void *))fastd_peer_eth_addr_cmp); } -void fastd_peer_add_eth_addr(fastd_context *ctx, fastd_peer *peer, const fastd_eth_addr *addr) { +void fastd_peer_eth_addr_add(fastd_context *ctx, fastd_peer *peer, const fastd_eth_addr *addr) { int min = 0, max = ctx->n_eth_addr; while (max > min) { @@ -195,6 +312,7 @@ void fastd_peer_add_eth_addr(fastd_context *ctx, fastd_peer *peer, const fastd_e if (cmp == 0) { ctx->eth_addr[cur].peer = peer; + ctx->eth_addr[cur].seen = ctx->now; return; /* We're done here. */ } else if (cmp < 0) { @@ -219,7 +337,29 @@ void fastd_peer_add_eth_addr(fastd_context *ctx, fastd_peer *peer, const fastd_e for (i = ctx->n_eth_addr-1; i > min+1; i--) ctx->eth_addr[i] = ctx->eth_addr[i-1]; - ctx->eth_addr[min] = (fastd_peer_eth_addr){ *addr, peer }; + ctx->eth_addr[min] = (fastd_peer_eth_addr){ *addr, peer, ctx->now }; + + pr_debug(ctx, "Learned new MAC address %02x:%02x:%02x:%02x:%02x:%02x", + addr->data[0], addr->data[1], addr->data[2], addr->data[3], addr->data[4], addr->data[5]); +} + +void fastd_peer_eth_addr_cleanup(fastd_context *ctx) { + int i, deleted = 0; + + for (i = 0; i < ctx->n_eth_addr; i++) { + if (timespec_diff(&ctx->now, &ctx->eth_addr[i].seen) > ctx->conf->eth_addr_stale_time*1000) { + deleted++; + pr_debug(ctx, "MAC address %02x:%02x:%02x:%02x:%02x:%02x not seen for more than %u seconds, removing", + ctx->eth_addr[i].addr.data[0], ctx->eth_addr[i].addr.data[1], ctx->eth_addr[i].addr.data[2], + ctx->eth_addr[i].addr.data[3], ctx->eth_addr[i].addr.data[4], ctx->eth_addr[i].addr.data[5], + ctx->conf->eth_addr_stale_time); + } + else if (deleted) { + ctx->eth_addr[i-deleted] = ctx->eth_addr[i]; + } + } + + ctx->n_eth_addr -= deleted; } fastd_peer *fastd_peer_find_by_eth_addr(fastd_context *ctx, const fastd_eth_addr *addr) { -- cgit v1.2.3