summaryrefslogtreecommitdiffstats
path: root/src/dht.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dht.c')
-rw-r--r--src/dht.c87
1 files changed, 52 insertions, 35 deletions
diff --git a/src/dht.c b/src/dht.c
index 83fcb68..4e57e5e 100644
--- a/src/dht.c
+++ b/src/dht.c
@@ -794,6 +794,8 @@ struct dht * dht_init (const struct bencoding * c) {
#pragma GCC diagnostic pop
goto e;
}
+#define TOOMUCH 32727
+ unsigned pinged = 0;
if (c) {
const struct bencoding * id = bpath(c, "id");
if (id && id->type & string && id->valuelen == 20)
@@ -811,7 +813,7 @@ struct dht * dht_init (const struct bencoding * c) {
.sin6_family = AF_INET6,
.sin6_port = htons(atoi(++port))
};
- if (inet_pton(AF_INET6, remote, addr.sin6_addr.s6_addr) == 1)
+ if (inet_pton(AF_INET6, remote, addr.sin6_addr.s6_addr) == 1 && pinged++ < TOOMUCH/2)
ping_node(d, &addr);
}
}
@@ -2172,6 +2174,30 @@ d:
} // do not log, it may have been a bencoded reply
}
+/**
+ * delete all but first bucket in ll, used in refresh on both lls (v4 and v6) in case of sybil
+ *
+ * @param b [in] first bucket in ll
+ */
+
+void delete_buckets (struct bucket * b) {
+ struct node * n = b->nodes;
+ while (n) {
+ struct node * old = n;
+ n = n->next;
+ node_free(old);
+ }
+ b->nodes = NULL;
+ memset(b->id, '\0', 20);
+ struct bucket * del = b->next;
+ b->next = NULL;
+ while (del) {
+ struct bucket * old = del;
+ del = del->next;
+ bucket_free(old);
+ }
+}
+
#define PERIODIC 10
/**
@@ -2214,33 +2240,10 @@ int refresh (struct dht * d, int fam) {
if (buckets > 64) { // sybil attack - node is broken - clear whole routing table, keeping one bucket
dht_print(d->log, d);
L(disagreement, d, "@@@@@@ SYBIL ATTACK - CLEARING ROUTING TABLE @@@@@@");
- int keep_first = rand() % 2; // should we even keep one bucket? the sybil node has a 1/2
- if (keep_first) { // chance of having stared in the bucket farthest away, so it's stored there ...
- memset(d->buckets->id, '\0', 20);
- b = d->buckets->next;
- d->buckets->next = NULL;
- while (b) {
- bucket_free(b);
- b = b->next;
- }
- } else {
- b = d->buckets;
- while (b->next) {
- struct bucket * old = b;
- b = b->next;
- bucket_free(old);
- }
- d->buckets = b;
- memset(d->buckets->id, '\0', 20);
- }
+ delete_buckets(d->buckets);
+ delete_buckets(d->buckets6);
if (getrandom(d->id, 20, GRND_NONBLOCK) == -1) // changing our ID. note that this might make
- L(std_fail, d, "getrandom: %s", strerror(errno)); // existing nodes hate us
- switch (fam) {
- case AF_INET:
- return node_count(d->buckets6->nodes);
- case AF_INET6:
- return node_count(d->buckets6->nodes);
- }
+ L(std_fail, d, "getrandom: %s", strerror(errno)); // existing nodes hate us, though we'll probably have no existing nodes
return 0;
}
return nrgood;
@@ -2337,25 +2340,36 @@ void periodic (struct dht * d) {
if (t->type & (peers | announce)) {
struct node * n = t->nodes;
int sent = 0;
- while (n) {
- sent++;
+ int c = node_count(n);
+ if (c)
+ c = rand() % c;
+ while (n && c--)
+ n = n->next;
+ if (n && sent < 3) { // we pick some consecutive at random and ping them.
+ sent++; // increase to more than this if desired ... idk this is shit
if (!n->unanswered)
n->last_sent = seconds();
n->unanswered++;
get_peers(d, &n->addr, t->hash);
n = n->next;
+ if (!n && !t->nodes->unanswered) // if unanswered, we already sent it
+ n = t->nodes;
}
- if (sent < 1) {
+ if (sent < 2) {
#define RTGP(buckets) {struct bucket * b = d->buckets; \
find(t->hash, &b, NULL); \
struct node * n = b->nodes; \
- while (sent < 1 && n) { \
+ int c = node_count(n); \
+ if (c) \
+ c = rand() % c; \
+ while (n && c--) \
+ n = n->next; \
+ if (n) { \
sent++; \
if (!n->unanswered) \
n->last_sent = seconds(); \
n->unanswered++; \
get_peers(d, &n->addr, t->hash); \
- n = n->next; \
}}
RTGP(buckets);
RTGP(buckets6);
@@ -2364,13 +2378,17 @@ void periodic (struct dht * d) {
struct bucket * b = d->buckets;
while (sent < 1 && b) {
n = b->nodes;
- while (sent < 1 && n) {
+ int c = node_count(n);
+ if (c)
+ c = rand() % c;
+ while (n && c--)
+ n = n->next;
+ if (sent < 1 && n) {
sent++;
if (!n->unanswered)
n->last_sent = seconds();
n->unanswered++;
get_peers(d, &n->addr, t->hash);
- n = n->next;
}
b = b->next;
}
@@ -2435,7 +2453,6 @@ void periodic (struct dht * d) {
t = t->next;
}
L(debug, d, "txqp=%u rxrp=%u rxqp=%u txrp=%u", d->txqp, d->rxrp, d->rxqp, d->txrp);
-#define TOOMUCH 32727
if (d->txqp > TOOMUCH || d->rxrp > TOOMUCH || d->rxqp > TOOMUCH || d->txrp > TOOMUCH) {
dht_print(stdout, d);
raise(SIGABRT);