mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Major protocol changes, this commit breaks all network compatibility.
Removed a bunch of useless space from various structs. pack_nodes() and unpack_nodes() are now used to transmit lists of nodes for the DHT and onion parts. They provide a way to transmit both ipv6 and ipv4 nodes in the same packet in a portable way that takes as little space as possible without compression. Using pack_nodes, merged the send nodes and send nodes ipv6 packets into one packet greatly reducing the risk of amplification attacks.
This commit is contained in:
parent
229b2b2dcd
commit
f9bf7b074a
|
@ -136,9 +136,8 @@ START_TEST(test_struct_sizes)
|
|||
{
|
||||
ck_assert_msg(sizeof(IP4) == 4, "sizeof(IP4): expected result 4, got %u.", sizeof(IP4));
|
||||
ck_assert_msg(sizeof(IP6) == 16, "sizeof(IP6): expected result 16, got %u.", sizeof(IP6));
|
||||
ck_assert_msg(sizeof(IP) == 20, "sizeof(IP): expected result 20, got %u.", sizeof(IP));
|
||||
ck_assert_msg(sizeof(IP_Port) == 24, "sizeof(IP_Port): expected result 24, got %u.", sizeof(IP_Port));
|
||||
ck_assert_msg(sizeof(IP4_Port) == 8, "sizeof(IP4_Port): expected result 8, got %u.", sizeof(IP4_Port));
|
||||
ck_assert_msg(sizeof(IP) == 17, "sizeof(IP): expected result 17, got %u.", sizeof(IP));
|
||||
ck_assert_msg(sizeof(IP_Port) == 19, "sizeof(IP_Port): expected result 19, got %u.", sizeof(IP_Port));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
|
|
@ -79,12 +79,9 @@ Protocol
|
|||
|
||||
Node format:
|
||||
```
|
||||
[char array (node_id), length=32 bytes][ip (in network byte order), length=4 bytes][port (in network byte order), length=2 bytes][Padding , length=2 bytes]
|
||||
[uint8_t family (2 == IPv4, 10 == IPv6, 130 == TCP IPv4, 138 == TCP IPv6)][ip (in network byte order), length=4 bytes if ipv4, 16 bytes if ipv6][port (in network byte order), length=2 bytes][char array (node_id), length=32 bytes]
|
||||
```
|
||||
see also: DHT.h (Node4_format struct)
|
||||
|
||||
IPv6 Node format:
|
||||
see: DHT.h (Node_format struct)
|
||||
see also: DHT.h (pack_nodes() and unpack_nodes())
|
||||
|
||||
Valid queries and Responses:
|
||||
|
||||
|
@ -102,12 +99,7 @@ Packet contents:
|
|||
```
|
||||
Valid replies: a send_nodes packet
|
||||
|
||||
Send_nodes (response (for ipv4 addresses)):
|
||||
Send_nodes (response (for all addresses)):
|
||||
```
|
||||
[byte with value: 03][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in node format, length=40 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]]
|
||||
```
|
||||
|
||||
Send_nodes_IPv6 (response (for ipv6 addresses)):
|
||||
```
|
||||
[byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in ipv6_node format, length=56 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]]
|
||||
[byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in node format, length=?? * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]]
|
||||
```
|
||||
|
|
373
toxcore/DHT.c
373
toxcore/DHT.c
|
@ -179,6 +179,105 @@ void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id)
|
|||
return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id);
|
||||
}
|
||||
|
||||
void to_net_family(IP *ip)
|
||||
{
|
||||
if (ip->family == AF_INET)
|
||||
ip->family = TOX_AF_INET;
|
||||
else if (ip->family == AF_INET6)
|
||||
ip->family = TOX_AF_INET6;
|
||||
}
|
||||
|
||||
void to_host_family(IP *ip)
|
||||
{
|
||||
if (ip->family == TOX_AF_INET)
|
||||
ip->family = AF_INET;
|
||||
else if (ip->family == TOX_AF_INET6)
|
||||
ip->family = AF_INET6;
|
||||
}
|
||||
|
||||
/* Pack number of nodes into data of maxlength length.
|
||||
*
|
||||
* return length of packed nodes on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number)
|
||||
{
|
||||
uint32_t i, packed_length = 0;
|
||||
|
||||
for (i = 0; i < number; ++i) {
|
||||
if (nodes[i].ip_port.ip.family == AF_INET) {
|
||||
uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE;
|
||||
|
||||
if (packed_length + size > length)
|
||||
return -1;
|
||||
|
||||
data[packed_length] = TOX_AF_INET;
|
||||
memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, sizeof(IP4));
|
||||
memcpy(data + packed_length + 1 + sizeof(IP4), &nodes[i].ip_port.port, sizeof(uint16_t));
|
||||
memcpy(data + packed_length + 1 + sizeof(IP4) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE);
|
||||
packed_length += size;
|
||||
} else if (nodes[i].ip_port.ip.family == AF_INET6) {
|
||||
uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE;
|
||||
|
||||
if (packed_length + size > length)
|
||||
return -1;
|
||||
|
||||
data[packed_length] = TOX_AF_INET6;
|
||||
memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, sizeof(IP6));
|
||||
memcpy(data + packed_length + 1 + sizeof(IP6), &nodes[i].ip_port.port, sizeof(uint16_t));
|
||||
memcpy(data + packed_length + 1 + sizeof(IP6) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE);
|
||||
packed_length += size;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return packed_length;
|
||||
}
|
||||
|
||||
/* Unpack data of length into nodes of size (in number of nodes).
|
||||
*
|
||||
* return number of unpacked nodes on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int unpack_nodes(Node_format *nodes, uint16_t size, uint8_t *data, uint16_t length)
|
||||
{
|
||||
uint32_t num = 0, len_processed = 0;
|
||||
|
||||
while (num < size && len_processed < length) {
|
||||
if (data[len_processed] == TOX_AF_INET) {
|
||||
uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE;
|
||||
|
||||
if (len_processed + size > length)
|
||||
return -1;
|
||||
|
||||
nodes[num].ip_port.ip.family = AF_INET;
|
||||
memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, sizeof(IP4));
|
||||
memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP4), sizeof(uint16_t));
|
||||
memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP4) + sizeof(uint16_t), CLIENT_ID_SIZE);
|
||||
len_processed += size;
|
||||
++num;
|
||||
} else if (data[len_processed] == TOX_AF_INET6) {
|
||||
uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE;
|
||||
|
||||
if (len_processed + size > length)
|
||||
return -1;
|
||||
|
||||
nodes[num].ip_port.ip.family = AF_INET6;
|
||||
memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, sizeof(IP6));
|
||||
memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP6), sizeof(uint16_t));
|
||||
memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP6) + sizeof(uint16_t), CLIENT_ID_SIZE);
|
||||
len_processed += size;
|
||||
++num;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Check if client with client_id is already in list of length length.
|
||||
* If it is then set its corresponding timestamp to current time.
|
||||
|
@ -322,15 +421,15 @@ static uint8_t hardening_correct(Hardening *h)
|
|||
/*
|
||||
* helper for get_close_nodes(). argument list is a monster :D
|
||||
*/
|
||||
static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list,
|
||||
static void get_close_nodes_inner(uint8_t *client_id, Node_format *nodes_list,
|
||||
sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length,
|
||||
uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good)
|
||||
{
|
||||
if ((sa_family != AF_INET) && (sa_family != AF_INET6))
|
||||
if ((sa_family != AF_INET) && (sa_family != AF_INET6) && (sa_family != 0))
|
||||
return;
|
||||
|
||||
uint32_t num_nodes = *num_nodes_ptr;
|
||||
int ipv46x, j, closest;
|
||||
int j, closest;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < client_list_length; i++) {
|
||||
|
@ -342,39 +441,22 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
|
|||
|
||||
IPPTsPng *ipptp = NULL;
|
||||
|
||||
if (sa_family == AF_INET)
|
||||
if (sa_family == AF_INET) {
|
||||
ipptp = &client->assoc4;
|
||||
else
|
||||
} else if (sa_family == AF_INET6) {
|
||||
ipptp = &client->assoc6;
|
||||
} else {
|
||||
if (client->assoc4.timestamp >= client->assoc6.timestamp) {
|
||||
ipptp = &client->assoc4;
|
||||
} else {
|
||||
ipptp = &client->assoc6;
|
||||
}
|
||||
}
|
||||
|
||||
/* node not in a good condition? */
|
||||
if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT))
|
||||
continue;
|
||||
|
||||
IP *client_ip = &ipptp->ip_port.ip;
|
||||
|
||||
/*
|
||||
* Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for
|
||||
* our connections, instead we have to look if it is an embedded
|
||||
* IPv4-in-IPv6 here and convert it down in sendnodes().
|
||||
*/
|
||||
sa_family_t ip_treat_as_family = client_ip->family;
|
||||
|
||||
if ((dht->net->family == AF_INET6) &&
|
||||
(client_ip->family == AF_INET6)) {
|
||||
/* socket is AF_INET6, address claims AF_INET6:
|
||||
* check for embedded IPv4-in-IPv6 (shouldn't happen anymore,
|
||||
* all storing functions should already convert down to IPv4) */
|
||||
if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr))
|
||||
ip_treat_as_family = AF_INET;
|
||||
}
|
||||
|
||||
ipv46x = !(sa_family == ip_treat_as_family);
|
||||
|
||||
/* node address of the wrong family? */
|
||||
if (ipv46x)
|
||||
continue;
|
||||
|
||||
/* don't send LAN ips to non LAN peers */
|
||||
if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN)
|
||||
continue;
|
||||
|
@ -428,7 +510,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n
|
|||
uint8_t is_LAN, uint8_t want_good)
|
||||
{
|
||||
uint32_t num_nodes = 0, i;
|
||||
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
|
||||
get_close_nodes_inner(client_id, nodes_list, sa_family,
|
||||
dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, want_good);
|
||||
|
||||
/*TODO uncomment this when hardening is added to close friend clients
|
||||
|
@ -438,7 +520,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n
|
|||
&num_nodes, is_LAN, want_good);
|
||||
*/
|
||||
for (i = 0; i < dht->num_friends; ++i)
|
||||
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
|
||||
get_close_nodes_inner(client_id, nodes_list, sa_family,
|
||||
dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
|
||||
&num_nodes, is_LAN, 0);
|
||||
|
||||
|
@ -456,6 +538,7 @@ int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_fa
|
|||
return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good);
|
||||
|
||||
#ifdef ENABLE_ASSOC_DHT
|
||||
//TODO: assoc, sa_family 0 (don't care if ipv4 or ipv6) support.
|
||||
Client_data *result[MAX_SENT_NODES];
|
||||
|
||||
Assoc_close_entries request;
|
||||
|
@ -907,95 +990,6 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
|
|||
return sendpacket(dht->net, ip_port, data, sizeof(data));
|
||||
}
|
||||
|
||||
/* Send a send nodes response. */
|
||||
/* because of BINARY compatibility, the Node_format MUST BE Node4_format,
|
||||
* IPv6 nodes are sent in a different message
|
||||
* encrypted_data must be of size NODES_ENCRYPTED_MESSAGE_LENGTH */
|
||||
static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data,
|
||||
uint8_t *shared_encryption_key)
|
||||
{
|
||||
/* Check if packet is going to be sent to ourself. */
|
||||
if (id_equal(public_key, dht->self_public_key))
|
||||
return -1;
|
||||
|
||||
size_t Node4_format_size = sizeof(Node4_format);
|
||||
uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
|
||||
+ Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES];
|
||||
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET, LAN_ip(ip_port.ip) == 0, 1);
|
||||
|
||||
if (num_nodes == 0)
|
||||
return 0;
|
||||
|
||||
uint8_t plain[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
uint8_t encrypt[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES];
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
new_nonce(nonce);
|
||||
|
||||
Node4_format *nodes4_list = (Node4_format *)(plain);
|
||||
uint32_t i, num_nodes_ok = 0;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
|
||||
nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port;
|
||||
|
||||
IP *node_ip = &nodes_list[i].ip_port.ip;
|
||||
|
||||
if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6.in6_addr))
|
||||
/* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */
|
||||
nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.uint32[3];
|
||||
else if (node_ip->family == AF_INET)
|
||||
nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip4.uint32;
|
||||
else /* shouldn't happen */
|
||||
continue;
|
||||
|
||||
num_nodes_ok++;
|
||||
}
|
||||
|
||||
if (num_nodes_ok < num_nodes) {
|
||||
/* shouldn't happen */
|
||||
num_nodes = num_nodes_ok;
|
||||
}
|
||||
|
||||
memcpy(plain + num_nodes * Node4_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH);
|
||||
int len = encrypt_data_fast( shared_encryption_key,
|
||||
nonce,
|
||||
plain,
|
||||
num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH,
|
||||
encrypt );
|
||||
|
||||
if ((unsigned int)len != num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH +
|
||||
crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
||||
data[0] = NET_PACKET_SEND_NODES;
|
||||
memcpy(data + 1, dht->self_public_key, CLIENT_ID_SIZE);
|
||||
memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
|
||||
memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
|
||||
|
||||
return sendpacket(dht->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
|
||||
}
|
||||
|
||||
void to_net_family(IP *ip)
|
||||
{
|
||||
ip->padding[0] = 0;
|
||||
ip->padding[1] = 0;
|
||||
ip->padding[2] = 0;
|
||||
|
||||
if (ip->family == AF_INET)
|
||||
ip->family = TOX_AF_INET;
|
||||
else if (ip->family == AF_INET6)
|
||||
ip->family = TOX_AF_INET6;
|
||||
}
|
||||
|
||||
void to_host_family(IP *ip)
|
||||
{
|
||||
if (ip->family == TOX_AF_INET)
|
||||
ip->family = AF_INET;
|
||||
else if (ip->family == TOX_AF_INET6)
|
||||
ip->family = AF_INET6;
|
||||
}
|
||||
/* Send a send nodes response: message for IPv6 nodes */
|
||||
static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data,
|
||||
uint8_t *shared_encryption_key)
|
||||
|
@ -1009,7 +1003,7 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_
|
|||
+ Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES];
|
||||
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6, LAN_ip(ip_port.ip) == 0, 1);
|
||||
uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, 0, LAN_ip(ip_port.ip) == 0, 1);
|
||||
|
||||
if (num_nodes == 0)
|
||||
return 0;
|
||||
|
@ -1019,20 +1013,19 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_
|
|||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
new_nonce(nonce);
|
||||
|
||||
uint32_t i;
|
||||
int nodes_length = pack_nodes(plain, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes);
|
||||
|
||||
for (i = 0; i < num_nodes; ++i)
|
||||
to_net_family(&nodes_list[i].ip_port.ip);
|
||||
if (nodes_length <= 0)
|
||||
return -1;
|
||||
|
||||
memcpy(plain, nodes_list, num_nodes * Node_format_size);
|
||||
memcpy(plain + num_nodes * Node_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH);
|
||||
memcpy(plain + nodes_length, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH);
|
||||
int len = encrypt_data_fast( shared_encryption_key,
|
||||
nonce,
|
||||
plain,
|
||||
num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH,
|
||||
nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH,
|
||||
encrypt );
|
||||
|
||||
if ((unsigned int)len != num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES)
|
||||
if ((unsigned int)len != nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
||||
data[0] = NET_PACKET_SEND_NODES_IPV6;
|
||||
|
@ -1068,12 +1061,9 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32
|
|||
if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
return 1;
|
||||
|
||||
sendnodes(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, shared_key);
|
||||
sendnodes_ipv6(dht, source, packet + 1, plain,
|
||||
plain + CLIENT_ID_SIZE, shared_key); /* TODO: prevent possible amplification attacks */
|
||||
sendnodes_ipv6(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, shared_key);
|
||||
|
||||
add_to_ping(dht->ping, packet + 1, source);
|
||||
//send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1108,15 +1098,12 @@ static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_i
|
|||
}
|
||||
|
||||
/* Function is needed in following functions. */
|
||||
static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list,
|
||||
uint16_t num_nodes);
|
||||
static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, uint8_t *nodes_data,
|
||||
uint16_t nodes_data_length);
|
||||
|
||||
static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length,
|
||||
size_t node_format_size, uint8_t *plain, uint16_t plain_length, uint32_t *num_nodes_out, Node_format *sendback_node)
|
||||
Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out)
|
||||
{
|
||||
if (plain_length != MAX_SENT_NODES * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
return 1;
|
||||
|
||||
DHT *dht = object;
|
||||
uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES;
|
||||
|
||||
|
@ -1125,27 +1112,33 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet,
|
|||
|
||||
uint32_t data_size = length - cid_size;
|
||||
|
||||
if ((data_size % node_format_size) != 0) /* invalid length */
|
||||
if (data_size == 0)
|
||||
return 1;
|
||||
|
||||
uint32_t num_nodes = data_size / node_format_size;
|
||||
|
||||
if (num_nodes > MAX_SENT_NODES) /* too long */
|
||||
if (data_size > sizeof(Node_format) * MAX_SENT_NODES) /* invalid length */
|
||||
return 1;
|
||||
|
||||
uint8_t plain[data_size + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
DHT_get_shared_key_sent(dht, shared_key, packet + 1);
|
||||
int len = decrypt_data_fast(
|
||||
shared_key,
|
||||
packet + 1 + CLIENT_ID_SIZE,
|
||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||
num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES,
|
||||
data_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES,
|
||||
plain);
|
||||
|
||||
if ((unsigned int)len != num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
if ((unsigned int)len != sizeof(plain))
|
||||
return 1;
|
||||
|
||||
if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * node_format_size, sendback_node))
|
||||
Node_format sendback_node;
|
||||
|
||||
if (!sent_getnode_to_node(dht, packet + 1, source, plain + data_size, &sendback_node))
|
||||
return 1;
|
||||
|
||||
int num_nodes = unpack_nodes(plain_nodes, size_plain_nodes, plain, data_size);
|
||||
|
||||
if (num_nodes <= 0)
|
||||
return 1;
|
||||
|
||||
/* store the address the *request* was sent to */
|
||||
|
@ -1153,79 +1146,28 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet,
|
|||
|
||||
*num_nodes_out = num_nodes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
DHT *dht = object;
|
||||
size_t node4_format_size = sizeof(Node4_format);
|
||||
uint8_t plain[node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
uint32_t num_nodes;
|
||||
|
||||
Node_format sendback_node;
|
||||
|
||||
if (handle_sendnodes_core(object, source, packet, length, node4_format_size, plain, sizeof(plain), &num_nodes,
|
||||
&sendback_node))
|
||||
return 1;
|
||||
|
||||
if (num_nodes == 0)
|
||||
return 0;
|
||||
|
||||
Node4_format *nodes4_list = (Node4_format *)(plain);
|
||||
|
||||
uint64_t time_now = unix_time();
|
||||
IPPTs ippts;
|
||||
ippts.ip_port.ip.family = AF_INET;
|
||||
ippts.timestamp = time_now;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
|
||||
for (i = 0; i < num_nodes; i++)
|
||||
if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) {
|
||||
ippts.ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
|
||||
ippts.ip_port.port = nodes4_list[i].ip_port.port;
|
||||
|
||||
send_ping_request(dht->ping, ippts.ip_port, nodes4_list[i].client_id);
|
||||
returnedip_ports(dht, ippts.ip_port, nodes4_list[i].client_id, packet + 1);
|
||||
|
||||
memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
|
||||
ipport_copy(&nodes_list[i].ip_port, &ippts.ip_port);
|
||||
|
||||
}
|
||||
|
||||
send_hardening_getnode_res(dht, &sendback_node, packet + 1, nodes_list, num_nodes);
|
||||
send_hardening_getnode_res(dht, &sendback_node, packet + 1, plain, data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
DHT *dht = object;
|
||||
size_t node_format_size = sizeof(Node_format);
|
||||
uint8_t plain[node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
Node_format plain_nodes[MAX_SENT_NODES];
|
||||
uint32_t num_nodes;
|
||||
|
||||
Node_format sendback_node;
|
||||
|
||||
if (handle_sendnodes_core(object, source, packet, length, node_format_size, plain, sizeof(plain), &num_nodes,
|
||||
&sendback_node))
|
||||
if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes))
|
||||
return 1;
|
||||
|
||||
if (num_nodes == 0)
|
||||
return 0;
|
||||
|
||||
Node_format *nodes_list = (Node_format *)(plain);
|
||||
uint32_t i;
|
||||
send_hardening_getnode_res(dht, &sendback_node, packet + 1, nodes_list, num_nodes);
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
to_host_family(&nodes_list[i].ip_port.ip);
|
||||
|
||||
if (ipport_isset(&nodes_list[i].ip_port)) {
|
||||
send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id);
|
||||
returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
|
||||
if (ipport_isset(&plain_nodes[i].ip_port)) {
|
||||
send_ping_request(dht->ping, plain_nodes[i].ip_port, plain_nodes[i].client_id);
|
||||
returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].client_id, packet + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1977,17 +1919,17 @@ static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *
|
|||
}
|
||||
|
||||
/* Send a get node hardening response */
|
||||
static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list,
|
||||
uint16_t num_nodes)
|
||||
static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, uint8_t *nodes_data,
|
||||
uint16_t nodes_data_length)
|
||||
{
|
||||
if (!ip_isset(&sendto->ip_port.ip))
|
||||
return -1;
|
||||
|
||||
uint8_t packet[MAX_DATA_SIZE];
|
||||
uint8_t data[1 + CLIENT_ID_SIZE + num_nodes * sizeof(Node_format)];
|
||||
uint8_t data[1 + CLIENT_ID_SIZE + nodes_data_length];
|
||||
data[0] = CHECK_TYPE_GETNODE_RES;
|
||||
memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE);
|
||||
memcpy(data + 1 + CLIENT_ID_SIZE, list, num_nodes * sizeof(Node_format));
|
||||
memcpy(data + 1 + CLIENT_ID_SIZE, nodes_data, nodes_data_length);
|
||||
int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data,
|
||||
sizeof(data), CRYPTO_PACKET_HARDENING);
|
||||
|
||||
|
@ -2075,28 +2017,22 @@ static int handle_hardening(void *object, IP_Port source, uint8_t *source_pubkey
|
|||
if (length <= CLIENT_ID_SIZE + 1)
|
||||
return 1;
|
||||
|
||||
if ((length - 1 - CLIENT_ID_SIZE) % sizeof(Node_format) != 0)
|
||||
if (length > 1 + CLIENT_ID_SIZE + sizeof(Node_format) * MAX_SENT_NODES)
|
||||
return 1;
|
||||
|
||||
uint16_t num = (length - 1 - CLIENT_ID_SIZE) / sizeof(Node_format);
|
||||
uint16_t length_nodes = length - 1 - CLIENT_ID_SIZE;
|
||||
Node_format nodes[MAX_SENT_NODES];
|
||||
int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, packet + 1 + CLIENT_ID_SIZE, length_nodes);
|
||||
|
||||
/* TODO: MAX_SENT_NODES nodes should be returned at all times
|
||||
(right now we have a small network size so it could cause problems for testing and etc..) */
|
||||
if (num > MAX_SENT_NODES || num == 0)
|
||||
if (num_nodes <= 0)
|
||||
return 1;
|
||||
|
||||
Node_format nodes[num];
|
||||
memcpy(nodes, packet + 1 + CLIENT_ID_SIZE, sizeof(Node_format)*num);
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < num; ++i)
|
||||
to_host_family(&nodes[i].ip_port.ip);
|
||||
|
||||
/* NOTE: This should work for now but should be changed to something better. */
|
||||
if (have_nodes_closelist(dht, nodes, num) < (uint32_t)((num + 2) / 2))
|
||||
if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2))
|
||||
return 1;
|
||||
|
||||
|
||||
IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family);
|
||||
|
||||
if (temp == NULL)
|
||||
|
@ -2329,7 +2265,6 @@ DHT *new_DHT(Net_Crypto *c)
|
|||
}
|
||||
|
||||
networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht);
|
||||
networking_registerhandler(dht->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht);
|
||||
networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht);
|
||||
init_cryptopackets(dht);
|
||||
cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht);
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
/* Redefinitions of variables for safe transfer over wire. */
|
||||
#define TOX_AF_INET 2
|
||||
#define TOX_AF_INET6 10
|
||||
#define TOX_TCP_INET 130
|
||||
#define TOX_TCP_INET6 138
|
||||
|
||||
/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */
|
||||
#define DHT_FAKE_FRIEND_NUMBER 4
|
||||
|
@ -128,16 +130,27 @@ typedef struct {
|
|||
NAT nat;
|
||||
} DHT_Friend;
|
||||
|
||||
/* this must be kept even if IP_Port is expanded: wire compatibility */
|
||||
typedef struct {
|
||||
uint8_t client_id[CLIENT_ID_SIZE];
|
||||
IP4_Port ip_port;
|
||||
} Node4_format;
|
||||
|
||||
typedef struct {
|
||||
typedef struct __attribute__ ((__packed__))
|
||||
{
|
||||
uint8_t client_id[CLIENT_ID_SIZE];
|
||||
IP_Port ip_port;
|
||||
} Node_format;
|
||||
}
|
||||
Node_format;
|
||||
|
||||
/* Pack number of nodes into data of maxlength length.
|
||||
*
|
||||
* return length of packed nodes on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number);
|
||||
|
||||
/* Unpack data of length into nodes of size (in number of nodes).
|
||||
*
|
||||
* return number of unpacked nodes on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int unpack_nodes(Node_format *nodes, uint16_t size, uint8_t *data, uint16_t length);
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
/* struct to store some shared keys so we don't have to regenerate them for each request. */
|
||||
|
@ -251,7 +264,7 @@ int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2);
|
|||
/* Get the (maximum MAX_SENT_NODES) closest nodes to client_id we know
|
||||
* and put them in nodes_list (must be MAX_SENT_NODES big).
|
||||
*
|
||||
* sa_family = family (IPv4 or IPv6)?
|
||||
* sa_family = family (IPv4 or IPv6) (0 if we don't care)?
|
||||
* is_LAN = return some LAN ips (true or false)
|
||||
* want_good = do we want tested nodes or not? (TODO)
|
||||
*
|
||||
|
|
|
@ -161,9 +161,6 @@ typedef int sock_t;
|
|||
#define TOX_PORTRANGE_TO 33545
|
||||
#define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM
|
||||
|
||||
|
||||
/* TODO: remove padding bytes next time we need to break compatibility with old versions of core. */
|
||||
|
||||
typedef union __attribute__ ((__packed__))
|
||||
{
|
||||
uint8_t uint8[4];
|
||||
|
@ -186,8 +183,6 @@ IP6;
|
|||
typedef struct __attribute__ ((__packed__))
|
||||
{
|
||||
uint8_t family;
|
||||
/* Not used for anything right now. */
|
||||
uint8_t padding[3];
|
||||
union {
|
||||
IP4 ip4;
|
||||
IP6 ip6;
|
||||
|
@ -195,22 +190,9 @@ typedef struct __attribute__ ((__packed__))
|
|||
}
|
||||
IP;
|
||||
|
||||
typedef union __attribute__ ((__packed__))
|
||||
{
|
||||
struct {
|
||||
IP4 ip;
|
||||
uint16_t port;
|
||||
/* Not used for anything right now. */
|
||||
uint16_t padding;
|
||||
};
|
||||
uint8_t uint8[8];
|
||||
}
|
||||
IP4_Port;
|
||||
|
||||
typedef struct __attribute__ ((__packed__)) IP_Port {
|
||||
IP ip;
|
||||
uint16_t port;
|
||||
uint16_t padding;
|
||||
} IP_Port;
|
||||
|
||||
#define TOX_ENABLE_IPV6_DEFAULT 1
|
||||
|
|
|
@ -247,14 +247,8 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
|
|||
|
||||
/*Respond with a announce response packet*/
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, source.ip.family,
|
||||
LAN_ip(source.ip) == 0, 1);
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < num_nodes; ++i)
|
||||
to_net_family(&nodes_list[i].ip_port.ip);
|
||||
|
||||
uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, 0, LAN_ip(source.ip) == 0,
|
||||
1);
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
random_nonce(nonce);
|
||||
|
||||
|
@ -274,13 +268,16 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
|
|||
}
|
||||
}
|
||||
|
||||
memcpy(pl + 1 + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format));
|
||||
int nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes);
|
||||
|
||||
if (nodes_length <= 0)
|
||||
return 1;
|
||||
|
||||
uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE];
|
||||
len = encrypt_data_fast(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format),
|
||||
len = encrypt_data_fast(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length,
|
||||
data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES);
|
||||
|
||||
if ((uint32_t)len != 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES)
|
||||
if (len != 1 + ONION_PING_ID_SIZE + nodes_length + crypto_box_MACBYTES)
|
||||
return 1;
|
||||
|
||||
data[0] = NET_PACKET_ANNOUNCE_RESPONSE;
|
||||
|
|
|
@ -345,8 +345,6 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n
|
|||
if (*ping_nodes_sent_second > MAX_PING_NODES_SECOND_PEER)
|
||||
return 0;
|
||||
|
||||
to_host_family(&nodes[i].ip_port.ip);
|
||||
|
||||
if (!lan_ips_accepted)
|
||||
if (LAN_ip(nodes[i].ip_port.ip) == 0)
|
||||
continue;
|
||||
|
@ -377,10 +375,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
|
|||
if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE)
|
||||
return 1;
|
||||
|
||||
if ((length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) % sizeof(Node_format) != 0)
|
||||
return 1;
|
||||
|
||||
uint16_t num_nodes = (length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) / sizeof(Node_format);
|
||||
uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
|
||||
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES];
|
||||
IP_Port ip_port;
|
||||
|
@ -389,7 +384,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
|
|||
if (num > onion_c->num_friends)
|
||||
return 1;
|
||||
|
||||
uint8_t plain[1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)];
|
||||
uint8_t plain[1 + ONION_PING_ID_SIZE + len_nodes];
|
||||
int len = -1;
|
||||
|
||||
if (num == 0) {
|
||||
|
@ -409,15 +404,19 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
|
|||
if ((uint32_t)len != sizeof(plain))
|
||||
return 1;
|
||||
|
||||
|
||||
if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1)
|
||||
return 1;
|
||||
|
||||
Node_format nodes[MAX_SENT_NODES];
|
||||
memcpy(nodes, plain + 1 + ONION_PING_ID_SIZE, num_nodes * sizeof(Node_format));
|
||||
if (len_nodes != 0) {
|
||||
Node_format nodes[MAX_SENT_NODES];
|
||||
int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, plain + 1 + ONION_PING_ID_SIZE, len_nodes);
|
||||
|
||||
if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1)
|
||||
return 1;
|
||||
if (num_nodes <= 0)
|
||||
return 1;
|
||||
|
||||
if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -469,9 +468,6 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t
|
|||
if (length > FAKEID_DATA_MAX_LENGTH)
|
||||
return 1;
|
||||
|
||||
if ((length - FAKEID_DATA_MIN_LENGTH) % sizeof(Node_format) != 0)
|
||||
return 1;
|
||||
|
||||
int friend_num = onion_friend_num(onion_c, source_pubkey);
|
||||
|
||||
if (friend_num == -1)
|
||||
|
@ -500,14 +496,20 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t
|
|||
memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES);
|
||||
}
|
||||
|
||||
uint16_t num_nodes = (length - FAKEID_DATA_MIN_LENGTH) / sizeof(Node_format);
|
||||
Node_format nodes[num_nodes];
|
||||
memcpy(nodes, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(nodes));
|
||||
uint32_t i;
|
||||
uint16_t len_nodes = length - FAKEID_DATA_MIN_LENGTH;
|
||||
|
||||
for (i = 0; i < num_nodes; ++i) {
|
||||
to_host_family(&nodes[i].ip_port.ip);
|
||||
DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id);
|
||||
if (len_nodes != 0) {
|
||||
Node_format nodes[MAX_SENT_NODES];
|
||||
int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, len_nodes);
|
||||
|
||||
if (num_nodes <= 0)
|
||||
return 1;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; ++i) {
|
||||
DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -658,19 +660,19 @@ static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num, uint
|
|||
memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
Node_format nodes[MAX_SENT_NODES];
|
||||
uint16_t num_nodes = closelist_nodes(onion_c->dht, nodes, MAX_SENT_NODES);
|
||||
uint32_t i;
|
||||
int nodes_len = pack_nodes(data + FAKEID_DATA_MIN_LENGTH, FAKEID_DATA_MAX_LENGTH - FAKEID_DATA_MIN_LENGTH, nodes,
|
||||
num_nodes);
|
||||
|
||||
for (i = 0; i < num_nodes; ++i)
|
||||
to_net_family(&nodes[i].ip_port.ip);
|
||||
if (nodes_len <= 0)
|
||||
return -1;
|
||||
|
||||
memcpy(data + FAKEID_DATA_MIN_LENGTH, nodes, sizeof(Node_format) * num_nodes);
|
||||
int num1 = -1, num2 = -1;
|
||||
|
||||
if (onion_dht_both != 1)
|
||||
num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes);
|
||||
num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len);
|
||||
|
||||
if (onion_dht_both != 0)
|
||||
num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes);
|
||||
num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len);
|
||||
|
||||
if (num1 == -1)
|
||||
return num2;
|
||||
|
|
Loading…
Reference in New Issue
Block a user