diff options
Diffstat (limited to 'src/dht.c')
-rw-r--r-- | src/dht.c | 87 |
1 files changed, 52 insertions, 35 deletions
@@ -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); |