mirror of
https://github.com/transmission/transmission
synced 2025-03-03 02:05:19 +00:00
Import dht-0.21. This has blacklisting support.
This commit is contained in:
parent
fe42e456b4
commit
d40fea774b
5 changed files with 95 additions and 53 deletions
4
third-party/dht/CHANGES
vendored
4
third-party/dht/CHANGES
vendored
|
@ -1,3 +1,7 @@
|
|||
25 July 2011: dht-0.21
|
||||
|
||||
* Blacklisting support.
|
||||
|
||||
7 July 2011: dht-0.20
|
||||
|
||||
* Fix compilation on systems that have memmem but don't define HAVE_MEMMEM.
|
||||
|
|
6
third-party/dht/README
vendored
6
third-party/dht/README
vendored
|
@ -157,6 +157,12 @@ of the search.
|
|||
In the case of DHT_EVENT_VALUES, data is a list of nodes in ``compact''
|
||||
format -- 6 or 18 bytes per node. Its length in bytes is in data_len.
|
||||
|
||||
* dht_blacklisted
|
||||
|
||||
This is a function that takes an IP address and returns true if this
|
||||
address should be silently ignored. Do not use this feature unless you
|
||||
really must -- Kademlia supposes transitive reachability.
|
||||
|
||||
* dht_hash
|
||||
|
||||
This should compute a reasonably strong cryptographic hash of the passed
|
||||
|
|
8
third-party/dht/dht-example.c
vendored
8
third-party/dht/dht-example.c
vendored
|
@ -409,6 +409,14 @@ main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
/* Functions called by the DHT. */
|
||||
|
||||
int
|
||||
dht_blacklisted(const struct sockaddr *sa, int salen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We need to provide a reasonably strong cryptographic hashing function.
|
||||
Here's how we'd do it if we had RSA's MD5 code. */
|
||||
#if 0
|
||||
|
|
129
third-party/dht/dht.c
vendored
129
third-party/dht/dht.c
vendored
|
@ -212,6 +212,8 @@ struct storage {
|
|||
struct storage *next;
|
||||
};
|
||||
|
||||
static void flush_search_node(struct search_node *n, struct search *sr);
|
||||
|
||||
static int send_ping(const struct sockaddr *sa, int salen,
|
||||
const unsigned char *tid, int tid_len);
|
||||
static int send_pong(const struct sockaddr *sa, int salen,
|
||||
|
@ -636,6 +638,68 @@ send_cached_ping(struct bucket *b)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* Called whenever we send a request to a node, increases the ping count
|
||||
and, if that reaches 3, sends a ping to a new candidate. */
|
||||
static void
|
||||
pinged(struct node *n, struct bucket *b)
|
||||
{
|
||||
n->pinged++;
|
||||
n->pinged_time = now.tv_sec;
|
||||
if(n->pinged >= 3)
|
||||
send_cached_ping(b ? b : find_bucket(n->id, n->ss.ss_family));
|
||||
}
|
||||
|
||||
/* The internal blacklist is an LRU cache of nodes that have sent
|
||||
incorrect messages. */
|
||||
static void
|
||||
blacklist_node(const unsigned char *id, const struct sockaddr *sa, int salen)
|
||||
{
|
||||
int i;
|
||||
|
||||
debugf("Blacklisting broken node.\n");
|
||||
|
||||
if(id) {
|
||||
struct node *n;
|
||||
struct search *sr;
|
||||
/* Make the node easy to discard. */
|
||||
n = find_node(id, sa->sa_family);
|
||||
if(n) {
|
||||
n->pinged = 3;
|
||||
pinged(n, NULL);
|
||||
}
|
||||
/* Discard it from any searches in progress. */
|
||||
sr = searches;
|
||||
while(sr) {
|
||||
for(i = 0; i < sr->numnodes; i++)
|
||||
if(id_cmp(sr->nodes[i].id, id) == 0)
|
||||
flush_search_node(&sr->nodes[i], sr);
|
||||
sr = sr->next;
|
||||
}
|
||||
}
|
||||
/* And make sure we don't hear from it again. */
|
||||
memcpy(&blacklist[next_blacklisted], sa, salen);
|
||||
next_blacklisted = (next_blacklisted + 1) % DHT_MAX_BLACKLISTED;
|
||||
}
|
||||
|
||||
static int
|
||||
node_blacklisted(const struct sockaddr *sa, int salen)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(salen > sizeof(struct sockaddr_storage))
|
||||
abort();
|
||||
|
||||
if(dht_blacklisted(sa, salen))
|
||||
return 1;
|
||||
|
||||
for(i = 0; i < DHT_MAX_BLACKLISTED; i++) {
|
||||
if(memcmp(&blacklist[i], sa, salen) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Split a bucket into two equal parts. */
|
||||
static struct bucket *
|
||||
split_bucket(struct bucket *b)
|
||||
|
@ -674,16 +738,6 @@ split_bucket(struct bucket *b)
|
|||
return b;
|
||||
}
|
||||
|
||||
/* Called whenever we send a request to a node. */
|
||||
static void
|
||||
pinged(struct node *n, struct bucket *b)
|
||||
{
|
||||
n->pinged++;
|
||||
n->pinged_time = now.tv_sec;
|
||||
if(n->pinged >= 3)
|
||||
send_cached_ping(b ? b : find_bucket(n->id, n->ss.ss_family));
|
||||
}
|
||||
|
||||
/* We just learnt about a node, not necessarily a new one. Confirm is 1 if
|
||||
the node sent a message, 2 if it sent us a reply. */
|
||||
static struct node *
|
||||
|
@ -700,7 +754,7 @@ new_node(const unsigned char *id, const struct sockaddr *sa, int salen,
|
|||
if(id_cmp(id, myid) == 0)
|
||||
return NULL;
|
||||
|
||||
if(is_martian(sa))
|
||||
if(is_martian(sa) || node_blacklisted(sa, salen))
|
||||
return NULL;
|
||||
|
||||
mybucket = in_bucket(myid, b);
|
||||
|
@ -1328,37 +1382,6 @@ expire_storage(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* We've just found out that a node is buggy. */
|
||||
static void
|
||||
broken_node(const unsigned char *id, const struct sockaddr *sa, int salen)
|
||||
{
|
||||
int i;
|
||||
|
||||
debugf("Blacklisting broken node.\n");
|
||||
|
||||
if(id) {
|
||||
struct node *n;
|
||||
struct search *sr;
|
||||
/* Make the node easy to discard. */
|
||||
n = find_node(id, sa->sa_family);
|
||||
if(n) {
|
||||
n->pinged = 3;
|
||||
pinged(n, NULL);
|
||||
}
|
||||
/* Discard it from any searches in progress. */
|
||||
sr = searches;
|
||||
while(sr) {
|
||||
for(i = 0; i < sr->numnodes; i++)
|
||||
if(id_cmp(sr->nodes[i].id, id) == 0)
|
||||
flush_search_node(&sr->nodes[i], sr);
|
||||
sr = sr->next;
|
||||
}
|
||||
}
|
||||
/* And make sure we don't hear from it again. */
|
||||
memcpy(&blacklist[next_blacklisted], sa, salen);
|
||||
next_blacklisted = (next_blacklisted + 1) % DHT_MAX_BLACKLISTED;
|
||||
}
|
||||
|
||||
static int
|
||||
rotate_secrets(void)
|
||||
{
|
||||
|
@ -1846,8 +1869,6 @@ dht_periodic(const void *buf, size_t buflen,
|
|||
time_t *tosleep,
|
||||
dht_callback *callback, void *closure)
|
||||
{
|
||||
int i;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
if(buflen > 0) {
|
||||
|
@ -1865,15 +1886,11 @@ dht_periodic(const void *buf, size_t buflen,
|
|||
if(is_martian(from))
|
||||
goto dontread;
|
||||
|
||||
for(i = 0; i < DHT_MAX_BLACKLISTED; i++) {
|
||||
if(memcmp(&blacklist[i], from, fromlen) == 0) {
|
||||
debugf("Received packet from blacklisted node.\n");
|
||||
goto dontread;
|
||||
}
|
||||
if(node_blacklisted(from, fromlen)) {
|
||||
debugf("Received packet from blacklisted node.\n");
|
||||
goto dontread;
|
||||
}
|
||||
|
||||
/* See parse_message. */
|
||||
|
||||
if(((char*)buf)[buflen] != '\0') {
|
||||
debugf("Unterminated message.\n");
|
||||
errno = EINVAL;
|
||||
|
@ -1915,7 +1932,7 @@ dht_periodic(const void *buf, size_t buflen,
|
|||
/* This is really annoying, as it means that we will
|
||||
time-out all our searches that go through this node.
|
||||
Kill it. */
|
||||
broken_node(id, from, fromlen);
|
||||
blacklist_node(id, from, fromlen);
|
||||
goto dontread;
|
||||
}
|
||||
if(tid_match(tid, "pn", NULL)) {
|
||||
|
@ -1933,7 +1950,7 @@ dht_periodic(const void *buf, size_t buflen,
|
|||
gp ? " for get_peers" : "");
|
||||
if(nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
|
||||
debugf("Unexpected length for node info!\n");
|
||||
broken_node(id, from, fromlen);
|
||||
blacklist_node(id, from, fromlen);
|
||||
} else if(gp && sr == NULL) {
|
||||
debugf("Unknown search!\n");
|
||||
new_node(id, from, fromlen, 1);
|
||||
|
@ -2300,6 +2317,12 @@ dht_send(const void *buf, size_t len, int flags,
|
|||
if(salen == 0)
|
||||
abort();
|
||||
|
||||
if(node_blacklisted(sa, salen)) {
|
||||
debugf("Attempting to send to blacklisted node.\n");
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(sa->sa_family == AF_INET)
|
||||
s = dht_socket;
|
||||
else if(sa->sa_family == AF_INET6)
|
||||
|
|
1
third-party/dht/dht.h
vendored
1
third-party/dht/dht.h
vendored
|
@ -50,6 +50,7 @@ int dht_get_nodes(struct sockaddr_in *sin, int *num,
|
|||
int dht_uninit(void);
|
||||
|
||||
/* This must be provided by the user. */
|
||||
int dht_blacklisted(const struct sockaddr *sa, int salen);
|
||||
void dht_hash(void *hash_return, int hash_size,
|
||||
const void *v1, int len1,
|
||||
const void *v2, int len2,
|
||||
|
|
Loading…
Reference in a new issue