/* Add nodes to the toping list. * All nodes in this list are pinged every TIME_TOPING seconds * and are then removed from the list. * If the list is full the nodes farthest from our client_id are replaced. * The purpose of this list is to enable quick integration of new nodes into the * network while preventing amplification attacks. * * return 0 if node was added. * return -1 if node was not added. */ int add_toping(PING *ping, size_t *client_id, IP_Port ip_port) { if (!ip_isset(&ip_port.ip)) return -1; size_t i; for (i = 0; i < MAX_TOPING; ++i) { if (!ip_isset(&ping->toping[i].ip_port.ip)) { memcpy(ping->toping[i].client_id, client_id, CLIENT_ID_SIZE); ipport_copy(&ping->toping[i].ip_port, &ip_port); return 0; } } for (i = 0; i < MAX_TOPING; ++i) { if (id_closest(ping->dht->self_public_key, ping->toping[i].client_id, client_id) == 2) { memcpy(ping->toping[i].client_id, client_id, CLIENT_ID_SIZE); ipport_copy(&ping->toping[i].ip_port, &ip_port); return 0; } } return -1; }
/* Add nodes to the to_ping list. * All nodes in this list are pinged every TIME_TO_PING seconds * and are then removed from the list. * If the list is full the nodes farthest from our client_id are replaced. * The purpose of this list is to enable quick integration of new nodes into the * network while preventing amplification attacks. * * return 0 if node was added. * return -1 if node was not added. */ int add_to_ping(PING *ping, uint8_t *client_id, IP_Port ip_port) { if (!ip_isset(&ip_port.ip)) return -1; if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) return -1; uint32_t i; for (i = 0; i < MAX_TO_PING; ++i) { if (!ip_isset(&ping->to_ping[i].ip_port.ip)) { memcpy(ping->to_ping[i].client_id, client_id, CLIENT_ID_SIZE); ipport_copy(&ping->to_ping[i].ip_port, &ip_port); return 0; } if (memcmp(ping->to_ping[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { return -1; } } uint32_t r = rand(); for (i = 0; i < MAX_TO_PING; ++i) { if (id_closest(ping->dht->self_public_key, ping->to_ping[(i + r) % MAX_TO_PING].client_id, client_id) == 2) { memcpy(ping->to_ping[(i + r) % MAX_TO_PING].client_id, client_id, CLIENT_ID_SIZE); ipport_copy(&ping->to_ping[(i + r) % MAX_TO_PING].ip_port, &ip_port); return 0; } } return -1; }
/* Add nodes to the to_ping list. * All nodes in this list are pinged every TIME_TO_PING seconds * and are then removed from the list. * If the list is full the nodes farthest from our public_key are replaced. * The purpose of this list is to enable quick integration of new nodes into the * network while preventing amplification attacks. * * return 0 if node was added. * return -1 if node was not added. */ int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port) { if (!ip_isset(&ip_port.ip)) return -1; if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, public_key, ip_port)) return -1; uint32_t i; for (i = 0; i < MAX_TO_PING; ++i) { if (!ip_isset(&ping->to_ping[i].ip_port.ip)) { memcpy(ping->to_ping[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); ipport_copy(&ping->to_ping[i].ip_port, &ip_port); return 0; } if (memcmp(ping->to_ping[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) { return -1; } } uint32_t r = rand(); for (i = 0; i < MAX_TO_PING; ++i) { if (id_closest(ping->dht->self_public_key, ping->to_ping[(i + r) % MAX_TO_PING].public_key, public_key) == 2) { memcpy(ping->to_ping[(i + r) % MAX_TO_PING].public_key, public_key, crypto_box_PUBLICKEYBYTES); ipport_copy(&ping->to_ping[(i + r) % MAX_TO_PING].ip_port, &ip_port); return 0; } } return -1; }
/* Add nodes to the to_ping list. * All nodes in this list are pinged every TIME_TO_PING seconds * and are then removed from the list. * If the list is full the nodes farthest from our public_key are replaced. * The purpose of this list is to enable quick integration of new nodes into the * network while preventing amplification attacks. * * return 0 if node was added. * return -1 if node was not added. */ int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port) { if (!ip_isset(&ip_port.ip)) { return -1; } if (!node_addable_to_close_list(ping->dht, public_key, ip_port)) { return -1; } if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, public_key, ip_port)) { return -1; } IP_Port temp; if (DHT_getfriendip(ping->dht, public_key, &temp) == 0) { send_ping_request(ping, ip_port, public_key); return -1; } unsigned int i; for (i = 0; i < MAX_TO_PING; ++i) { if (!ip_isset(&ping->to_ping[i].ip_port.ip)) { memcpy(ping->to_ping[i].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); ipport_copy(&ping->to_ping[i].ip_port, &ip_port); return 0; } if (public_key_cmp(ping->to_ping[i].public_key, public_key) == 0) { return -1; } } if (add_to_list(ping->to_ping, MAX_TO_PING, public_key, ip_port, ping->dht->self_public_key)) { return 0; } return -1; }
void test_addto_lists_update(DHT *dht, Client_data *list, uint32_t length, IP_Port *ip_port) { int used, test, test1, test2, found; IP_Port test_ipp; uint8_t test_id[CLIENT_ID_SIZE]; uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0; // check id update for existing ip_port test = rand() % length; ipport_copy(&test_ipp, ipv6 ? &list[test].assoc6.ip_port : &list[test].assoc4.ip_port); randombytes(test_id, sizeof(test_id)); used = addto_lists(dht, test_ipp, test_id); ck_assert_msg(used >= 1, "Wrong number of added clients"); // it is possible to have ip_port duplicates in the list, so ip_port @ found not always equal to ip_port @ test found = client_in_list(list, length, test_id); ck_assert_msg(found >= 0, "Client id is not in the list"); ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[found].assoc6.ip_port : &list[found].assoc4.ip_port), "Client IP_Port is incorrect"); // check ip_port update for existing id test = rand() % length; test_ipp.port = rand() % TOX_PORT_DEFAULT; id_copy(test_id, list[test].client_id); used = addto_lists(dht, test_ipp, test_id); ck_assert_msg(used >= 1, "Wrong number of added clients"); // it is not possible to have id duplicates in the list, so id @ found must be equal id @ test ck_assert_msg(client_in_list(list, length, test_id) == test, "Client id is not in the list"); ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[test].assoc6.ip_port : &list[test].assoc4.ip_port), "Client IP_Port is incorrect"); // check ip_port update for existing id and ip_port (... port ... id ...) test1 = rand() % (length / 2); test2 = rand() % (length / 2) + length / 2; ipport_copy(&test_ipp, ipv6 ? &list[test1].assoc6.ip_port : &list[test1].assoc4.ip_port); id_copy(test_id, list[test2].client_id); if (ipv6) list[test2].assoc6.ip_port.port = -1; else list[test2].assoc4.ip_port.port = -1; used = addto_lists(dht, test_ipp, test_id); ck_assert_msg(used >= 1, "Wrong number of added clients"); ck_assert_msg(client_in_list(list, length, test_id) == test2, "Client id is not in the list"); ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[test2].assoc6.ip_port : &list[test2].assoc4.ip_port), "Client IP_Port is incorrect"); // check ip_port update for existing id and ip_port (... id ... port ...) test1 = rand() % (length / 2); test2 = rand() % (length / 2) + length / 2; ipport_copy(&test_ipp, ipv6 ? &list[test2].assoc6.ip_port : &list[test2].assoc4.ip_port); id_copy(test_id, list[test1].client_id); if (ipv6) list[test1].assoc6.ip_port.port = -1; else list[test1].assoc4.ip_port.port = -1; used = addto_lists(dht, test_ipp, test_id); ck_assert_msg(used >= 1, "Wrong number of added clients"); ck_assert_msg(client_in_list(list, length, test_id) == test1, "Client id is not in the list"); ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[test1].assoc6.ip_port : &list[test1].assoc4.ip_port), "Client IP_Port is incorrect"); }