Example #1
0
/*
* Lookup known nodes that are nearest to the given id.
*/
int kad_lookup_value( const char query[], IP addr_array[], size_t *addr_num ) {
	char hexbuf[SHA1_HEX_LENGTH+1];
	UCHAR id[SHA1_BIN_LENGTH];
	int rc;

	/* Generate the id, e.g. id = sha1(query) */
	id_compute( id, query );

	log_debug( "KAD: Lookup '%s' as '%s'.", query, str_id( id, hexbuf ) );

	dht_lock();

	rc = results_collect( id, addr_array, *addr_num );

	if( rc < 0 ) {
		/* No results item found - no search in progress - start search */
		dht_lock();
		results_add( id, query );
		dht_search( id, 0, gconf->af, dht_callback_func, NULL );
		dht_unlock();
		*addr_num = 0;
		rc = -1;
	} else {
		*addr_num = rc;
		rc = 0;
	}

	dht_unlock();

	return rc;
}
Example #2
0
/* Handle incoming packets and pass them to the DHT code */
void dht_handler( int rc, int sock ) {
	UCHAR buf[1500];
    IP from;
    socklen_t fromlen;
	time_t time_wait = 0;

	if( rc > 0 ) {
		/* Check which socket received the data */
		fromlen = sizeof(from);
		rc = recvfrom( sock, buf, sizeof(buf) - 1, 0, (struct sockaddr*) &from, &fromlen );

		if( rc <= 0 || rc >= sizeof(buf) ) {
			return;
		}

		/* The DHT code expects the message to be null-terminated. */
		buf[rc] = '\0';

		/* Handle incoming data */
		dht_lock();
		rc = dht_periodic( buf, rc, (struct sockaddr*) &from, fromlen, &time_wait, dht_callback_func, NULL );
		dht_unlock();

		if( rc < 0 && errno != EINTR ) {
			if( rc == EINVAL || rc == EFAULT ) {
				log_err( "DHT: Error calling dht_periodic." );
			}
			g_dht_maintenance = time_now_sec() + 1;
		} else {
			g_dht_maintenance = time_now_sec() + time_wait;
		}
	} else if( g_dht_maintenance <= time_now_sec() ) {
		/* Do a maintenance call */
		dht_lock();
		rc = dht_periodic( NULL, 0, NULL, 0, &time_wait, dht_callback_func, NULL );
		dht_unlock();

		/* Wait for the next maintenance call */
		g_dht_maintenance = time_now_sec() + time_wait;
		log_debug( "DHT: Next maintenance call in %u seconds.", (unsigned int) time_wait );
	} else {
		rc = 0;
	}

	if( rc < 0 ) {
		if( errno == EINTR ) {
			return;
		} else if( rc == EINVAL || rc == EFAULT ) {
			log_err( "DHT: Error using select: %s", strerror( errno ) );
			return;
		} else {
			g_dht_maintenance = time_now_sec() + 1;
		}
	}
}
Example #3
0
/* Print announced ids we have received */
void kad_debug_storage( int fd ) {
	char addrbuf[FULL_ADDSTRLEN+1];
	char hexbuf[SHA1_HEX_LENGTH+1];
	struct storage *s = storage;
	IP addr;
	int i, j;

	dht_lock();

	for( j = 0; s != NULL; ++j ) {
		dprintf( fd, "Id: %s\n", str_id(s->id, hexbuf ));
		for( i = 0; i < s->numpeers; ++i ) {
			struct peer* p = &s->peers[i];
			if( p->len == 16 ) {
				IP6 *a = (IP6 *) &addr;
				a->sin6_family = AF_INET6;
				a->sin6_port = htons( p->port );
				memcpy( &a->sin6_addr, p->ip, 16 );
			} else {
				IP4 *a = (IP4 *) &addr;
				a->sin_family = AF_INET;
				a->sin_port = htons( p->port );
				memcpy( &a->sin_addr, p->ip, 4 );
			}
			dprintf( fd, "  Peer: %s\n", str_addr( &addr, addrbuf)  );
		}
		dprintf( fd, " Found %d peers.\n", i );
		s = s->next;
	}
	dprintf( fd, " Found %d stored hashes from received announcements.\n", j );

	dht_unlock();
}
Example #4
0
/* Print searches */
void kad_debug_searches( int fd ) {
	char addrbuf[FULL_ADDSTRLEN+1];
	char hexbuf[SHA1_HEX_LENGTH+1];
	struct search *s = searches;
	int i, j;

	dht_lock();

	for( j = 0; s != NULL; ++j ) {
		dprintf( fd, " Search: %s\n", str_id( s->id, hexbuf ) );
		dprintf( fd, "  af: %s\n", (s->af == AF_INET) ? "AF_INET" : "AF_INET6" );
		dprintf( fd, "  port: %hu\n", s->port );
		dprintf( fd, "  done: %d\n", s->done );
		for(i = 0; i < s->numnodes; ++i) {
			struct search_node *sn = &s->nodes[i];
			dprintf( fd, "   Node: %s\n", str_id(sn->id, hexbuf ) );
			dprintf( fd, "    addr: %s\n", str_addr( &sn->ss, addrbuf ) );
			dprintf( fd, "    pinged: %d\n", sn->pinged );
			dprintf( fd, "    replied: %d\n", sn->replied );
			dprintf( fd, "    acked: %d\n", sn->acked );
		}
		dprintf( fd, "  Found %d nodes.\n", i );
		s = s->next;
	}
	dprintf( fd, " Found %d searches.\n", j );

	dht_unlock();
}
Example #5
0
/* Print buckets (leaf/finger table) */
void kad_debug_buckets( int fd ) {
	char addrbuf[FULL_ADDSTRLEN+1];
	char hexbuf[SHA1_HEX_LENGTH+1];
	struct bucket *b;
	struct node *n;
	int i, j;

	dht_lock();

	b = (gconf->af == AF_INET) ? buckets : buckets6;
	for( j = 0; b != NULL; ++j ) {
		dprintf( fd, " Bucket: %s\n", str_id( b->first, hexbuf ) );

		n = b->nodes;
		for( i = 0; n != NULL; ++i ) {
			dprintf( fd, "   Node: %s\n", str_id( n->id, hexbuf ) );
			dprintf( fd, "    addr: %s\n", str_addr( &n->ss, addrbuf ) );
			dprintf( fd, "    pinged: %d\n", n->pinged );
			n = n->next;
		}
		dprintf( fd, "  Found %d nodes.\n", i );
		b = b->next;
	}
	dprintf( fd, " Found %d buckets.\n", j );

	dht_unlock();
}
Example #6
0
int kad_export_nodes( IP addr_array[], size_t *num ) {
	IP4 addr4[64];
	IP6 addr6[64];
	int num4;
	int num6;
	int i, count;

	num6 = N_ELEMS( addr6 );
	num4 = N_ELEMS( addr4 );

	dht_lock();
	dht_get_nodes( addr4, &num4, addr6, &num6 );
	dht_unlock();

	count = 0;

	for( i = 0; i < num6 && count < *num; ++i, ++count ) {
		memcpy( &addr_array[i], &addr6[i], sizeof(IP6) );
	}

	for( i = 0; i < num4 && count < *num; ++i, ++count ) {
		memcpy( &addr_array[i], &addr4[i], sizeof(IP4) );
	}

	/* Store number of nodes we have actually found */
	*num = count;

	return 0;
}
Example #7
0
/*
* Lookup the address of the node that has the given id.
* The port refers to the kad instance.
*/
int kad_lookup_node( const char query[], IP *addr_return ) {
	UCHAR id[SHA1_BIN_LENGTH];
	struct search *sr;
	int i, rc;

	/* That is the node id to lookup */
	id_compute( id, query );

	dht_lock();

	rc = -1;
	sr = searches;
    while( sr ) {
		if( sr->af == gconf->af && id_equal( sr->id, id ) ) {
			for( i = 0; i < sr->numnodes; ++i ) {
				if( id_equal( sr->nodes[i].id, id ) ) {
					memcpy( addr_return, &sr->nodes[i].ss, sizeof(IP) );
					rc = 0;
					goto done;
				}
			}
			break;
		}
        sr = sr->next;
    }

	done:;

	dht_unlock();

	return rc;
}
Example #8
0
/* Print announced ids we have received */
void kad_debug_storage( int fd ) {
	char addrbuf[FULL_ADDSTRLEN+1];
	char hexbuf[SHA1_HEX_LENGTH+1];
	struct storage *s;
	struct peer* p;
	IP addr;
	int i, j;

	dht_lock();

	s = storage;
	for( j = 0; s != NULL; ++j ) {
		dprintf( fd, " ID: %s\n", str_id(s->id, hexbuf ));
		for( i = 0; i < s->numpeers; ++i ) {
			p = &s->peers[i];
			to_addr( &addr, &p->ip, p->len, htons( p->port ) );
			dprintf( fd, "   Peer: %s\n", str_addr( &addr, addrbuf)  );
		}
		dprintf( fd, "  Found %d peers.\n", i );
		s = s->next;
	}
	dprintf( fd, " Found %d stored hashes from received announcements.\n", j );

	dht_unlock();
}
Example #9
0
/*
* Lookup the address of the node that has the given id.
* The port refers to the kad instance.
*/
int kad_lookup_node( const char query[], IP *addr_return ) {
	UCHAR id[SHA1_BIN_LENGTH];
	struct search *sr;
	int i, rc;

	if( strlen( query ) != SHA1_HEX_LENGTH || !str_isHex( query, SHA1_HEX_LENGTH ) ) {
		return -1;
	}

	bytes_from_hex( id, query, SHA1_HEX_LENGTH );

	dht_lock();

	rc = 1;
	sr = searches;
	while( sr ) {
		if( sr->af == gconf->af && id_equal( sr->id, id ) ) {
			for( i = 0; i < sr->numnodes; ++i ) {
				if( id_equal( sr->nodes[i].id, id ) ) {
					memcpy( addr_return, &sr->nodes[i].ss, sizeof(IP) );
					rc = 0;
					goto done;
				}
			}
			break;
		}
		sr = sr->next;
	}

	done:;

	dht_unlock();

	return rc;
}
Example #10
0
int kad_blacklist( const IP* addr ) {

	dht_lock();
	blacklist_node( NULL, (struct sockaddr *) addr, sizeof(IP) );
	dht_unlock();

	return 0;
}
Example #11
0
int kad_ping( const IP* addr ) {
	int rc;

	dht_lock();
	rc = dht_ping_node( (struct sockaddr *)addr, addr_len( addr ) );
	dht_unlock();

	return (rc < 0) ? -1 : 0;
}
Example #12
0
/*
* Lookup known nodes that are nearest to the given id.
*/
int kad_lookup_value( const char _query[], IP addr_array[], size_t *addr_num ) {
	char query[QUERY_MAX_SIZE];
	struct results_t *results;
	int is_new;
	int rc;

	if( query_sanitize( query, sizeof(query), _query ) != 0 ) {
		return -2;
	}

	log_debug( "KAD: Lookup string: %s", query );

	dht_lock();

	/* Find existing or create new item */
	results = results_add( query, &is_new );

	if( results && is_new ) {
		/* Search own announced values */
		kad_lookup_local_values( results );
	}

	if( results == NULL ) {
		/* Failed to create a new search */
		rc = -1;
	} else if( results->done ) {
		/*
		* The search exists already but has finished. Restart the search when
		* no results have been found or more than half of the searches lifetime
		* has expired.
		*/
		if( results_entries_count( results ) == 0 ||
			(time_now_sec() - results->start_time) > (MAX_SEARCH_LIFETIME / 2)
		) {
			/* Mark search as in progress */
			results_done( results, 0 );

			/* Start another search for this id */
			dht_search( results->id, 0, gconf->af, dht_callback_func, NULL );
		}
		rc = 2;
	} else if( is_new ) {
		/* Start a new DHT search */
		dht_search( results->id, 0, gconf->af, dht_callback_func, NULL );
		rc = 1;
	} else {
		/* Search is still running */
		rc = 0;
	}

	/* Collect addresses to be returned */
	*addr_num = results_collect( results, addr_array, *addr_num );

	dht_unlock();

	return rc;
}
Example #13
0
/*
* Find nodes that are near the given id and announce to them
* that this node can satisfy the given id on the given port
*/
int kad_announce( const UCHAR *id, int port ) {

	if( port < 1 || port > 65535 ) {
		return -1;
	}

	dht_lock();
	dht_search( id, port, gconf->af, dht_callback_func, NULL );
	dht_unlock();

	return 0;
}
Example #14
0
void kad_debug_blacklist( int fd ) {
	char addrbuf[FULL_ADDSTRLEN+1];
	int i;

	dht_lock();

	for( i = 0; i < (next_blacklisted % DHT_MAX_BLACKLISTED); i++ ) {
		dprintf( fd, " %s\n", str_addr( &blacklist[i], addrbuf ) );
	}

	dprintf( fd, " Found %d blacklisted addresses.\n", i );

	dht_unlock();
}
Example #15
0
/* Export known nodes; the maximum is 200 nodes */
int kad_export_nodes( IP addr_array[], size_t *num ) {
	IP4 *addr4;
	IP6 *addr6;
	int num4;
	int num6;
	int i;

	if( gconf->af == AF_INET6 ) {
		num6 = MIN(*num, 200);
		addr6 = calloc( num6, sizeof(IP6) );
		num4 = 0;
		addr4 = NULL;
	} else {
		num6 = 0;
		addr6 = NULL;
		num4 = MIN(*num, 200);
		addr4 = calloc( num4, sizeof(IP4) );
	}

	dht_lock();
	dht_get_nodes( addr4, &num4, addr6, &num6 );
	dht_unlock();

	if( gconf->af == AF_INET6 ) {
		for( i = 0; i < num6; ++i ) {
			memcpy( &addr_array[i], &addr6[i], sizeof(IP6) );
		}
		free( addr6 );
	} else {
		for( i = 0; i < num4; ++i ) {
			memcpy( &addr_array[i], &addr4[i], sizeof(IP4) );
		}
		free( addr4 );
	}

	/* Store number of nodes we have actually found */
	*num = i;

	return 0;
}