summaryrefslogtreecommitdiffstats
path: root/src/peer.c
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-03-07 02:12:36 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-03-07 02:12:36 +0100
commitc6e6c751546124134ed0087bd30a1905a8d4a99d (patch)
tree0c2c8eaf4fa5d7d1ba4e10e302a7cb8df995d47b /src/peer.c
parentf8a2fec8f399229d15d3481be0ce8567b2ed6851 (diff)
downloadfastd-c6e6c751546124134ed0087bd30a1905a8d4a99d.tar
fastd-c6e6c751546124134ed0087bd30a1905a8d4a99d.zip
Forget old peers and addresses
Diffstat (limited to 'src/peer.c')
-rw-r--r--src/peer.c188
1 files changed, 164 insertions, 24 deletions
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 <floating>");
+ 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 <floating>");
+ pr_debug(ctx, "adding peer <floating>");
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("<floating>");
+ 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("<floating>");
+ 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 <floating>");
+ 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) {