/* * 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; }
/* * 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; }
static int handle_ping_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) { DHT *dht = (DHT *)object; int rc; if (length != DHT_PING_SIZE) { return 1; } PING *ping = dht->ping; if (id_equal(packet + 1, ping->dht->self_public_key)) { return 1; } uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; // generate key to encrypt ping_id with recipient privkey DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1); uint8_t ping_plain[PING_PLAIN_SIZE]; // Decrypt ping_id rc = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, PING_PLAIN_SIZE + CRYPTO_MAC_SIZE, ping_plain); if (rc != sizeof(ping_plain)) { return 1; } if (ping_plain[0] != NET_PACKET_PING_RESPONSE) { return 1; } uint64_t ping_id; memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); uint8_t data[PING_DATA_SIZE]; if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data)) { return 1; } if (!id_equal(packet + 1, data)) { return 1; } IP_Port ipp; memcpy(&ipp, data + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port)); if (!ipport_equal(&ipp, &source)) { return 1; } addto_lists(dht, source, packet + 1); return 0; }
static int handle_ping_response(void *_dht, IP_Port source, const uint8_t *packet, uint16_t length) { DHT *dht = _dht; int rc; if (length != DHT_PING_SIZE) return 1; PING *ping = dht->ping; if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; uint8_t shared_key[crypto_box_BEFORENMBYTES]; // generate key to encrypt ping_id with recipient privkey DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1); uint8_t ping_plain[PING_PLAIN_SIZE]; // Decrypt ping_id rc = decrypt_data_symmetric(shared_key, packet + 1 + crypto_box_PUBLICKEYBYTES, packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, PING_PLAIN_SIZE + crypto_box_MACBYTES, ping_plain); if (rc != sizeof(ping_plain)) return 1; if (ping_plain[0] != NET_PACKET_PING_RESPONSE) return 1; uint64_t ping_id; memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); uint8_t data[PING_DATA_SIZE]; if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data)) return 1; if (!id_equal(packet + 1, data)) return 1; IP_Port ipp; memcpy(&ipp, data + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port)); if (!ipport_equal(&ipp, &source)) return 1; addto_lists(dht, source, packet + 1); return 0; }
static int send_ping_response(PING *ping, IP_Port ipp, const uint8_t *public_key, uint64_t ping_id, uint8_t *shared_encryption_key) { uint8_t pk[DHT_PING_SIZE]; int rc; if (id_equal(public_key, ping->dht->self_public_key)) return 1; uint8_t ping_plain[PING_PLAIN_SIZE]; ping_plain[0] = NET_PACKET_PING_RESPONSE; memcpy(ping_plain + 1, &ping_id, sizeof(ping_id)); pk[0] = NET_PACKET_PING_RESPONSE; id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey new_nonce(pk + 1 + crypto_box_PUBLICKEYBYTES); // Generate new nonce // Encrypt ping_id using recipient privkey rc = encrypt_data_symmetric(shared_encryption_key, pk + 1 + crypto_box_PUBLICKEYBYTES, ping_plain, sizeof(ping_plain), pk + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES ); if (rc != PING_PLAIN_SIZE + crypto_box_MACBYTES) return 1; return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); }
static int handle_ping_response(void *_dht, IP_Port source, size_t *packet, size_t length) { DHT *dht = _dht; int rc; size_t ping_id; if (length != DHT_PING_SIZE) return 1; PING *ping = dht->ping; if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data(packet + 1, ping->dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + crypto_box_MACBYTES, (size_t *) &ping_id); if (rc != sizeof(ping_id)) return 1; /* Make sure ping_id is correct. */ int ping_index = is_pinging(ping, source, ping_id); if (!ping_index) return 1; addto_lists(dht, source, packet + 1); return 0; }
static int handle_ping_request(void *_dht, IP_Port source, size_t *packet, size_t length) { DHT *dht = _dht; int rc; size_t ping_id; if (length != DHT_PING_SIZE) return 1; PING *ping = dht->ping; if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data(packet + 1, ping->dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + crypto_box_MACBYTES, (size_t *) &ping_id); if (rc != sizeof(ping_id)) return 1; // Send response send_ping_response(ping, source, packet + 1, ping_id); add_toping(ping, packet + 1, source); return 0; }
/* * Delete a peer to the group chat. * * return 0 if success * return -1 if error. */ static int delpeer(Group_Chat *chat, uint8_t *client_id) { uint32_t i; Group_Peer *temp; for (i = 0; i < chat->numpeers; ++i) { /* Equal */ if (id_equal(chat->group[i].client_id, client_id)) { --chat->numpeers; if (chat->numpeers == 0) { free(chat->group); chat->group = NULL; return 0; } if (chat->numpeers != i) memcpy(&chat->group[i], &chat->group[chat->numpeers], sizeof(Group_Peer)); temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers)); if (temp == NULL) return -1; chat->group = temp; return 0; } } return -1; }
/* Attempt to add a peer to the close list. * Update last_recv if it is in list. * Attempt to add it to list if it is not. * * Return 0 if success. * Return -1 if peer was not put in list/updated. */ static int add_closepeer(Group_Chat *chat, uint8_t *client_id, IP_Port ip_port) { uint32_t i; for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Check if node is already in list, if it is update its last_recv */ if (id_equal(chat->close[i].client_id, client_id)) { chat->close[i].last_recv = unix_time(); return 0; } } for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Try replacing bad nodes first */ if (is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) { id_copy(chat->close[i].client_id, client_id); chat->close[i].ip_port = ip_port; chat->close[i].last_recv = unix_time(); return 0; } } for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Replace nodes if given one is closer. */ if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2) { id_copy(chat->close[i].client_id, client_id); chat->close[i].ip_port = ip_port; chat->close[i].last_recv = unix_time(); return 0; } } return -1; }
int send_ping_request(PING *ping, IP_Port ipp, size_t *client_id) { size_t pk[DHT_PING_SIZE]; int rc; size_t ping_id; if (is_pinging(ping, ipp, 0) || id_equal(client_id, ping->dht->self_public_key)) return 1; // Generate random ping_id. ping_id = add_ping(ping, ipp); pk[0] = NET_PACKET_PING_REQUEST; id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey rc = encrypt_data(client_id, ping->dht->self_secret_key, pk + 1 + CLIENT_ID_SIZE, (size_t *) &ping_id, sizeof(ping_id), pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); if (rc != sizeof(ping_id) + crypto_box_MACBYTES) return 1; return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); }
int client_in_list(Client_data *list, uint32_t length, const uint8_t *public_key) { int i; for (i = 0; i < (int)length; ++i) if (id_equal(public_key, list[i].public_key)) return i; return -1; }
static int peer_in_chat(Group_Chat *chat, uint8_t *client_id) { uint32_t i; for (i = 0; i < chat->numpeers; ++i) if (id_equal(chat->group[i].client_id, client_id)) return i; return -1; }
/* Check if a friend request was already received. * * return 0 if it did not. * return 1 if it did. */ static int request_received(Friend_Requests *fr, uint8_t *client_id) { uint32_t i; for (i = 0; i < MAX_RECEIVED_STORED; ++i) if (id_equal(fr->received_requests[i], client_id)) return 1; return 0; }
static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk) { uint32_t i; for (i = 0; i < chat->numpeers; ++i) if (id_equal(chat->group[i].real_pk, real_pk)) return i; return -1; }
int client_in_list(Client_data *list, uint32_t length, const uint8_t *client_id) { int i; for (i = 0; i < (int)length; ++i) if (id_equal(client_id, list[i].client_id)) return i; return -1; }
/* Check if a friend request was already received. * * return 0 if it did not. * return 1 if it did. */ static int request_received(Friend_Requests *fr, const uint8_t *real_pk) { uint32_t i; for (i = 0; i < MAX_RECEIVED_STORED; ++i) { if (id_equal(fr->received_requests[i], real_pk)) { return 1; } } return 0; }
/* Remove real pk from received_requests list. * * return 0 if it removed it successfully. * return -1 if it didn't find it. */ int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk) { uint32_t i; for (i = 0; i < MAX_RECEIVED_STORED; ++i) { if (id_equal(fr->received_requests[i], real_pk)) { crypto_memzero(fr->received_requests[i], CRYPTO_PUBLIC_KEY_SIZE); return 0; } } return -1; }
static int peer_okping(Group_Chat *chat, uint8_t *client_id) { uint32_t i, j = 0; if (id_equal(chat->self_public_key, client_id)) return -1; for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { if (is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) { ++j; continue; } /* Equal */ if (id_equal(chat->close[i].client_id, client_id)) return -1; if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2) ++j; } return j; }
int send_ping_request(PING *ping, IP_Port ipp, const uint8_t *public_key) { uint8_t pk[DHT_PING_SIZE]; int rc; uint64_t ping_id; if (id_equal(public_key, ping->dht->self_public_key)) { return 1; } uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; // generate key to encrypt ping_id with recipient privkey DHT_get_shared_key_sent(ping->dht, shared_key, public_key); // Generate random ping_id. uint8_t data[PING_DATA_SIZE]; id_copy(data, public_key); memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, &ipp, sizeof(IP_Port)); ping_id = ping_array_add(&ping->ping_array, data, sizeof(data)); if (ping_id == 0) { return 1; } uint8_t ping_plain[PING_PLAIN_SIZE]; ping_plain[0] = NET_PACKET_PING_REQUEST; memcpy(ping_plain + 1, &ping_id, sizeof(ping_id)); pk[0] = NET_PACKET_PING_REQUEST; id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey random_nonce(pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce rc = encrypt_data_symmetric(shared_key, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE, ping_plain, sizeof(ping_plain), pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); if (rc != PING_PLAIN_SIZE + CRYPTO_MAC_SIZE) { return 1; } return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); }
static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *public_key, uint8_t *data, uint32_t length, uint8_t request_id) { if (id_equal(chat->self_public_key, public_key)) return -1; uint8_t packet[MAX_DATA_SIZE]; int len = create_request(chat->self_public_key, chat->self_secret_key, packet, public_key, data, length, request_id); packet[0] = NET_PACKET_GROUP_CHATS; if (len == -1) return -1; if (sendpacket(chat->net, ip_port, packet, len) == len) return 0; return -1; }
static int handle_ping_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) { DHT *dht = (DHT *)object; int rc; if (length != DHT_PING_SIZE) { return 1; } PING *ping = dht->ping; if (id_equal(packet + 1, ping->dht->self_public_key)) { return 1; } uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; uint8_t ping_plain[PING_PLAIN_SIZE]; // Decrypt ping_id DHT_get_shared_key_recv(dht, shared_key, packet + 1); rc = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, PING_PLAIN_SIZE + CRYPTO_MAC_SIZE, ping_plain); if (rc != sizeof(ping_plain)) { return 1; } if (ping_plain[0] != NET_PACKET_PING_REQUEST) { return 1; } uint64_t ping_id; memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); // Send response send_ping_response(ping, source, packet + 1, ping_id, shared_key); add_to_ping(ping, packet + 1, source); return 0; }
int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) { uint8_t pk[DHT_PING_SIZE]; int rc; uint64_t ping_id; if (id_equal(client_id, ping->dht->self_public_key)) return 1; uint8_t shared_key[crypto_box_BEFORENMBYTES]; // generate key to encrypt ping_id with recipient privkey DHT_get_shared_key_sent(ping->dht, shared_key, client_id); // Generate random ping_id. uint8_t data[PING_DATA_SIZE]; id_copy(data, client_id); memcpy(data + CLIENT_ID_SIZE, &ipp, sizeof(IP_Port)); ping_id = ping_array_add(&ping->ping_array, data, sizeof(data)); if (ping_id == 0) return 1; uint8_t ping_plain[PING_PLAIN_SIZE]; ping_plain[0] = NET_PACKET_PING_REQUEST; memcpy(ping_plain + 1, &ping_id, sizeof(ping_id)); pk[0] = NET_PACKET_PING_REQUEST; id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce rc = encrypt_data_symmetric(shared_key, pk + 1 + CLIENT_ID_SIZE, ping_plain, sizeof(ping_plain), pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); if (rc != PING_PLAIN_SIZE + crypto_box_MACBYTES) return 1; return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); }
/* * Delete a peer from the group chat. * * return 0 if success * return -1 if error. */ static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index) { Group_c *g = get_group_c(g_c, groupnumber); if (!g) return -1; uint32_t i; for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { /* If peer is in closest_peers list, remove it. */ if (g->closest_peers[i].entry && id_equal(g->closest_peers[i].real_pk, g->group[peer_index].real_pk)) { g->closest_peers[i].entry = 0; g->changed = GROUPCHAT_CLOSEST_REMOVED; break; } } Group_Peer *temp; --g->numpeers; if (g->numpeers == 0) { free(g->group); g->group = NULL; return 0; } if (g->numpeers != (uint32_t)peer_index) memcpy(&g->group[peer_index], &g->group[g->numpeers], sizeof(Group_Peer)); temp = realloc(g->group, sizeof(Group_Peer) * (g->numpeers)); if (temp == NULL) return -1; g->group = temp; if (g_c->peer_namelistchange) g_c->peer_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_DEL, g_c->group_namelistchange_userdata); return 0; }
/* Check if public_key with ip_port is in the list. * * return 1 if it is. * return 0 if it isn't. */ static int in_list(const Client_data *list, uint16_t length, const uint8_t *public_key, IP_Port ip_port) { uint32_t i; for (i = 0; i < length; ++i) { if (id_equal(list[i].public_key, public_key)) { const IPPTsPng *ipptp; if (ip_port.ip.family == AF_INET) { ipptp = &list[i].assoc4; } else { ipptp = &list[i].assoc6; } if (!is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) return 1; } } return 0; }
/* * Delete a peer from the group chat. * * return 0 if success * return -1 if error. */ static int delpeer(Group_Chat *chat, int peernum) { if ((uint32_t)peernum >= chat->numpeers) return -1; uint32_t i; for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* If peer is in close list, time it out forcefully. */ if (id_equal(chat->close[i].client_id, chat->group[peernum].client_id)) { chat->close[i].last_recv = 0; break; } } Group_Peer *temp; --chat->numpeers; if (chat->numpeers == 0) { free(chat->group); chat->group = NULL; return 0; } if (chat->numpeers != (uint32_t)peernum) memcpy(&chat->group[peernum], &chat->group[chat->numpeers], sizeof(Group_Peer)); temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers)); if (temp == NULL) return -1; chat->group = temp; if (chat->peer_namelistchange != NULL) { (*chat->peer_namelistchange)(chat, peernum, CHAT_CHANGE_PEER_DEL, chat->group_namelistchange_userdata); } return 0; }
static int handle_ping_request(void *_dht, IP_Port source, const uint8_t *packet, uint16_t length) { DHT *dht = _dht; int rc; if (length != DHT_PING_SIZE) return 1; PING *ping = dht->ping; if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; uint8_t shared_key[crypto_box_BEFORENMBYTES]; uint8_t ping_plain[PING_PLAIN_SIZE]; // Decrypt ping_id DHT_get_shared_key_recv(dht, shared_key, packet + 1); rc = decrypt_data_symmetric(shared_key, packet + 1 + crypto_box_PUBLICKEYBYTES, packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, PING_PLAIN_SIZE + crypto_box_MACBYTES, ping_plain ); if (rc != sizeof(ping_plain)) return 1; if (ping_plain[0] != NET_PACKET_PING_REQUEST) return 1; uint64_t ping_id; memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); // Send response send_ping_response(ping, source, packet + 1, ping_id, shared_key); add_to_ping(ping, packet + 1, source); return 0; }
int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length) { if (length > MAX_DATA_SIZE) return 1; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; uint8_t number; int len = handle_request(chat->self_public_key, chat->self_secret_key, public_key, data, &number, packet, length); if (len <= 0) return 1; if (id_equal(chat->self_public_key, public_key)) return 1; int peernum = peer_in_chat(chat, public_key); if (peernum == -1) return 1; switch (number) { case CRYPTO_PACKET_GROUP_CHAT_GET_NODES: return handle_getnodes(chat, source, peernum, data, len); case CRYPTO_PACKET_GROUP_CHAT_SEND_NODES: return handle_sendnodes(chat, source, peernum, data, len); case CRYPTO_PACKET_GROUP_CHAT_BROADCAST: return handle_data(chat, data, len); default: return 1; } return 1; }
END_TEST START_TEST(test_fillup) { /* TODO: real test */ int i, j; uint8_t id[CLIENT_ID_SIZE]; //uint32_t a = current_time(); uint32_t a = 2710106197; srand(a); for(i = 0; i < CLIENT_ID_SIZE; ++i) { id[i] = rand(); } Assoc *assoc = new_Assoc(6, 15, id); ck_assert_msg(assoc != NULL, "failed to create default assoc"); struct entry { uint8_t id[CLIENT_ID_SIZE]; IPPTs ippts_send; IP_Port ipp_recv; }; unsigned int fail = 0; struct entry entries[128]; struct entry closest[8]; for(j = 0; j < 128; ++j) { for(i = 0; i < CLIENT_ID_SIZE; ++i) { entries[j].id[i] = rand(); } IP_Port ipp; ipp.ip.family = AF_INET; ipp.ip.ip4.uint32 = rand(); ipp.port = rand(); entries[j].ippts_send.ip_port = ipp; entries[j].ippts_send.timestamp = unix_time(); ipp.ip.ip4.uint32 = rand(); ipp.port = rand(); entries[j].ipp_recv = ipp; if (j % 16 == 0) { memcpy(entries[j].id, id, CLIENT_ID_SIZE - 30); memcpy(&closest[j/16], &entries[j], sizeof(struct entry)); } uint8_t res = Assoc_add_entry(assoc, entries[j].id, &entries[j].ippts_send, &entries[j].ipp_recv, 1); ck_assert_msg(res == 1, "failed to store entry: expected %u, got %u, j = %u", 1, res, j); } int good = 0; Assoc_close_entries close_entries; memset(&close_entries, 0, sizeof(close_entries)); close_entries.count = 8; close_entries.count_good = 8; close_entries.wanted_id = id; Client_data *entri[close_entries.count]; close_entries.result = entri; uint8_t found = Assoc_get_close_entries(assoc, &close_entries); ck_assert_msg(found == 8, "get_close_entries(): expected %u, got %u", 1, found); for (i = 0; i < 8; ++i) { for (j = 0; j < 8; ++j) { if (id_equal(entri[j]->client_id, closest[i].id)) ++good; } }ck_assert_msg(good == 8, "Entries found were not the closest ones. Only %u/8 were.", good); //printf("good: %u %u %u\n", good, a, ((uint32_t)current_time() - a)); }