/* return 0 if ip is a LAN ip. * return -1 if it is not. */ int ip_is_lan(IP ip) { if (ip_is_local(ip)) { return 0; } if (ip.family == TOX_AF_INET) { IP4 ip4 = ip.ip.v4; /* 10.0.0.0 to 10.255.255.255 range. */ if (ip4.uint8[0] == 10) { return 0; } /* 172.16.0.0 to 172.31.255.255 range. */ if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31) { return 0; } /* 192.168.0.0 to 192.168.255.255 range. */ if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) { return 0; } /* 169.254.1.0 to 169.254.254.255 range. */ if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0 && ip4.uint8[2] != 255) { return 0; } /* RFC 6598: 100.64.0.0 to 100.127.255.255 (100.64.0.0/10) * (shared address space to stack another layer of NAT) */ if ((ip4.uint8[0] == 100) && ((ip4.uint8[1] & 0xC0) == 0x40)) { return 0; } } else if (ip.family == TOX_AF_INET6) { /* autogenerated for each interface: FE80::* (up to FEBF::*) FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ if (((ip.ip.v6.uint8[0] == 0xFF) && (ip.ip.v6.uint8[1] < 3) && (ip.ip.v6.uint8[15] == 1)) || ((ip.ip.v6.uint8[0] == 0xFE) && ((ip.ip.v6.uint8[1] & 0xC0) == 0x80))) { return 0; } /* embedded IPv4-in-IPv6 */ if (IPV6_IPV4_IN_V6(ip.ip.v6)) { IP ip4; ip4.family = TOX_AF_INET; ip4.ip.v4.uint32 = ip.ip.v6.uint32[3]; return ip_is_lan(ip4); } } return -1; }
static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) { DHT *dht = (DHT *)object; char ip_str[IP_NTOA_LEN] = { 0 }; ip_ntoa(&source.ip, ip_str, sizeof(ip_str)); if (ip_is_lan(source.ip) == -1) { return 1; } if (length != CRYPTO_PUBLIC_KEY_SIZE + 1) { return 1; } DHT_bootstrap(dht, source, packet + 1); return 0; }
static int handle_announce_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) { Onion_Announce *onion_a = (Onion_Announce *)object; if (length != ANNOUNCE_REQUEST_SIZE_RECV) { return 1; } const uint8_t *packet_public_key = packet + 1 + CRYPTO_NONCE_SIZE; uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; get_shared_key(onion_a->mono_time, &onion_a->shared_keys_recv, shared_key, dht_get_self_secret_key(onion_a->dht), packet_public_key); uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_MAC_SIZE, plain); if ((uint32_t)len != sizeof(plain)) { return 1; } uint8_t ping_id1[ONION_PING_ID_SIZE]; generate_ping_id(onion_a, mono_time_get(onion_a->mono_time), packet_public_key, source, ping_id1); uint8_t ping_id2[ONION_PING_ID_SIZE]; generate_ping_id(onion_a, mono_time_get(onion_a->mono_time) + PING_ID_TIMEOUT, packet_public_key, source, ping_id2); int index; uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE; if (crypto_memcmp(ping_id1, plain, ONION_PING_ID_SIZE) == 0 || crypto_memcmp(ping_id2, plain, ONION_PING_ID_SIZE) == 0) { index = add_to_entries(onion_a, source, packet_public_key, data_public_key, packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)); } else { index = in_entries(onion_a, plain + ONION_PING_ID_SIZE); } /*Respond with a announce response packet*/ Node_format nodes_list[MAX_SENT_NODES]; unsigned int num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, net_family_unspec, ip_is_lan(source.ip), 1); uint8_t nonce[CRYPTO_NONCE_SIZE]; random_nonce(nonce); uint8_t pl[1 + ONION_PING_ID_SIZE + sizeof(nodes_list)]; if (index == -1) { pl[0] = 0; memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE); } else { if (public_key_cmp(onion_a->entries[index].public_key, packet_public_key) == 0) { if (public_key_cmp(onion_a->entries[index].data_public_key, data_public_key) != 0) { pl[0] = 0; memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE); } else { pl[0] = 2; memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE); } } else { pl[0] = 1; memcpy(pl + 1, onion_a->entries[index].data_public_key, CRYPTO_PUBLIC_KEY_SIZE); } } int nodes_length = 0; if (num_nodes != 0) { 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_symmetric(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length, data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE); if (len != 1 + ONION_PING_ID_SIZE + nodes_length + CRYPTO_MAC_SIZE) { return 1; } data[0] = NET_PACKET_ANNOUNCE_RESPONSE; memcpy(data + 1, plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH); memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, CRYPTO_NONCE_SIZE); if (send_onion_response(onion_a->net, source, data, 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE + len, packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)) == -1) { return 1; } return 0; }