From bcb283cf4512f36b189ce2d49eb040c205cbc778 Mon Sep 17 00:00:00 2001 From: "Coren[m]" Date: Tue, 10 Sep 2013 16:36:20 +0200 Subject: [PATCH] big push, putting all the infrastructure in place behind TOX_ENABLE_IPV6 --- other/DHT_bootstrap.c | 13 +- .../DHT_bootstrap_daemon.c | 9 +- testing/DHT_test.c | 33 +- testing/Lossless_UDP_testclient.c | 16 +- testing/Lossless_UDP_testserver.c | 8 +- testing/Messenger_test.c | 5 +- testing/nTox.c | 19 +- toxcore/DHT.c | 118 +++---- toxcore/DHT.h | 25 +- toxcore/LAN_discovery.c | 77 +++- toxcore/Lossless_UDP.c | 50 ++- toxcore/Lossless_UDP.h | 6 + toxcore/Messenger.c | 15 +- toxcore/friend_requests.c | 10 +- toxcore/group_chats.c | 2 +- toxcore/net_crypto.c | 2 +- toxcore/network.c | 332 ++++++++++++++++-- toxcore/network.h | 46 ++- toxcore/ping.c | 6 +- toxcore/tox.c | 5 +- toxcore/tox.h | 49 ++- toxcore/util.c | 5 - toxcore/util.h | 1 - 23 files changed, 621 insertions(+), 231 deletions(-) diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index bc0c592a..7355ca10 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -81,10 +81,14 @@ void manage_keys(DHT *dht) int main(int argc, char *argv[]) { + /* let use decide by cmdline: TODO */ + uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; + /* Initialize networking - Bind to ip 0.0.0.0:PORT */ - IP4 ip; - ip.uint32 = 0; + IP ip; + ip_init(&ip, ipv6enabled); + DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); manage_keys(dht); printf("Public key: "); @@ -110,11 +114,8 @@ int main(int argc, char *argv[]) if (argc > 3) { printf("Trying to bootstrap into the network...\n"); - IP_Port bootstrap_info; - bootstrap_info.ip.uint32 = inet_addr(argv[1]); - bootstrap_info.port = htons(atoi(argv[2])); uint8_t *bootstrap_key = hex_string_to_bin(argv[3]); - DHT_bootstrap(dht, bootstrap_info, bootstrap_key); + DHT_bootstrap_ex(dht, argv[1], ipv6enabled, htons(atoi(argv[2])), bootstrap_key); free(bootstrap_key); } diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c index 58af2751..cf19435d 100644 --- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c +++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c @@ -301,7 +301,12 @@ struct server_conf_s configure_server(char *cfg_file) printf("bootstrap_server %d: Invalid port.\n", i); } +#ifdef TOX_ENABLE_IPV6 + server_conf.info[i].conn.ip.family = AF_INET; + server_conf.info[i].conn.ip.ip4.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip)); +#else server_conf.info[i].conn.ip.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip)); +#endif server_conf.info[i].conn.port = htons(bs_port); b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p); } @@ -339,8 +344,8 @@ int main(int argc, char *argv[]) /* Initialize networking bind to ip 0.0.0.0:PORT */ - IP4 ip; - ip.uint32 = 0; + IP ip; + ip_init(&ip, 0); DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port))); /* Read the config file */ printf("PID file: %s\n", server_conf.pid_file); diff --git a/testing/DHT_test.c b/testing/DHT_test.c index a7349a65..caa0cde2 100644 --- a/testing/DHT_test.c +++ b/testing/DHT_test.c @@ -66,13 +66,11 @@ void print_clientlist(DHT *dht) } p_ip = dht->close_clientlist[i].ip_port; - printf("\nIP: %u.%u.%u.%u Port: %u", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], - ntohs(p_ip.port)); + printf("\nIP: %s Port: %u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port)); printf("\nTimestamp: %llu", (long long unsigned int) dht->close_clientlist[i].timestamp); printf("\nLast pinged: %llu\n", (long long unsigned int) dht->close_clientlist[i].last_pinged); p_ip = dht->close_clientlist[i].ret_ip_port; - printf("OUR IP: %u.%u.%u.%u Port: %u\n", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], - ntohs(p_ip.port)); + printf("OUR IP: %s Port: %u\n", ip_ntoa(&p_ip.ip), ntohs(p_ip.port)); printf("Timestamp: %llu\n", (long long unsigned int) dht->close_clientlist[i].ret_timestamp); } } @@ -91,9 +89,8 @@ void print_friendlist(DHT *dht) printf("%c", dht->friends_list[k].client_id[j]); } - p_ip = DHT_getfriendip(dht, dht->friends_list[k].client_id); - printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], - ntohs(p_ip.port)); + int friendok = DHT_getfriendip(dht, dht->friends_list[k].client_id, &p_ip); + printf("\nIP: %s:%u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port)); printf("\nCLIENTS IN LIST:\n\n"); @@ -108,13 +105,11 @@ void print_friendlist(DHT *dht) } p_ip = dht->friends_list[k].client_list[i].ip_port; - printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], - ntohs(p_ip.port)); + printf("\nIP: %s:%u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port)); printf("\nTimestamp: %llu", (long long unsigned int) dht->friends_list[k].client_list[i].timestamp); printf("\nLast pinged: %llu\n", (long long unsigned int) dht->friends_list[k].client_list[i].last_pinged); p_ip = dht->friends_list[k].client_list[i].ret_ip_port; - printf("ret IP: %u.%u.%u.%u:%u\n", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], - ntohs(p_ip.port)); + printf("ret IP: %s:%u\n", ip_ntoa(&p_ip.ip), ntohs(p_ip.port)); printf("Timestamp: %llu\n", (long long unsigned int)dht->friends_list[k].client_list[i].ret_timestamp); } } @@ -138,11 +133,14 @@ void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) int main(int argc, char *argv[]) { + /* let use decide by cmdline: TODO */ + uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; + //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); /* initialize networking */ /* bind to ip 0.0.0.0:PORT */ - IP4 ip; - ip.uint32 = 0; + IP ip; + ip_init(&ip, ipv6enabled); DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); @@ -172,14 +170,7 @@ int main(int argc, char *argv[]) perror("Initialization"); - IP_Port bootstrap_ip_port; - bootstrap_ip_port.port = htons(atoi(argv[2])); - /* bootstrap_ip_port.ip.c[0] = 127; - * bootstrap_ip_port.ip.c[1] = 0; - * bootstrap_ip_port.ip.c[2] = 0; - * bootstrap_ip_port.ip.c[3] = 1; */ - bootstrap_ip_port.ip.uint32 = inet_addr(argv[1]); - DHT_bootstrap(dht, bootstrap_ip_port, hex_string_to_bin(argv[3])); + DHT_bootstrap_ex(dht, argv[1], ipv6enabled, htons(atoi(argv[2])), hex_string_to_bin(argv[3])); /* IP_Port ip_port; diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c index 4ac94b4b..564b2ecf 100644 --- a/testing/Lossless_UDP_testclient.c +++ b/testing/Lossless_UDP_testclient.c @@ -66,8 +66,7 @@ void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) void printip(IP_Port ip_port) { - printf("\nIP: %u.%u.%u.%u Port: %u", ip_port.ip.uint8[0], ip_port.ip.uint8[1], ip_port.ip.uint8[2], ip_port.ip.uint8[3], - ntohs(ip_port.port)); + printf("\nIP: %s Port: %u", ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); } /* void printpackets(Data test) @@ -152,6 +151,9 @@ void printconnection(int connection_id) int main(int argc, char *argv[]) { + /* let use decide by cmdline: TODO */ + uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; + if (argc < 4) { printf("usage: %s ip port filename\n", argv[0]); exit(0); @@ -168,14 +170,18 @@ int main(int argc, char *argv[]) /* initialize networking */ /* bind to ip 0.0.0.0:PORT */ - IP4 ip; - ip.uint32 = 0; + IP ip; + ip_init(&ip, ipv6enabled); + Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); perror("Initialization"); + IP_Port serverip; - serverip.ip.uint32 = inet_addr(argv[1]); + ip_init(&serverip.ip, ipv6enabled); + addr_resolve(argv[1], &serverip.ip); serverip.port = htons(atoi(argv[2])); printip(serverip); + int connection = new_connection(ludp, serverip); uint64_t timer = current_time(); diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c index e0ea92bc..3e54e9be 100644 --- a/testing/Lossless_UDP_testserver.c +++ b/testing/Lossless_UDP_testserver.c @@ -147,6 +147,9 @@ void printconnection(int connection_id) int main(int argc, char *argv[]) { + /* let use decide by cmdline: TODO */ + uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; + if (argc < 2) { printf("usage: %s filename\n", argv[0]); exit(0); @@ -163,8 +166,9 @@ int main(int argc, char *argv[]) //initialize networking //bind to ip 0.0.0.0:PORT - IP4 ip; - ip.uint32 = 0; + IP ip; + ip_init(&ip, ipv6enabled); + Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); perror("Initialization"); diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c index 04d3bc14..73d44efb 100644 --- a/testing/Messenger_test.c +++ b/testing/Messenger_test.c @@ -101,7 +101,8 @@ int main(int argc, char *argv[]) } /* IPv6: maybe allow from cmdline --ipv6? sticking to IPv4 for now */ - m = initMessenger(0); + uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; + m = initMessenger(ipv6enabled); if ( !m ) { fputs("Failed to allocate messenger datastructure\n", stderr); @@ -110,7 +111,7 @@ int main(int argc, char *argv[]) if (argc > 3) { uint16_t port = htons(atoi(argv[2])); - DHT_bootstrap_ex(m->dht, argv[1], port, hex_string_to_bin(argv[3])); + DHT_bootstrap_ex(m->dht, argv[1], ipv6enabled, port, hex_string_to_bin(argv[3])); } else { FILE *file = fopen(argv[1], "rb"); diff --git a/testing/nTox.c b/testing/nTox.c index 438468bd..6084aeda 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -537,6 +537,9 @@ void print_help(void) int main(int argc, char *argv[]) { + /* let use decide by cmdline: TODO */ + uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; + int on = 0; int c = 0; int i = 0; @@ -566,7 +569,7 @@ int main(int argc, char *argv[]) } } - m = tox_new(); + m = tox_new_ex(ipv6enabled); if ( !m ) { fputs("Failed to allocate Messenger datastructure", stderr); @@ -590,20 +593,12 @@ int main(int argc, char *argv[]) new_lines(idstring); strcpy(line, ""); - tox_IP_Port bootstrap_ip_port; - bootstrap_ip_port.port = htons(atoi(argv[2])); - int resolved_address = resolve_addr(argv[1]); - - if (resolved_address != 0) - bootstrap_ip_port.ip.i = resolved_address; - else - exit(1); - + uint16_t port = htons(atoi(argv[2])); unsigned char *binary_string = hex_string_to_bin(argv[3]); - tox_bootstrap(m, bootstrap_ip_port, binary_string); + tox_bootstrap_ex(m, argv[1], ipv6enabled, port, binary_string); free(binary_string); - nodelay(stdscr, TRUE); + nodelay(stdscr, TRUE); while (1) { if (on == 0 && tox_isconnected(m)) { new_lines("[i] connected to DHT\n[i] define username with /n"); diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 4c15c1eb..a4734747 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -115,11 +115,6 @@ static int client_id_cmp(ClientPair p1, ClientPair p2) return c; } -static int ip4port_equal(IP_Port a, IP_Port b) -{ - return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port); -} - static int id_equal(uint8_t *a, uint8_t *b) { return memcmp(a, b, CLIENT_ID_SIZE) == 0; @@ -144,15 +139,14 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id for (i = 0; i < length; ++i) { /* If ip_port is assigned to a different client_id replace it */ - if (ip4port_equal(list[i].ip_port, ip_port)) { + if (ipport_equal(&list[i].ip_port, &ip_port)) { memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); } if (id_equal(list[i].client_id, client_id)) { /* Refresh the client timestamp. */ list[i].timestamp = temp_time; - list[i].ip_port.ip.uint32 = ip_port.ip.uint32; - list[i].ip_port.port = ip_port.port; + ipport_copy(&list[i].ip_port, &ip_port); return 1; } } @@ -216,7 +210,7 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the * partner node understands - that's true if *they* are on IPv6 */ -#ifdef NETWORK_IP_PORT_IS_IPV6 +#ifdef TOX_ENABLE_IPV6 ipv46x = 0; if (sa_family == AF_INET) ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET; @@ -266,7 +260,7 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list MAX_SENT_NODES, dht->friends_list[i].client_list[j].client_id); -#ifdef NETWORK_IP_PORT_IS_IPV6 +#ifdef TOX_ENABLE_IPV6 ipv46x = 0; if (sa_family == AF_INET) ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET; @@ -330,7 +324,7 @@ static int replace_bad( Client_data *list, memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); list[i].ip_port = ip_port; list[i].timestamp = temp_time; - list[i].ret_ip_port.ip.uint32 = 0; + ip_reset(&list[i].ret_ip_port.ip); list[i].ret_ip_port.port = 0; list[i].ret_timestamp = 0; return 0; @@ -378,7 +372,7 @@ static int replace_good( Client_data *list, memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); list[i].ip_port = ip_port; list[i].timestamp = temp_time; - list[i].ret_ip_port.ip.uint32 = 0; + ip_reset(&list[i].ret_ip_port.ip); list[i].ret_ip_port.port = 0; list[i].ret_timestamp = 0; return 0; @@ -476,13 +470,13 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id) if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { pinging = 0; - if (ip_port.ip.uint32 != 0 && ip4port_equal(dht->send_nodes[i].ip_port, ip_port)) - ++pinging; - if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) ++pinging; - if (pinging == (ping_id != 0) + (ip_port.ip.uint32 != 0)) + if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port)) + ++pinging; + + if (pinging == (ping_id != 0) + (ip_isset(&ip_port.ip) != 0)) return 1; } } @@ -575,11 +569,11 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl random_nonce(nonce); memcpy(plain, &ping_id, sizeof(ping_id)); -#if DHT_NODEFORMAT == 46 - Node4_format *nodes4_list = &(plain + sizeof(ping_id)); +#ifdef TOX_ENABLE_IPV6 + Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); int i, num_nodes_ok = 0; - for(i = 0; i < num_nodes, i++) - if (nodes_list[i].ip.family == AF_INET) { + for(i = 0; i < num_nodes; i++) + if (nodes_list[i].ip_port.ip.family == AF_INET) { memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32; nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; @@ -680,14 +674,15 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 if (!is_gettingnodes(dht, source, ping_id)) return 1; + uint32_t i; Node_format nodes_list[MAX_SENT_NODES]; -#if DHT_NODEFORMAT == 46 - Node4_format *nodes4_list = &(plain + sizeof(ping_id)); +#ifdef TOX_ENABLE_IPV6 + Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); - int i, num_nodes_ok = 0; - for(i = 0; i < num_nodes, i++) - if ((nodes_list[i].ip != 0) && (nodes_list[i].ip != ~0)) { + int num_nodes_ok = 0; + for(i = 0; i < num_nodes; i++) + if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) { memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; @@ -706,8 +701,6 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 addto_lists(dht, source, packet + 1); - uint32_t i; - for (i = 0; i < num_nodes; ++i) { send_ping_request(dht->ping, dht->c, 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); @@ -775,27 +768,30 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id) } /* TODO: Optimize this. */ -IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id) +int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port) { uint32_t i, j; uint64_t temp_time = unix_time(); - IP_Port empty = {{{{0}}, 0, 0}}; + + ip_reset(&ip_port->ip); + ip_port->port = 0; for (i = 0; i < dht->num_friends; ++i) { /* Equal */ if (id_equal(dht->friends_list[i].client_id, client_id)) { for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) - && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) - return dht->friends_list[i].client_list[j].ip_port; + && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { + *ip_port = dht->friends_list[i].client_list[j].ip_port; + return 1; + } } - return empty; + return 0; } } - empty.ip.uint32 = 1; - return empty; + return -1; } /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request @@ -880,16 +876,12 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) getnodes(dht, ip_port, public_key, dht->c->self_public_key); send_ping_request(dht->ping, dht->c, ip_port, public_key); } -void DHT_bootstrap_ex(DHT *dht, const char *address, uint16_t port, uint8_t *public_key) +void DHT_bootstrap_ex(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) { - IPAny_Port ipany_port; - ipany_port.ip.family = AF_INET; - if (addr_resolve_or_parse_ip(address, &ipany_port.ip)) { - /* IPAny temporary: copy down */ - IP_Port ip_port; - ip_port.ip.uint32 = ipany_port.ip.ip4.uint32; + IP_Port ip_port; + ip_init(&ip_port.ip, ipv6enabled); + if (addr_resolve_or_parse_ip(address, &ip_port.ip)) { ip_port.port = port; - DHT_bootstrap(dht, ip_port, public_key); } } @@ -933,7 +925,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) client = &friend->client_list[i]; /* If ip is not zero and node is good. */ - if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { + if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { if (id_equal(client->client_id, friend->client_id)) return 0; @@ -975,7 +967,7 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt client = &friend->client_list[i]; /* If ip is not zero and node is good. */ - if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { + if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length); if ((unsigned int)retval == length) @@ -1009,7 +1001,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint client = &friend->client_list[i]; /* If ip is not zero and node is good. */ - if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { + if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { ip_list[n] = client->ip_port; ++n; } @@ -1115,9 +1107,10 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey, * * return ip of 0 if failure. */ -static IP4 NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) +static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) { - IP4 zero = {{0}}; + IP zero; + ip_reset(&zero); if (len > MAX_FRIEND_CLIENTS) return zero; @@ -1127,7 +1120,7 @@ static IP4 NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) for (i = 0; i < len; ++i) { for (j = 0; j < len; ++j) { - if (ip_portlist[i].ip.uint32 == ip_portlist[j].ip.uint32) + if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) ++numbers[i]; } @@ -1144,13 +1137,13 @@ static IP4 NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) * * return number of ports and puts the list of ports in portlist. */ -static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP4 ip) +static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip) { uint32_t i; uint16_t num = 0; for (i = 0; i < len; ++i) { - if (ip_portlist[i].ip.uint32 == ip.uint32) { + if (ip_equal(&ip_portlist[i].ip, &ip)) { portlist[num] = ntohs(ip_portlist[i].port); ++num; } @@ -1159,7 +1152,7 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t return num; } -static void punch_holes(DHT *dht, IP4 ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) +static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) { if (numports > MAX_FRIEND_CLIENTS || numports == 0) return; @@ -1170,7 +1163,9 @@ static void punch_holes(DHT *dht, IP4 ip, uint16_t *port_list, uint16_t numports for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { /* TODO: Improve port guessing algorithm. */ uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); - IP_Port pinging = {{ip, htons(port), 0}}; + IP_Port pinging; + ip_copy(&pinging.ip, &ip); + pinging.port = htons(port); send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); } @@ -1199,9 +1194,8 @@ static void do_NAT(DHT *dht) dht->friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { - IP4 ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); - - if (ip.uint32 == 0) + IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); + if (!ip_isset(&ip)) continue; uint16_t port_list[MAX_FRIEND_CLIENTS]; @@ -1230,16 +1224,15 @@ static void do_NAT(DHT *dht) */ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) { - if (ip_port.ip.uint32 == 0) + if (!ip_isset(&ip_port.ip)) return -1; uint32_t i; for (i = 0; i < MAX_TOPING; ++i) { - if (dht->toping[i].ip_port.ip.uint32 == 0) { + if (!ip_isset(&dht->toping[i].ip_port.ip)) { memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); - dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; - dht->toping[i].ip_port.port = ip_port.port; + ipport_copy(&dht->toping[i].ip_port, &ip_port); return 0; } } @@ -1247,8 +1240,7 @@ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) for (i = 0; i < MAX_TOPING; ++i) { if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); - dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; - dht->toping[i].ip_port.port = ip_port.port; + ipport_copy(&dht->toping[i].ip_port, &ip_port); return 0; } } @@ -1270,11 +1262,11 @@ static void do_toping(DHT *dht) uint32_t i; for (i = 0; i < MAX_TOPING; ++i) { - if (dht->toping[i].ip_port.ip.uint32 == 0) + if (!ip_isset(&dht->toping[i].ip_port.ip)) return; send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); - dht->toping[i].ip_port.ip.uint32 = 0; + ip_reset(&dht->toping[i].ip_port.ip); } } diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 5963d297..d980f269 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -83,13 +83,14 @@ typedef struct { typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; - IPAny_Port ip_port; + IP_Port ip_port; } Node46_format; -/* IPAny temporary: change to 46 */ -#define DHT_NODEFORMAT 4 + +#ifdef TOX_ENABLE_IPV6 +typedef Node46_format Node_format; +#else typedef Node4_format Node_format; -/* #define DHT_NODEFORMAT 46 */ -/* typedef Node46_format Node_format; */ +#endif typedef struct { IP_Port ip_port; @@ -135,11 +136,21 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id); * ip must be 4 bytes long. * port must be 2 bytes long. * + * !!! Signature changed!!! + * + * OLD: IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id); + * * return ip if success. * return ip of 0 if failure (This means the friend is either offline or we have not found him yet). * return ip of 1 if friend is not in list. + * + * NEW: int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port); + * + * return -1, -- if client_id does NOT refer to a friend + * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) + * return 1, ip if client_id refers to a friend and we found him */ -IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id); +int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port); /* Run this function at least a couple times per second (It's the main loop). */ void do_DHT(DHT *dht); @@ -148,7 +159,7 @@ void do_DHT(DHT *dht); * Sends a get nodes request to the given node with ip port and public_key. */ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); -void DHT_bootstrap_ex(DHT *dht, const char *address, uint16_t port, uint8_t *public_key); +void DHT_bootstrap_ex(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key); /* Add nodes to the toping list. * All nodes in this list are pinged every TIME_TOPING seconds diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index bc73a6a1..4cbe3177 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c @@ -81,33 +81,76 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t * d #endif /* Return the broadcast ip. */ -static IP4 broadcast_ip(void) +static IP broadcast_ip(sa_family_t sa_family) { - IP4 ip; - ip.uint32 = ~0; + IP ip; + ip_reset(&ip); + +#ifdef TOX_ENABLE_IPV6 + if (sa_family == AF_INET) + { + ip.family = AF_INET; + ip.ip4.uint32 = INADDR_BROADCAST; + } + + if (sa_family == AF_INET6) + { + ip.family = AF_INET6; + /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ + /* FE80::*: MUST be exact, for that we would need to look over all + * interfaces and check in which status they are */ + ip.ip6.s6_addr[ 0] = 0xFF; + ip.ip6.s6_addr[ 1] = 0x02; + ip.ip6.s6_addr[15] = 0x01; + } +#else + ip.uint32 = INADDR_BROADCAST; +#endif + return ip; } /* return 0 if ip is a LAN ip. * return -1 if it is not. */ -static int LAN_ip(IP4 ip) +static int LAN_ip(IP ip) { - if (ip.uint8[0] == 127) /* Loopback. */ - return 0; +#ifdef TOX_ENABLE_IPV6 + if (ip.family == AF_INET) { + IP4 ip4 = ip.ip4; +#else + IP4 ip4 = ip; +#endif + /* Loopback. */ + if (ip4.uint8[0] == 127) + return 0; - if (ip.uint8[0] == 10) /* 10.0.0.0 to 10.255.255.255 range. */ - return 0; + /* 10.0.0.0 to 10.255.255.255 range. */ + if (ip4.uint8[0] == 10) + return 0; - if (ip.uint8[0] == 172 && ip.uint8[1] >= 16 && ip.uint8[1] <= 31) /* 172.16.0.0 to 172.31.255.255 range. */ - 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; - if (ip.uint8[0] == 192 && ip.uint8[1] == 168) /* 192.168.0.0 to 192.168.255.255 range. */ - return 0; + /* 192.168.0.0 to 192.168.255.255 range. */ + if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) + return 0; - if (ip.uint8[0] == 169 && ip.uint8[1] == 254 && ip.uint8[2] != 0 - && ip.uint8[2] != 255)/* 169.254.1.0 to 169.254.254.255 range. */ - 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; +#ifdef TOX_ENABLE_IPV6 + } + else if (ip.family == AF_INET6) { + /* autogenerated for each interface: FE80::* (up to FEBF::*) + /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ + if (((ip.ip6.s6_addr[0] == 0xFF) && (ip.ip6.s6_addr[1] < 3) && (ip.ip6.s6_addr[15] == 1)) || + ((ip.ip6.s6_addr[0] == 0xFE) && ((ip.ip6.s6_addr[1] & 0xC0) == 0x80))) + return 0; + } +#endif return -1; } @@ -135,7 +178,9 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c) #ifdef __linux send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); #endif - IP_Port ip_port = {{broadcast_ip(), port, 0}}; + IP_Port ip_port; + ip_port.ip = broadcast_ip(c->lossless_udp->net->family); + ip_port.port = port; return sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); } diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c index f66d5b62..ca874562 100644 --- a/toxcore/Lossless_UDP.c +++ b/toxcore/Lossless_UDP.c @@ -44,9 +44,7 @@ int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) { tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->ip_port.ip.uint32 == ip_port.ip.uint32 && - tmp->ip_port.port == ip_port.port && - tmp->status > 0) { + if (tmp-> status > 0 && ipport_equal(&tmp->ip_port, &ip_port)) { return tmp_i; } } @@ -61,17 +59,49 @@ int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) * * TODO: make this better */ + +static uint8_t randtable_initget(Lossless_UDP *ludp, uint32_t index, uint8_t value) +{ + if (ludp->randtable[index][value] == 0) + ludp->randtable[index][value] = random_int(); + + return ludp->randtable[index][value]; +} + static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source) { - uint32_t id = 0, i; + uint32_t id = 0, i = 0; - for (i = 0; i < 6; ++i) { - if (ludp->randtable[i][source.uint8[i]] == 0) - ludp->randtable[i][source.uint8[i]] = random_int(); + uint8_t *uint8; + uint8 = (uint8_t *)&source.port; + id ^= randtable_initget(ludp, i, *uint8); + i++, uint8++; + id ^= randtable_initget(ludp, i, *uint8); + i++; - id ^= ludp->randtable[i][source.uint8[i]]; +#ifdef TOX_ENABLE_IPV6 + if (source.ip.family == AF_INET) + { + IP4 ip4 = source.ip.ip4; +#else + IP4 ip4 = source.ip; +#endif + int k; + for (k = 0; k < 4; k++) { + id ^= randtable_initget(ludp, i++, ip4.uint8[k]); + } +#ifdef TOX_ENABLE_IPV6 } + if (source.ip.family == AF_INET6) + { + int k; + for (k = 0; k < 16; k++) { + id ^= randtable_initget(ludp, i++, source.ip.ip6.s6_addr[k]); + } + } +#endif + /* id can't be zero. */ if (id == 0) id = 1; @@ -290,7 +320,9 @@ IP_Port connection_ip(Lossless_UDP *ludp, int connection_id) if ((unsigned int)connection_id < ludp->connections.len) return tox_array_get(&ludp->connections, connection_id, Connection).ip_port; - IP_Port zero = {{{{0}}, 0, 0}}; + IP_Port zero; + ip_reset(&zero.ip); + zero.port = 0; return zero; } diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h index 20471b0a..f0ce0e87 100644 --- a/toxcore/Lossless_UDP.h +++ b/toxcore/Lossless_UDP.h @@ -123,7 +123,13 @@ typedef struct { tox_array connections; /* Table of random numbers used in handshake_id. */ +#ifdef TOX_ENABLE_IPV6 + /* IPv6 (16) + port (2)*/ + uint32_t randtable[18][256]; +#else + /* IPv4 (4) + port (2) */ uint32_t randtable[6][256]; +#endif } Lossless_UDP; diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 61a76a76..cf744e23 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -658,14 +658,8 @@ Messenger *initMessenger(uint8_t ipv6enabled) if ( ! m ) return NULL; -#ifdef NETWORK_IP_PORT_IS_IPV6 - IPAny ip; - memset(&ip, 0, sizeof(ip)); - ip.family = ipv6enabled ? AF_INET6 : AF_INET; -#else - IP4 ip; - ip.uint32 = 0; -#endif + IP ip; + ip_init(&ip, ipv6enabled); m->net = new_networking(ip, PORT); if (m->net == NULL) { @@ -749,11 +743,12 @@ void doFriends(Messenger *m) } } - IP_Port friendip = DHT_getfriendip(m->dht, m->friendlist[i].client_id); + IP_Port friendip; + int friendok = DHT_getfriendip(m->dht, m->friendlist[i].client_id, &friendip); switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { case 0: - if (friendip.ip.uint32 > 1) + if (friendok == 1) m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip); break; diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index 51a8112f..c821d998 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c @@ -50,18 +50,22 @@ int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8 if (len == -1) return -1; - IP_Port ip_port = DHT_getfriendip(dht, public_key); + IP_Port ip_port; + int friendok = DHT_getfriendip(dht, public_key, &ip_port); - if (ip_port.ip.uint32 == 1) + // not a friend + if (friendok == -1) return -1; - if (ip_port.ip.uint32 != 0) { + // is a friend and we know how to reach him + if (friendok == 1) { if (sendpacket(dht->c->lossless_udp->net, ip_port, packet, len) != -1) return 0; return -1; } + // is a friend, we DON'T know how to reach him int num = route_tofriend(dht, public_key, packet, len); if (num == 0) diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c index 1b021e20..59266b7a 100644 --- a/toxcore/group_chats.c +++ b/toxcore/group_chats.c @@ -204,7 +204,7 @@ static uint8_t sendto_allpeers(Group_Chat *chat, uint8_t *data, uint16_t length, uint64_t temp_time = unix_time(); for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { - if (chat->close[i].ip_port.ip.uint32 != 0 && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) { + if (ip_isset(&chat->close[i].ip_port.ip) && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) { if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0) ++sent; } diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index a182bb53..b6f08fe4 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -439,7 +439,7 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) if (id != -1) { IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number); - if (c_ip.ip.uint32 == ip_port.ip.uint32 && c_ip.port == ip_port.port) + if (ipport_equal(&c_ip, &ip_port)) return -1; } diff --git a/toxcore/network.c b/toxcore/network.c index 1fb5b77a..d65e2077 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -66,8 +66,63 @@ uint32_t random_int(void) */ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length) { - ADDR addr = {AF_INET, ip_port.port, ip_port.ip, {0}}; - return sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); +#ifdef TOX_ENABLE_IPV6 + /* socket AF_INET, but target IP NOT: can't send */ + if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET)) + return 0; +#endif + + struct sockaddr_storage addr; + size_t addrsize = 0; + +#ifdef TOX_ENABLE_IPV6 + if (ip_port.ip.family == AF_INET) { + if (net->family == AF_INET6) { + /* must convert to IPV4-in-IPV6 address */ + addrsize = sizeof(struct sockaddr_in6); + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_port = ip_port.port; + + /* there should be a macro for this in a standards compliant + * environment, not found */ + addr6->sin6_addr.s6_addr32[0] = 0; + addr6->sin6_addr.s6_addr32[1] = 0; + addr6->sin6_addr.s6_addr32[2] = htonl(0xFFFF); + addr6->sin6_addr.s6_addr32[3] = ip_port.ip.ip4.uint32; + + addr6->sin6_flowinfo = 0; + addr6->sin6_scope_id = 0; + } + else { + IP4 ip4 = ip_port.ip.ip4; +#else + IP4 ip4 = ip_port.ip; +#endif + addrsize = sizeof(struct sockaddr_in); + struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; + addr4->sin_family = AF_INET; + addr4->sin_addr = ip4.in_addr; + addr4->sin_port = ip_port.port; +#ifdef TOX_ENABLE_IPV6 + } + } + else if (ip_port.ip.family == AF_INET6) { + addrsize = sizeof(struct sockaddr_in6); + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_port = ip_port.port; + addr6->sin6_addr = ip_port.ip.ip6; + + addr6->sin6_flowinfo = 0; + addr6->sin6_scope_id = 0; + } else { + /* unknown address type*/ + return 0; + } +#endif + + return sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize); } /* Function to receive data @@ -82,7 +137,7 @@ static int receivepacket(unsigned int sock, IP_Port *ip_port, uint8_t *data, uin static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) #endif { - ADDR addr; + struct sockaddr_storage addr; #ifdef WIN32 int addrlen = sizeof(addr); #else @@ -93,8 +148,31 @@ static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *le if (*(int32_t *)length <= 0) return -1; /* Nothing received or empty packet. */ - ip_port->ip = addr.ip; - ip_port->port = addr.port; +#ifdef TOX_ENABLE_IPV6 + if (addr.ss_family == AF_INET) { + struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; + ip_port->ip.family = addr_in->sin_family; + ip_port->ip.ip4.in_addr = addr_in->sin_addr; + ip_port->port = addr_in->sin_port; + } + else if (addr.ss_family == AF_INET6) { + struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr; + ip_port->ip.family = addr_in6->sin6_family; + ip_port->ip.ip6 = addr_in6->sin6_addr; + ip_port->port = addr_in6->sin6_port; + } + else + return -1; +#else + if (addr.ss_family == AF_INET) { + struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; + ip_port->ip.in_addr = addr_in->sin_addr; + ip_port->port = addr_in->sin_port; + } + else + return -1; +#endif + return 0; } @@ -156,18 +234,32 @@ static void at_shutdown(void) * return Networking_Core object if no problems * return NULL if there are problems. */ -Networking_Core *new_networking(IP4 ip, uint16_t port) +Networking_Core *new_networking(IP ip, uint16_t port) { +#ifdef TOX_ENABLE_IPV6 + /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */ + if (ip.family != AF_INET && ip.family != AF_INET6) + return NULL; +#endif + if (at_startup() != 0) return NULL; - /* Initialize our socket. */ Networking_Core *temp = calloc(1, sizeof(Networking_Core)); - if (temp == NULL) return NULL; - temp->family = AF_INET; + sa_family_t family = 0; +#ifdef TOX_ENABLE_IPV6 + family = ip.family; +#else + family = AF_INET; +#endif + temp->family = family; + temp->port = 0; + + /* Initialize our socket. */ + /* add log message what we're creating */ temp->sock = socket(temp->family, SOCK_DGRAM, IPPROTO_UDP); /* Check for socket error. */ @@ -201,7 +293,7 @@ Networking_Core *new_networking(IP4 ip, uint16_t port) return -1; */ - /* Enable broadcast on socket. */ + /* Enable broadcast on socket? */ int broadcast = 1; setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); @@ -216,11 +308,72 @@ Networking_Core *new_networking(IP4 ip, uint16_t port) #endif /* Bind our socket to port PORT and address 0.0.0.0 */ - ADDR addr = {temp->family, htons(port), ip, {0}}; - if (!bind(temp->sock, (struct sockaddr *)&addr, sizeof(addr))) - temp->port = port; + uint16_t *portptr = NULL; + struct sockaddr_storage addr; + size_t addrsize; +#ifdef TOX_ENABLE_IPV6 + if (temp->family == AF_INET) + { + IP4 ip4 = ip.ip4; +#else + IP4 ip4 = ip; +#endif + addrsize = sizeof(struct sockaddr_in); + struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(port); + addr4->sin_addr = ip4.in_addr; - return temp; + portptr = &addr4->sin_port; +#ifdef TOX_ENABLE_IPV6 + } + else if (temp->family == AF_INET6) + { + addrsize = sizeof(struct sockaddr_in6); + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(port); + addr6->sin6_addr = ip.ip6; + + addr6->sin6_flowinfo = 0; + addr6->sin6_scope_id = 0; + + portptr = &addr6->sin6_port; + } + else + return NULL; + + if (ip.family == AF_INET6) { + char ipv6only = 0; + int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)); + if (res < 0) { + /* add log message*/ + } + } +#endif + + /* a hanging program or a different user might block the standard port; + * as long as it isn't a parameter coming from the commandline, + * try a few ports after it, to see if we can find a "free" one + */ + int tries, res; + for(tries = 0; tries < 9; tries++) + { + res = bind(temp->sock, (struct sockaddr *)&addr, addrsize); + if (!res) + { + temp->port = *portptr; + return temp; + } + + uint16_t port = ntohs(*portptr); + port++; + *portptr = htons(port); + } + + printf("Failed to bind socket: %s (IP/Port: %s:%u\n", strerror(errno), ip_ntoa(&ip), port); + free(temp); + return NULL; } /* Function to cleanup networking stuff. */ @@ -241,11 +394,12 @@ void kill_networking(Networking_Core *net) * * returns 0 when not equal or when uninitialized */ -int ip_equal(IPAny *a, IPAny *b) +int ip_equal(IP *a, IP *b) { if (!a || !b) return 0; +#ifdef TOX_ENABLE_IPV6 if (a->family == AF_INET) return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr); @@ -253,6 +407,9 @@ int ip_equal(IPAny *a, IPAny *b) return IN6_ARE_ADDR_EQUAL(&a->ip6, &b->ip6); return 0; +#else + return (a->uint32 == b->uint32); +#endif }; /* ipport_equal @@ -261,7 +418,7 @@ int ip_equal(IPAny *a, IPAny *b) * * returns 0 when not equal or when uninitialized */ -int ipport_equal(IPAny_Port *a, IPAny_Port *b) +int ipport_equal(IP_Port *a, IP_Port *b) { if (!a || !b) return 0; @@ -272,15 +429,86 @@ int ipport_equal(IPAny_Port *a, IPAny_Port *b) return ip_equal(&a->ip, &b->ip); }; -/* ipany_ntoa +/* nulls out ip */ +void ip_reset(IP *ip) +{ + if (!ip) + return; + +#ifdef TOX_ENABLE_IPV6 + memset(ip, 0, sizeof(*ip)); +#else + ip->uint32 = 0; +#endif +}; + +/* nulls out ip, sets family according to flag */ +void ip_init(IP *ip, uint8_t ipv6enabled) +{ + if (!ip) + return; + +#ifdef TOX_ENABLE_IPV6 + memset(ip, 0, sizeof(ip)); + ip->family = ipv6enabled ? AF_INET6 : AF_INET; +#else + ip->uint32 = 0; +#endif +}; + +/* checks if ip is valid */ +int ip_isset(IP *ip) +{ + if (!ip) + return 0; + +#ifdef TOX_ENABLE_IPV6 + return (ip->family != 0); +#else + return (ip->uint32 != 0); +#endif +}; + +/* checks if ip is valid */ +int ipport_isset(IP_Port *ipport) +{ + if (!ipport) + return 0; + + if (!ipport->port) + return 0; + + return ip_isset(&ipport->ip); +}; + +/* copies an ip structure (careful about direction!) */ +void ip_copy(IP *target, IP *source) +{ + if (!source || !target) + return; + + memcpy(target, source, sizeof(IP)); +}; + +/* copies an ip_port structure (careful about direction!) */ +void ipport_copy(IP_Port *target, IP_Port *source) +{ + if (!source || !target) + return; + + memcpy(target, source, sizeof(IP_Port)); +}; + +/* ip_ntoa * converts ip into a string * uses a static buffer, so mustn't used multiple times in the same output */ /* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */ static char addresstext[96]; -const char *ipany_ntoa(IPAny *ip) +const char *ip_ntoa(IP *ip) { if (ip) { +#ifdef TOX_ENABLE_IPV6 if (ip->family == AF_INET) { addresstext[0] = 0; struct in_addr *addr = (struct in_addr *)&ip->ip4; @@ -296,6 +524,11 @@ const char *ipany_ntoa(IPAny *ip) } else snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family); +#else + addresstext[0] = 0; + struct in_addr *addr = (struct in_addr *)&ip; + inet_ntop(AF_INET, addr, addresstext, sizeof(addresstext)); +#endif } else snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)"); @@ -318,8 +551,12 @@ const char *ipany_ntoa(IPAny *ip) * returns 1 on success, 0 on failure */ -int addr_parse_ip(const char *address, IPAny *to) +int addr_parse_ip(const char *address, IP *to) { + if (!address || !to) + return 0; + +#ifdef TOX_ENABLE_IPV6 struct in_addr addr4; if (1 == inet_pton(AF_INET, address, &addr4)) { to->family = AF_INET; @@ -333,6 +570,13 @@ int addr_parse_ip(const char *address, IPAny *to) to->ip6 = addr6; return 1; }; +#else + struct in_addr addr4; + if (1 == inet_pton(AF_INET, address, &addr4)) { + to->in_addr = addr4; + return 1; + }; +#endif return 0; }; @@ -353,15 +597,25 @@ int addr_parse_ip(const char *address, IPAny *to) * returns 0 on failure */ -int addr_resolve(const char *address, IPAny *ip) +int addr_resolve(const char *address, IP *to) { + if (!address || !to) + return 0; + + sa_family_t family; +#ifdef TOX_ENABLE_IPV6 + family = to->family; +#else + family = AF_INET; +#endif + struct addrinfo *server = NULL; struct addrinfo *walker = NULL; struct addrinfo hints; int rc; memset(&hints, 0, sizeof(hints)); - hints.ai_family = ip->family; + hints.ai_family = family; hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses. #ifdef __WIN32__ @@ -385,31 +639,40 @@ int addr_resolve(const char *address, IPAny *ip) return 0; } +#ifdef TOX_ENABLE_IPV6 IP4 ip4; memset(&ip4, 0, sizeof(ip4)); IP6 ip6; memset(&ip6, 0, sizeof(ip6)); +#endif walker = server; while (walker && (rc != 3)) { - if (ip->family != AF_UNSPEC) { - if (walker->ai_family == ip->family) { - if (ip->family == AF_INET) { + if (family != AF_UNSPEC) { + if (walker->ai_family == family) { + if (family == AF_INET) { if (walker->ai_addrlen == sizeof(struct sockaddr_in)) { struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; - ip->ip4.in_addr = addr->sin_addr; +#ifdef TOX_ENABLE_IPV6 + to->ip4.in_addr = addr->sin_addr; +#else + to->in_addr = addr->sin_addr; +#endif rc = 3; } } - else if (ip->family == AF_INET6) { +#ifdef TOX_ENABLE_IPV6 + else if (family == AF_INET6) { if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; - ip->ip6 = addr->sin6_addr; + to->ip6 = addr->sin6_addr; rc = 3; } } +#endif } } +#ifdef TOX_ENABLE_IPV6 else { if (walker->ai_family == AF_INET) { if (walker->ai_addrlen == sizeof(struct sockaddr_in)) { @@ -426,22 +689,25 @@ int addr_resolve(const char *address, IPAny *ip) } } } +#endif walker = walker->ai_next; } - if (ip->family == AF_UNSPEC) { +#ifdef TOX_ENABLE_IPV6 + if (to->family == AF_UNSPEC) { if (rc & 2) { - ip->family = AF_INET6; - ip->ip6 = ip6; + to->family = AF_INET6; + to->ip6 = ip6; } else if (rc & 1) { - ip->family = AF_INET; - ip->ip4 = ip4; + to->family = AF_INET; + to->ip4 = ip4; } else rc = 0; } +#endif freeaddrinfo(server); @@ -458,7 +724,7 @@ int addr_resolve(const char *address, IPAny *ip) * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6) * returns 1 on success, 0 on failure */ -int addr_resolve_or_parse_ip(const char *address, IPAny *to) +int addr_resolve_or_parse_ip(const char *address, IP *to) { if (!addr_resolve(address, to)) if (!addr_parse_ip(address, to)) diff --git a/toxcore/network.h b/toxcore/network.h index 913763ee..0d31ffac 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -101,12 +101,6 @@ typedef struct { }; } IPAny; -/* ipany_ntoa - * converts ip into a string - * uses a static buffer, so mustn't used multiple times in the same output - */ -const char *ipany_ntoa(IPAny *ip); - typedef union { struct { IP4 ip; @@ -124,29 +118,43 @@ typedef struct { uint16_t port; } IPAny_Port; -#ifdef NETWORK_IP_PORT_IS_IPV6 +#undef TOX_ENABLE_IPV6 +#ifdef TOX_ENABLE_IPV6 +#define TOX_ENABLE_IPV6_DEFAULT 1 +typedef IPAny IP; typedef IPAny_Port IP_Port; #else +#define TOX_ENABLE_IPV6_DEFAULT 0 +typedef IP4 IP; typedef IP4_Port IP_Port; #endif +/* ip_ntoa + * converts ip into a string + * uses a static buffer, so mustn't used multiple times in the same output + */ +const char *ip_ntoa(IP *ip); + /* ipport_equal * compares two IPAny_Port structures * unset means unequal * * returns 0 when not equal or when uninitialized */ -int ipport_equal(IPAny_Port *a, IPAny_Port *b); +int ipport_equal(IP_Port *a, IP_Port *b); -typedef struct { - int16_t family; - uint16_t port; - IP4 ip; - uint8_t zeroes[8]; -#ifdef ENABLE_IPV6 - uint8_t zeroes2[12]; -#endif -} ADDR; +/* nulls out ip */ +void ip_reset(IP *ip); +/* nulls out ip, sets family according to flag */ +void ip_init(IP *ip, uint8_t ipv6enabled); +/* checks if ip is valid */ +int ip_isset(IP *ip); +/* checks if ip is valid */ +int ipport_isset(IP_Port *ipport); +/* copies an ip structure */ +void ip_copy(IP *target, IP *source); +/* copies an ip_port structure */ +void ipport_copy(IP_Port *target, IP_Port *source); /* * addr_resolve_or_parse_ip @@ -155,7 +163,7 @@ typedef struct { * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6) * returns 1 on success, 0 on failure */ -int addr_resolve_or_parse_ip(const char *address, IPAny *to); +int addr_resolve_or_parse_ip(const char *address, IP *to); /* Function to receive data, ip and port of sender is put into ip_port. * Packet data is put into data. @@ -204,7 +212,7 @@ void networking_poll(Networking_Core *net); * return 0 if no problems. * return -1 if there were problems. */ -Networking_Core *new_networking(IP4 ip, uint16_t port); +Networking_Core *new_networking(IP ip, uint16_t port); /* Function to cleanup networking stuff (doesn't do much right now). */ void kill_networking(Networking_Core *net); diff --git a/toxcore/ping.c b/toxcore/ping.c index 5f405b52..49e0dba9 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -100,7 +100,8 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl { PING *png = ping; - if (ipp.ip.uint32 == 0 && ping_id == 0) + /* shouldn't that be an OR ? */ + if (!ip_isset(&ipp.ip) && ping_id == 0) return false; size_t i, id; @@ -111,7 +112,8 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl id = (png->pos_pings + i) % PING_NUM_MAX; /* ping_id = 0 means match any id. */ - if ((ipp_eq(png->pings[id].ipp, ipp) || ipp.ip.uint32 == 0) && (png->pings[id].id == ping_id || ping_id == 0)) { + if ((!ip_isset(&ipp.ip) || ipport_equal(&png->pings[id].ipp, &ipp)) && + (png->pings[id].id == ping_id || ping_id == 0)) { return true; } } diff --git a/toxcore/tox.c b/toxcore/tox.c index e37eac3e..6417b16a 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -374,10 +374,11 @@ void tox_bootstrap(void *tox, IP_Port ip_port, uint8_t *public_key) Messenger *m = tox; DHT_bootstrap(m->dht, ip_port, public_key); } -void tox_bootstrap_ex(void *tox, const char *address, uint16_t port, uint8_t *public_key) +void tox_bootstrap_ex(void *tox, const char *address, uint8_t ipv6enabled, + uint16_t port, uint8_t *public_key) { Messenger *m = tox; - DHT_bootstrap_ex(m->dht, address, port, public_key); + DHT_bootstrap_ex(m->dht, address, ipv6enabled, port, public_key); }; /* return 0 if we are not connected to the DHT. diff --git a/toxcore/tox.h b/toxcore/tox.h index f8d7975f..44eba081 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -36,21 +36,51 @@ extern "C" { #define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) - typedef union { uint8_t c[4]; uint16_t s[2]; uint32_t i; -} tox_IP; +} tox_IP4; + + +typedef struct in6_addr tox_IP6; typedef struct { - tox_IP ip; - uint16_t port; - /* Not used for anything right now. */ - uint16_t padding; -} tox_IP_Port; + sa_family_t family; + union { + tox_IP4 ip4; + tox_IP6 ip6; + }; +} tox_IPAny; + +typedef union { + struct { + tox_IP4 ip; + uint16_t port; + /* Not used for anything right now. */ + uint16_t padding; + }; + uint8_t uint8[8]; +} tox_IP4_Port; + +/* will replace IP_Port as soon as the complete infrastructure is in place + * removed the unused union and padding also */ +typedef struct { + tox_IPAny ip; + uint16_t port; +} tox_IPAny_Port; + +#undef TOX_ENABLE_IPV6 +#ifdef TOX_ENABLE_IPV6 +#define TOX_ENABLE_IPV6_DEFAULT 1 +typedef tox_IPAny tox_IP; +typedef tox_IPAny_Port tox_IP_Port; +#else +#define TOX_ENABLE_IPV6_DEFAULT 0 +typedef tox_IP4 tox_IP; +typedef tox_IP4_Port tox_IP_Port; +#endif -#define TOX_IP_IS_IPV6 0 /* Errors for m_addfriend * FAERR - Friend Add Error @@ -296,7 +326,8 @@ void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uin * tox_bootstrap_ex converts the address into an IP_Port structure internally */ void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); -void tox_bootstrap_ex(Tox *tox, const char *address, uint16_t port, uint8_t *public_key); +void tox_bootstrap_ex(Tox *tox, const char *address, uint8_t ipv6enabled, + uint16_t port, uint8_t *public_key); /* return 0 if we are not connected to the DHT. * return 1 if we are. diff --git a/toxcore/util.c b/toxcore/util.c index 1728ea21..ff366a07 100644 --- a/toxcore/util.c +++ b/toxcore/util.c @@ -32,11 +32,6 @@ uint64_t random_64b() return r; } -bool ipp_eq(IP_Port a, IP_Port b) -{ - return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port); -} - bool id_eq(uint8_t *dest, uint8_t *src) { return memcmp(dest, src, CLIENT_ID_SIZE) == 0; diff --git a/toxcore/util.h b/toxcore/util.h index 90a3c8e4..7dea3eac 100644 --- a/toxcore/util.h +++ b/toxcore/util.h @@ -7,6 +7,5 @@ uint64_t now(); uint64_t random_64b(); -bool ipp_eq(IP_Port a, IP_Port b); bool id_eq(uint8_t *dest, uint8_t *src); void id_cpy(uint8_t *dest, uint8_t *src);