summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--other/DHT_bootstrap.c13
-rw-r--r--other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c9
-rw-r--r--testing/DHT_test.c33
-rw-r--r--testing/Lossless_UDP_testclient.c16
-rw-r--r--testing/Lossless_UDP_testserver.c8
-rw-r--r--testing/Messenger_test.c5
-rw-r--r--testing/nTox.c19
-rw-r--r--toxcore/DHT.c116
-rw-r--r--toxcore/DHT.h25
-rw-r--r--toxcore/LAN_discovery.c85
-rw-r--r--toxcore/Lossless_UDP.c52
-rw-r--r--toxcore/Lossless_UDP.h6
-rw-r--r--toxcore/Messenger.c15
-rw-r--r--toxcore/friend_requests.c10
-rw-r--r--toxcore/group_chats.c2
-rw-r--r--toxcore/net_crypto.c2
-rw-r--r--toxcore/network.c332
-rw-r--r--toxcore/network.h48
-rw-r--r--toxcore/ping.c6
-rw-r--r--toxcore/tox.c5
-rw-r--r--toxcore/tox.h47
-rw-r--r--toxcore/util.c5
-rw-r--r--toxcore/util.h1
23 files changed, 625 insertions, 235 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)
81 81
82int main(int argc, char *argv[]) 82int main(int argc, char *argv[])
83{ 83{
84 /* let use decide by cmdline: TODO */
85 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
86
84 /* Initialize networking - 87 /* Initialize networking -
85 Bind to ip 0.0.0.0:PORT */ 88 Bind to ip 0.0.0.0:PORT */
86 IP4 ip; 89 IP ip;
87 ip.uint32 = 0; 90 ip_init(&ip, ipv6enabled);
91
88 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); 92 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
89 manage_keys(dht); 93 manage_keys(dht);
90 printf("Public key: "); 94 printf("Public key: ");
@@ -110,11 +114,8 @@ int main(int argc, char *argv[])
110 114
111 if (argc > 3) { 115 if (argc > 3) {
112 printf("Trying to bootstrap into the network...\n"); 116 printf("Trying to bootstrap into the network...\n");
113 IP_Port bootstrap_info;
114 bootstrap_info.ip.uint32 = inet_addr(argv[1]);
115 bootstrap_info.port = htons(atoi(argv[2]));
116 uint8_t *bootstrap_key = hex_string_to_bin(argv[3]); 117 uint8_t *bootstrap_key = hex_string_to_bin(argv[3]);
117 DHT_bootstrap(dht, bootstrap_info, bootstrap_key); 118 DHT_bootstrap_ex(dht, argv[1], ipv6enabled, htons(atoi(argv[2])), bootstrap_key);
118 free(bootstrap_key); 119 free(bootstrap_key);
119 } 120 }
120 121
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)
301 printf("bootstrap_server %d: Invalid port.\n", i); 301 printf("bootstrap_server %d: Invalid port.\n", i);
302 } 302 }
303 303
304#ifdef TOX_ENABLE_IPV6
305 server_conf.info[i].conn.ip.family = AF_INET;
306 server_conf.info[i].conn.ip.ip4.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip));
307#else
304 server_conf.info[i].conn.ip.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip)); 308 server_conf.info[i].conn.ip.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip));
309#endif
305 server_conf.info[i].conn.port = htons(bs_port); 310 server_conf.info[i].conn.port = htons(bs_port);
306 b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p); 311 b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p);
307 } 312 }
@@ -339,8 +344,8 @@ int main(int argc, char *argv[])
339 344
340 /* Initialize networking 345 /* Initialize networking
341 bind to ip 0.0.0.0:PORT */ 346 bind to ip 0.0.0.0:PORT */
342 IP4 ip; 347 IP ip;
343 ip.uint32 = 0; 348 ip_init(&ip, 0);
344 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port))); 349 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port)));
345 /* Read the config file */ 350 /* Read the config file */
346 printf("PID file: %s\n", server_conf.pid_file); 351 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)
66 } 66 }
67 67
68 p_ip = dht->close_clientlist[i].ip_port; 68 p_ip = dht->close_clientlist[i].ip_port;
69 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], 69 printf("\nIP: %s Port: %u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port));
70 ntohs(p_ip.port));
71 printf("\nTimestamp: %llu", (long long unsigned int) dht->close_clientlist[i].timestamp); 70 printf("\nTimestamp: %llu", (long long unsigned int) dht->close_clientlist[i].timestamp);
72 printf("\nLast pinged: %llu\n", (long long unsigned int) dht->close_clientlist[i].last_pinged); 71 printf("\nLast pinged: %llu\n", (long long unsigned int) dht->close_clientlist[i].last_pinged);
73 p_ip = dht->close_clientlist[i].ret_ip_port; 72 p_ip = dht->close_clientlist[i].ret_ip_port;
74 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], 73 printf("OUR IP: %s Port: %u\n", ip_ntoa(&p_ip.ip), ntohs(p_ip.port));
75 ntohs(p_ip.port));
76 printf("Timestamp: %llu\n", (long long unsigned int) dht->close_clientlist[i].ret_timestamp); 74 printf("Timestamp: %llu\n", (long long unsigned int) dht->close_clientlist[i].ret_timestamp);
77 } 75 }
78} 76}
@@ -91,9 +89,8 @@ void print_friendlist(DHT *dht)
91 printf("%c", dht->friends_list[k].client_id[j]); 89 printf("%c", dht->friends_list[k].client_id[j]);
92 } 90 }
93 91
94 p_ip = DHT_getfriendip(dht, dht->friends_list[k].client_id); 92 int friendok = DHT_getfriendip(dht, dht->friends_list[k].client_id, &p_ip);
95 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], 93 printf("\nIP: %s:%u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port));
96 ntohs(p_ip.port));
97 94
98 printf("\nCLIENTS IN LIST:\n\n"); 95 printf("\nCLIENTS IN LIST:\n\n");
99 96
@@ -108,13 +105,11 @@ void print_friendlist(DHT *dht)
108 } 105 }
109 106
110 p_ip = dht->friends_list[k].client_list[i].ip_port; 107 p_ip = dht->friends_list[k].client_list[i].ip_port;
111 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], 108 printf("\nIP: %s:%u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port));
112 ntohs(p_ip.port));
113 printf("\nTimestamp: %llu", (long long unsigned int) dht->friends_list[k].client_list[i].timestamp); 109 printf("\nTimestamp: %llu", (long long unsigned int) dht->friends_list[k].client_list[i].timestamp);
114 printf("\nLast pinged: %llu\n", (long long unsigned int) dht->friends_list[k].client_list[i].last_pinged); 110 printf("\nLast pinged: %llu\n", (long long unsigned int) dht->friends_list[k].client_list[i].last_pinged);
115 p_ip = dht->friends_list[k].client_list[i].ret_ip_port; 111 p_ip = dht->friends_list[k].client_list[i].ret_ip_port;
116 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], 112 printf("ret IP: %s:%u\n", ip_ntoa(&p_ip.ip), ntohs(p_ip.port));
117 ntohs(p_ip.port));
118 printf("Timestamp: %llu\n", (long long unsigned int)dht->friends_list[k].client_list[i].ret_timestamp); 113 printf("Timestamp: %llu\n", (long long unsigned int)dht->friends_list[k].client_list[i].ret_timestamp);
119 } 114 }
120 } 115 }
@@ -138,11 +133,14 @@ void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port)
138 133
139int main(int argc, char *argv[]) 134int main(int argc, char *argv[])
140{ 135{
136 /* let use decide by cmdline: TODO */
137 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
138
141 //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); 139 //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32);
142 /* initialize networking */ 140 /* initialize networking */
143 /* bind to ip 0.0.0.0:PORT */ 141 /* bind to ip 0.0.0.0:PORT */
144 IP4 ip; 142 IP ip;
145 ip.uint32 = 0; 143 ip_init(&ip, ipv6enabled);
146 144
147 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); 145 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
148 146
@@ -172,14 +170,7 @@ int main(int argc, char *argv[])
172 170
173 171
174 perror("Initialization"); 172 perror("Initialization");
175 IP_Port bootstrap_ip_port; 173 DHT_bootstrap_ex(dht, argv[1], ipv6enabled, htons(atoi(argv[2])), hex_string_to_bin(argv[3]));
176 bootstrap_ip_port.port = htons(atoi(argv[2]));
177 /* bootstrap_ip_port.ip.c[0] = 127;
178 * bootstrap_ip_port.ip.c[1] = 0;
179 * bootstrap_ip_port.ip.c[2] = 0;
180 * bootstrap_ip_port.ip.c[3] = 1; */
181 bootstrap_ip_port.ip.uint32 = inet_addr(argv[1]);
182 DHT_bootstrap(dht, bootstrap_ip_port, hex_string_to_bin(argv[3]));
183 174
184 /* 175 /*
185 IP_Port ip_port; 176 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)
66 66
67void printip(IP_Port ip_port) 67void printip(IP_Port ip_port)
68{ 68{
69 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], 69 printf("\nIP: %s Port: %u", ip_ntoa(&ip_port.ip), ntohs(ip_port.port));
70 ntohs(ip_port.port));
71} 70}
72/* 71/*
73void printpackets(Data test) 72void printpackets(Data test)
@@ -152,6 +151,9 @@ void printconnection(int connection_id)
152 151
153int main(int argc, char *argv[]) 152int main(int argc, char *argv[])
154{ 153{
154 /* let use decide by cmdline: TODO */
155 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
156
155 if (argc < 4) { 157 if (argc < 4) {
156 printf("usage: %s ip port filename\n", argv[0]); 158 printf("usage: %s ip port filename\n", argv[0]);
157 exit(0); 159 exit(0);
@@ -168,14 +170,18 @@ int main(int argc, char *argv[])
168 170
169 /* initialize networking */ 171 /* initialize networking */
170 /* bind to ip 0.0.0.0:PORT */ 172 /* bind to ip 0.0.0.0:PORT */
171 IP4 ip; 173 IP ip;
172 ip.uint32 = 0; 174 ip_init(&ip, ipv6enabled);
175
173 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); 176 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT));
174 perror("Initialization"); 177 perror("Initialization");
178
175 IP_Port serverip; 179 IP_Port serverip;
176 serverip.ip.uint32 = inet_addr(argv[1]); 180 ip_init(&serverip.ip, ipv6enabled);
181 addr_resolve(argv[1], &serverip.ip);
177 serverip.port = htons(atoi(argv[2])); 182 serverip.port = htons(atoi(argv[2]));
178 printip(serverip); 183 printip(serverip);
184
179 int connection = new_connection(ludp, serverip); 185 int connection = new_connection(ludp, serverip);
180 uint64_t timer = current_time(); 186 uint64_t timer = current_time();
181 187
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)
147 147
148int main(int argc, char *argv[]) 148int main(int argc, char *argv[])
149{ 149{
150 /* let use decide by cmdline: TODO */
151 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
152
150 if (argc < 2) { 153 if (argc < 2) {
151 printf("usage: %s filename\n", argv[0]); 154 printf("usage: %s filename\n", argv[0]);
152 exit(0); 155 exit(0);
@@ -163,8 +166,9 @@ int main(int argc, char *argv[])
163 166
164 //initialize networking 167 //initialize networking
165 //bind to ip 0.0.0.0:PORT 168 //bind to ip 0.0.0.0:PORT
166 IP4 ip; 169 IP ip;
167 ip.uint32 = 0; 170 ip_init(&ip, ipv6enabled);
171
168 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); 172 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT));
169 perror("Initialization"); 173 perror("Initialization");
170 174
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[])
101 } 101 }
102 102
103 /* IPv6: maybe allow from cmdline --ipv6? sticking to IPv4 for now */ 103 /* IPv6: maybe allow from cmdline --ipv6? sticking to IPv4 for now */
104 m = initMessenger(0); 104 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
105 m = initMessenger(ipv6enabled);
105 106
106 if ( !m ) { 107 if ( !m ) {
107 fputs("Failed to allocate messenger datastructure\n", stderr); 108 fputs("Failed to allocate messenger datastructure\n", stderr);
@@ -110,7 +111,7 @@ int main(int argc, char *argv[])
110 111
111 if (argc > 3) { 112 if (argc > 3) {
112 uint16_t port = htons(atoi(argv[2])); 113 uint16_t port = htons(atoi(argv[2]));
113 DHT_bootstrap_ex(m->dht, argv[1], port, hex_string_to_bin(argv[3])); 114 DHT_bootstrap_ex(m->dht, argv[1], ipv6enabled, port, hex_string_to_bin(argv[3]));
114 } else { 115 } else {
115 FILE *file = fopen(argv[1], "rb"); 116 FILE *file = fopen(argv[1], "rb");
116 117
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)
537 537
538int main(int argc, char *argv[]) 538int main(int argc, char *argv[])
539{ 539{
540 /* let use decide by cmdline: TODO */
541 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
542
540 int on = 0; 543 int on = 0;
541 int c = 0; 544 int c = 0;
542 int i = 0; 545 int i = 0;
@@ -566,7 +569,7 @@ int main(int argc, char *argv[])
566 } 569 }
567 } 570 }
568 571
569 m = tox_new(); 572 m = tox_new_ex(ipv6enabled);
570 573
571 if ( !m ) { 574 if ( !m ) {
572 fputs("Failed to allocate Messenger datastructure", stderr); 575 fputs("Failed to allocate Messenger datastructure", stderr);
@@ -590,20 +593,12 @@ int main(int argc, char *argv[])
590 new_lines(idstring); 593 new_lines(idstring);
591 strcpy(line, ""); 594 strcpy(line, "");
592 595
593 tox_IP_Port bootstrap_ip_port; 596 uint16_t port = htons(atoi(argv[2]));
594 bootstrap_ip_port.port = htons(atoi(argv[2]));
595 int resolved_address = resolve_addr(argv[1]);
596
597 if (resolved_address != 0)
598 bootstrap_ip_port.ip.i = resolved_address;
599 else
600 exit(1);
601
602 unsigned char *binary_string = hex_string_to_bin(argv[3]); 597 unsigned char *binary_string = hex_string_to_bin(argv[3]);
603 tox_bootstrap(m, bootstrap_ip_port, binary_string); 598 tox_bootstrap_ex(m, argv[1], ipv6enabled, port, binary_string);
604 free(binary_string); 599 free(binary_string);
605 nodelay(stdscr, TRUE);
606 600
601 nodelay(stdscr, TRUE);
607 while (1) { 602 while (1) {
608 if (on == 0 && tox_isconnected(m)) { 603 if (on == 0 && tox_isconnected(m)) {
609 new_lines("[i] connected to DHT\n[i] define username with /n"); 604 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)
115 return c; 115 return c;
116} 116}
117 117
118static int ip4port_equal(IP_Port a, IP_Port b)
119{
120 return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port);
121}
122
123static int id_equal(uint8_t *a, uint8_t *b) 118static int id_equal(uint8_t *a, uint8_t *b)
124{ 119{
125 return memcmp(a, b, CLIENT_ID_SIZE) == 0; 120 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
144 139
145 for (i = 0; i < length; ++i) { 140 for (i = 0; i < length; ++i) {
146 /* If ip_port is assigned to a different client_id replace it */ 141 /* If ip_port is assigned to a different client_id replace it */
147 if (ip4port_equal(list[i].ip_port, ip_port)) { 142 if (ipport_equal(&list[i].ip_port, &ip_port)) {
148 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 143 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
149 } 144 }
150 145
151 if (id_equal(list[i].client_id, client_id)) { 146 if (id_equal(list[i].client_id, client_id)) {
152 /* Refresh the client timestamp. */ 147 /* Refresh the client timestamp. */
153 list[i].timestamp = temp_time; 148 list[i].timestamp = temp_time;
154 list[i].ip_port.ip.uint32 = ip_port.ip.uint32; 149 ipport_copy(&list[i].ip_port, &ip_port);
155 list[i].ip_port.port = ip_port.port;
156 return 1; 150 return 1;
157 } 151 }
158 } 152 }
@@ -216,7 +210,7 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list
216 * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the 210 * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the
217 * partner node understands - that's true if *they* are on IPv6 211 * partner node understands - that's true if *they* are on IPv6
218 */ 212 */
219#ifdef NETWORK_IP_PORT_IS_IPV6 213#ifdef TOX_ENABLE_IPV6
220 ipv46x = 0; 214 ipv46x = 0;
221 if (sa_family == AF_INET) 215 if (sa_family == AF_INET)
222 ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET; 216 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
266 MAX_SENT_NODES, 260 MAX_SENT_NODES,
267 dht->friends_list[i].client_list[j].client_id); 261 dht->friends_list[i].client_list[j].client_id);
268 262
269#ifdef NETWORK_IP_PORT_IS_IPV6 263#ifdef TOX_ENABLE_IPV6
270 ipv46x = 0; 264 ipv46x = 0;
271 if (sa_family == AF_INET) 265 if (sa_family == AF_INET)
272 ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET; 266 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,
330 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 324 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
331 list[i].ip_port = ip_port; 325 list[i].ip_port = ip_port;
332 list[i].timestamp = temp_time; 326 list[i].timestamp = temp_time;
333 list[i].ret_ip_port.ip.uint32 = 0; 327 ip_reset(&list[i].ret_ip_port.ip);
334 list[i].ret_ip_port.port = 0; 328 list[i].ret_ip_port.port = 0;
335 list[i].ret_timestamp = 0; 329 list[i].ret_timestamp = 0;
336 return 0; 330 return 0;
@@ -378,7 +372,7 @@ static int replace_good( Client_data *list,
378 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 372 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
379 list[i].ip_port = ip_port; 373 list[i].ip_port = ip_port;
380 list[i].timestamp = temp_time; 374 list[i].timestamp = temp_time;
381 list[i].ret_ip_port.ip.uint32 = 0; 375 ip_reset(&list[i].ret_ip_port.ip);
382 list[i].ret_ip_port.port = 0; 376 list[i].ret_ip_port.port = 0;
383 list[i].ret_timestamp = 0; 377 list[i].ret_timestamp = 0;
384 return 0; 378 return 0;
@@ -476,13 +470,13 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id)
476 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { 470 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) {
477 pinging = 0; 471 pinging = 0;
478 472
479 if (ip_port.ip.uint32 != 0 && ip4port_equal(dht->send_nodes[i].ip_port, ip_port)) 473 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id)
480 ++pinging; 474 ++pinging;
481 475
482 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) 476 if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port))
483 ++pinging; 477 ++pinging;
484 478
485 if (pinging == (ping_id != 0) + (ip_port.ip.uint32 != 0)) 479 if (pinging == (ping_id != 0) + (ip_isset(&ip_port.ip) != 0))
486 return 1; 480 return 1;
487 } 481 }
488 } 482 }
@@ -575,11 +569,11 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
575 random_nonce(nonce); 569 random_nonce(nonce);
576 570
577 memcpy(plain, &ping_id, sizeof(ping_id)); 571 memcpy(plain, &ping_id, sizeof(ping_id));
578#if DHT_NODEFORMAT == 46 572#ifdef TOX_ENABLE_IPV6
579 Node4_format *nodes4_list = &(plain + sizeof(ping_id)); 573 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
580 int i, num_nodes_ok = 0; 574 int i, num_nodes_ok = 0;
581 for(i = 0; i < num_nodes, i++) 575 for(i = 0; i < num_nodes; i++)
582 if (nodes_list[i].ip.family == AF_INET) { 576 if (nodes_list[i].ip_port.ip.family == AF_INET) {
583 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); 577 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
584 nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32; 578 nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32;
585 nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; 579 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
680 if (!is_gettingnodes(dht, source, ping_id)) 674 if (!is_gettingnodes(dht, source, ping_id))
681 return 1; 675 return 1;
682 676
677 uint32_t i;
683 Node_format nodes_list[MAX_SENT_NODES]; 678 Node_format nodes_list[MAX_SENT_NODES];
684 679
685#if DHT_NODEFORMAT == 46 680#ifdef TOX_ENABLE_IPV6
686 Node4_format *nodes4_list = &(plain + sizeof(ping_id)); 681 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
687 682
688 int i, num_nodes_ok = 0; 683 int num_nodes_ok = 0;
689 for(i = 0; i < num_nodes, i++) 684 for(i = 0; i < num_nodes; i++)
690 if ((nodes_list[i].ip != 0) && (nodes_list[i].ip != ~0)) { 685 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) {
691 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); 686 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
692 nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; 687 nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET;
693 nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; 688 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
706 701
707 addto_lists(dht, source, packet + 1); 702 addto_lists(dht, source, packet + 1);
708 703
709 uint32_t i;
710
711 for (i = 0; i < num_nodes; ++i) { 704 for (i = 0; i < num_nodes; ++i) {
712 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); 705 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id);
713 returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); 706 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)
775} 768}
776 769
777/* TODO: Optimize this. */ 770/* TODO: Optimize this. */
778IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id) 771int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port)
779{ 772{
780 uint32_t i, j; 773 uint32_t i, j;
781 uint64_t temp_time = unix_time(); 774 uint64_t temp_time = unix_time();
782 IP_Port empty = {{{{0}}, 0, 0}}; 775
776 ip_reset(&ip_port->ip);
777 ip_port->port = 0;
783 778
784 for (i = 0; i < dht->num_friends; ++i) { 779 for (i = 0; i < dht->num_friends; ++i) {
785 /* Equal */ 780 /* Equal */
786 if (id_equal(dht->friends_list[i].client_id, client_id)) { 781 if (id_equal(dht->friends_list[i].client_id, client_id)) {
787 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 782 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
788 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) 783 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id)
789 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) 784 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) {
790 return dht->friends_list[i].client_list[j].ip_port; 785 *ip_port = dht->friends_list[i].client_list[j].ip_port;
786 return 1;
787 }
791 } 788 }
792 789
793 return empty; 790 return 0;
794 } 791 }
795 } 792 }
796 793
797 empty.ip.uint32 = 1; 794 return -1;
798 return empty;
799} 795}
800 796
801/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request 797/* 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)
880 getnodes(dht, ip_port, public_key, dht->c->self_public_key); 876 getnodes(dht, ip_port, public_key, dht->c->self_public_key);
881 send_ping_request(dht->ping, dht->c, ip_port, public_key); 877 send_ping_request(dht->ping, dht->c, ip_port, public_key);
882} 878}
883void DHT_bootstrap_ex(DHT *dht, const char *address, uint16_t port, uint8_t *public_key) 879void DHT_bootstrap_ex(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key)
884{ 880{
885 IPAny_Port ipany_port; 881 IP_Port ip_port;
886 ipany_port.ip.family = AF_INET; 882 ip_init(&ip_port.ip, ipv6enabled);
887 if (addr_resolve_or_parse_ip(address, &ipany_port.ip)) { 883 if (addr_resolve_or_parse_ip(address, &ip_port.ip)) {
888 /* IPAny temporary: copy down */
889 IP_Port ip_port;
890 ip_port.ip.uint32 = ipany_port.ip.ip4.uint32;
891 ip_port.port = port; 884 ip_port.port = port;
892
893 DHT_bootstrap(dht, ip_port, public_key); 885 DHT_bootstrap(dht, ip_port, public_key);
894 } 886 }
895} 887}
@@ -933,7 +925,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
933 client = &friend->client_list[i]; 925 client = &friend->client_list[i];
934 926
935 /* If ip is not zero and node is good. */ 927 /* If ip is not zero and node is good. */
936 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 928 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
937 929
938 if (id_equal(client->client_id, friend->client_id)) 930 if (id_equal(client->client_id, friend->client_id))
939 return 0; 931 return 0;
@@ -975,7 +967,7 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt
975 client = &friend->client_list[i]; 967 client = &friend->client_list[i];
976 968
977 /* If ip is not zero and node is good. */ 969 /* If ip is not zero and node is good. */
978 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 970 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
979 int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length); 971 int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length);
980 972
981 if ((unsigned int)retval == length) 973 if ((unsigned int)retval == length)
@@ -1009,7 +1001,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
1009 client = &friend->client_list[i]; 1001 client = &friend->client_list[i];
1010 1002
1011 /* If ip is not zero and node is good. */ 1003 /* If ip is not zero and node is good. */
1012 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1004 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
1013 ip_list[n] = client->ip_port; 1005 ip_list[n] = client->ip_port;
1014 ++n; 1006 ++n;
1015 } 1007 }
@@ -1115,9 +1107,10 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey,
1115 * 1107 *
1116 * return ip of 0 if failure. 1108 * return ip of 0 if failure.
1117 */ 1109 */
1118static IP4 NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) 1110static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1119{ 1111{
1120 IP4 zero = {{0}}; 1112 IP zero;
1113 ip_reset(&zero);
1121 1114
1122 if (len > MAX_FRIEND_CLIENTS) 1115 if (len > MAX_FRIEND_CLIENTS)
1123 return zero; 1116 return zero;
@@ -1127,7 +1120,7 @@ static IP4 NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1127 1120
1128 for (i = 0; i < len; ++i) { 1121 for (i = 0; i < len; ++i) {
1129 for (j = 0; j < len; ++j) { 1122 for (j = 0; j < len; ++j) {
1130 if (ip_portlist[i].ip.uint32 == ip_portlist[j].ip.uint32) 1123 if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip))
1131 ++numbers[i]; 1124 ++numbers[i];
1132 } 1125 }
1133 1126
@@ -1144,13 +1137,13 @@ static IP4 NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1144 * 1137 *
1145 * return number of ports and puts the list of ports in portlist. 1138 * return number of ports and puts the list of ports in portlist.
1146 */ 1139 */
1147static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP4 ip) 1140static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip)
1148{ 1141{
1149 uint32_t i; 1142 uint32_t i;
1150 uint16_t num = 0; 1143 uint16_t num = 0;
1151 1144
1152 for (i = 0; i < len; ++i) { 1145 for (i = 0; i < len; ++i) {
1153 if (ip_portlist[i].ip.uint32 == ip.uint32) { 1146 if (ip_equal(&ip_portlist[i].ip, &ip)) {
1154 portlist[num] = ntohs(ip_portlist[i].port); 1147 portlist[num] = ntohs(ip_portlist[i].port);
1155 ++num; 1148 ++num;
1156 } 1149 }
@@ -1159,7 +1152,7 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t
1159 return num; 1152 return num;
1160} 1153}
1161 1154
1162static void punch_holes(DHT *dht, IP4 ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) 1155static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num)
1163{ 1156{
1164 if (numports > MAX_FRIEND_CLIENTS || numports == 0) 1157 if (numports > MAX_FRIEND_CLIENTS || numports == 0)
1165 return; 1158 return;
@@ -1170,7 +1163,9 @@ static void punch_holes(DHT *dht, IP4 ip, uint16_t *port_list, uint16_t numports
1170 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { 1163 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) {
1171 /* TODO: Improve port guessing algorithm. */ 1164 /* TODO: Improve port guessing algorithm. */
1172 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); 1165 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1);
1173 IP_Port pinging = {{ip, htons(port), 0}}; 1166 IP_Port pinging;
1167 ip_copy(&pinging.ip, &ip);
1168 pinging.port = htons(port);
1174 send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); 1169 send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id);
1175 } 1170 }
1176 1171
@@ -1199,9 +1194,8 @@ static void do_NAT(DHT *dht)
1199 dht->friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && 1194 dht->friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time &&
1200 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { 1195 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
1201 1196
1202 IP4 ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 1197 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
1203 1198 if (!ip_isset(&ip))
1204 if (ip.uint32 == 0)
1205 continue; 1199 continue;
1206 1200
1207 uint16_t port_list[MAX_FRIEND_CLIENTS]; 1201 uint16_t port_list[MAX_FRIEND_CLIENTS];
@@ -1230,16 +1224,15 @@ static void do_NAT(DHT *dht)
1230 */ 1224 */
1231int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) 1225int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1232{ 1226{
1233 if (ip_port.ip.uint32 == 0) 1227 if (!ip_isset(&ip_port.ip))
1234 return -1; 1228 return -1;
1235 1229
1236 uint32_t i; 1230 uint32_t i;
1237 1231
1238 for (i = 0; i < MAX_TOPING; ++i) { 1232 for (i = 0; i < MAX_TOPING; ++i) {
1239 if (dht->toping[i].ip_port.ip.uint32 == 0) { 1233 if (!ip_isset(&dht->toping[i].ip_port.ip)) {
1240 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); 1234 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1241 dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; 1235 ipport_copy(&dht->toping[i].ip_port, &ip_port);
1242 dht->toping[i].ip_port.port = ip_port.port;
1243 return 0; 1236 return 0;
1244 } 1237 }
1245 } 1238 }
@@ -1247,8 +1240,7 @@ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1247 for (i = 0; i < MAX_TOPING; ++i) { 1240 for (i = 0; i < MAX_TOPING; ++i) {
1248 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { 1241 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) {
1249 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); 1242 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1250 dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; 1243 ipport_copy(&dht->toping[i].ip_port, &ip_port);
1251 dht->toping[i].ip_port.port = ip_port.port;
1252 return 0; 1244 return 0;
1253 } 1245 }
1254 } 1246 }
@@ -1270,11 +1262,11 @@ static void do_toping(DHT *dht)
1270 uint32_t i; 1262 uint32_t i;
1271 1263
1272 for (i = 0; i < MAX_TOPING; ++i) { 1264 for (i = 0; i < MAX_TOPING; ++i) {
1273 if (dht->toping[i].ip_port.ip.uint32 == 0) 1265 if (!ip_isset(&dht->toping[i].ip_port.ip))
1274 return; 1266 return;
1275 1267
1276 send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); 1268 send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id);
1277 dht->toping[i].ip_port.ip.uint32 = 0; 1269 ip_reset(&dht->toping[i].ip_port.ip);
1278 } 1270 }
1279} 1271}
1280 1272
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 {
83 83
84typedef struct { 84typedef struct {
85 uint8_t client_id[CLIENT_ID_SIZE]; 85 uint8_t client_id[CLIENT_ID_SIZE];
86 IPAny_Port ip_port; 86 IP_Port ip_port;
87} Node46_format; 87} Node46_format;
88/* IPAny temporary: change to 46 */ 88
89#define DHT_NODEFORMAT 4 89#ifdef TOX_ENABLE_IPV6
90typedef Node46_format Node_format;
91#else
90typedef Node4_format Node_format; 92typedef Node4_format Node_format;
91/* #define DHT_NODEFORMAT 46 */ 93#endif
92/* typedef Node46_format Node_format; */
93 94
94typedef struct { 95typedef struct {
95 IP_Port ip_port; 96 IP_Port ip_port;
@@ -135,11 +136,21 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id);
135 * ip must be 4 bytes long. 136 * ip must be 4 bytes long.
136 * port must be 2 bytes long. 137 * port must be 2 bytes long.
137 * 138 *
139 * !!! Signature changed!!!
140 *
141 * OLD: IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id);
142 *
138 * return ip if success. 143 * return ip if success.
139 * return ip of 0 if failure (This means the friend is either offline or we have not found him yet). 144 * return ip of 0 if failure (This means the friend is either offline or we have not found him yet).
140 * return ip of 1 if friend is not in list. 145 * return ip of 1 if friend is not in list.
146 *
147 * NEW: int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port);
148 *
149 * return -1, -- if client_id does NOT refer to a friend
150 * return 0, -- if client_id refers to a friend and we failed to find the friend (yet)
151 * return 1, ip if client_id refers to a friend and we found him
141 */ 152 */
142IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id); 153int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port);
143 154
144/* Run this function at least a couple times per second (It's the main loop). */ 155/* Run this function at least a couple times per second (It's the main loop). */
145void do_DHT(DHT *dht); 156void do_DHT(DHT *dht);
@@ -148,7 +159,7 @@ void do_DHT(DHT *dht);
148 * Sends a get nodes request to the given node with ip port and public_key. 159 * Sends a get nodes request to the given node with ip port and public_key.
149 */ 160 */
150void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); 161void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key);
151void DHT_bootstrap_ex(DHT *dht, const char *address, uint16_t port, uint8_t *public_key); 162void DHT_bootstrap_ex(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key);
152 163
153/* Add nodes to the toping list. 164/* Add nodes to the toping list.
154 * All nodes in this list are pinged every TIME_TOPING seconds 165 * 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
81#endif 81#endif
82 82
83/* Return the broadcast ip. */ 83/* Return the broadcast ip. */
84static IP4 broadcast_ip(void) 84static IP broadcast_ip(sa_family_t sa_family)
85{ 85{
86 IP4 ip; 86 IP ip;
87 ip.uint32 = ~0; 87 ip_reset(&ip);
88
89#ifdef TOX_ENABLE_IPV6
90 if (sa_family == AF_INET)
91 {
92 ip.family = AF_INET;
93 ip.ip4.uint32 = INADDR_BROADCAST;
94 }
95
96 if (sa_family == AF_INET6)
97 {
98 ip.family = AF_INET6;
99 /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
100 /* FE80::*: MUST be exact, for that we would need to look over all
101 * interfaces and check in which status they are */
102 ip.ip6.s6_addr[ 0] = 0xFF;
103 ip.ip6.s6_addr[ 1] = 0x02;
104 ip.ip6.s6_addr[15] = 0x01;
105 }
106#else
107 ip.uint32 = INADDR_BROADCAST;
108#endif
109
88 return ip; 110 return ip;
89} 111}
90 112
91/* return 0 if ip is a LAN ip. 113/* return 0 if ip is a LAN ip.
92 * return -1 if it is not. 114 * return -1 if it is not.
93 */ 115 */
94static int LAN_ip(IP4 ip) 116static int LAN_ip(IP ip)
95{ 117{
96 if (ip.uint8[0] == 127) /* Loopback. */ 118#ifdef TOX_ENABLE_IPV6
97 return 0; 119 if (ip.family == AF_INET) {
98 120 IP4 ip4 = ip.ip4;
99 if (ip.uint8[0] == 10) /* 10.0.0.0 to 10.255.255.255 range. */ 121#else
100 return 0; 122 IP4 ip4 = ip;
101 123#endif
102 if (ip.uint8[0] == 172 && ip.uint8[1] >= 16 && ip.uint8[1] <= 31) /* 172.16.0.0 to 172.31.255.255 range. */ 124 /* Loopback. */
103 return 0; 125 if (ip4.uint8[0] == 127)
104 126 return 0;
105 if (ip.uint8[0] == 192 && ip.uint8[1] == 168) /* 192.168.0.0 to 192.168.255.255 range. */ 127
106 return 0; 128 /* 10.0.0.0 to 10.255.255.255 range. */
107 129 if (ip4.uint8[0] == 10)
108 if (ip.uint8[0] == 169 && ip.uint8[1] == 254 && ip.uint8[2] != 0 130 return 0;
109 && ip.uint8[2] != 255)/* 169.254.1.0 to 169.254.254.255 range. */ 131
110 return 0; 132 /* 172.16.0.0 to 172.31.255.255 range. */
133 if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31)
134 return 0;
135
136 /* 192.168.0.0 to 192.168.255.255 range. */
137 if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168)
138 return 0;
139
140 /* 169.254.1.0 to 169.254.254.255 range. */
141 if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0
142 && ip4.uint8[2] != 255)
143 return 0;
144#ifdef TOX_ENABLE_IPV6
145 }
146 else if (ip.family == AF_INET6) {
147 /* autogenerated for each interface: FE80::* (up to FEBF::*)
148 /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
149 if (((ip.ip6.s6_addr[0] == 0xFF) && (ip.ip6.s6_addr[1] < 3) && (ip.ip6.s6_addr[15] == 1)) ||
150 ((ip.ip6.s6_addr[0] == 0xFE) && ((ip.ip6.s6_addr[1] & 0xC0) == 0x80)))
151 return 0;
152 }
153#endif
111 154
112 return -1; 155 return -1;
113} 156}
@@ -135,7 +178,9 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c)
135#ifdef __linux 178#ifdef __linux
136 send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); 179 send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES);
137#endif 180#endif
138 IP_Port ip_port = {{broadcast_ip(), port, 0}}; 181 IP_Port ip_port;
182 ip_port.ip = broadcast_ip(c->lossless_udp->net->family);
183 ip_port.port = port;
139 return sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); 184 return sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES);
140} 185}
141 186
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 @@
44int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) 44int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
45{ 45{
46 tox_array_for_each(&ludp->connections, Connection, tmp) { 46 tox_array_for_each(&ludp->connections, Connection, tmp) {
47 if (tmp->ip_port.ip.uint32 == ip_port.ip.uint32 && 47 if (tmp-> status > 0 && ipport_equal(&tmp->ip_port, &ip_port)) {
48 tmp->ip_port.port == ip_port.port &&
49 tmp->status > 0) {
50 return tmp_i; 48 return tmp_i;
51 } 49 }
52 } 50 }
@@ -61,17 +59,49 @@ int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
61 * 59 *
62 * TODO: make this better 60 * TODO: make this better
63 */ 61 */
64static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source) 62
63static uint8_t randtable_initget(Lossless_UDP *ludp, uint32_t index, uint8_t value)
65{ 64{
66 uint32_t id = 0, i; 65 if (ludp->randtable[index][value] == 0)
66 ludp->randtable[index][value] = random_int();
67 67
68 for (i = 0; i < 6; ++i) { 68 return ludp->randtable[index][value];
69 if (ludp->randtable[i][source.uint8[i]] == 0) 69}
70 ludp->randtable[i][source.uint8[i]] = random_int();
71 70
72 id ^= ludp->randtable[i][source.uint8[i]]; 71static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
72{
73 uint32_t id = 0, i = 0;
74
75 uint8_t *uint8;
76 uint8 = (uint8_t *)&source.port;
77 id ^= randtable_initget(ludp, i, *uint8);
78 i++, uint8++;
79 id ^= randtable_initget(ludp, i, *uint8);
80 i++;
81
82#ifdef TOX_ENABLE_IPV6
83 if (source.ip.family == AF_INET)
84 {
85 IP4 ip4 = source.ip.ip4;
86#else
87 IP4 ip4 = source.ip;
88#endif
89 int k;
90 for (k = 0; k < 4; k++) {
91 id ^= randtable_initget(ludp, i++, ip4.uint8[k]);
92 }
93#ifdef TOX_ENABLE_IPV6
73 } 94 }
74 95
96 if (source.ip.family == AF_INET6)
97 {
98 int k;
99 for (k = 0; k < 16; k++) {
100 id ^= randtable_initget(ludp, i++, source.ip.ip6.s6_addr[k]);
101 }
102 }
103#endif
104
75 /* id can't be zero. */ 105 /* id can't be zero. */
76 if (id == 0) 106 if (id == 0)
77 id = 1; 107 id = 1;
@@ -290,7 +320,9 @@ IP_Port connection_ip(Lossless_UDP *ludp, int connection_id)
290 if ((unsigned int)connection_id < ludp->connections.len) 320 if ((unsigned int)connection_id < ludp->connections.len)
291 return tox_array_get(&ludp->connections, connection_id, Connection).ip_port; 321 return tox_array_get(&ludp->connections, connection_id, Connection).ip_port;
292 322
293 IP_Port zero = {{{{0}}, 0, 0}}; 323 IP_Port zero;
324 ip_reset(&zero.ip);
325 zero.port = 0;
294 return zero; 326 return zero;
295} 327}
296 328
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 {
123 tox_array connections; 123 tox_array connections;
124 124
125 /* Table of random numbers used in handshake_id. */ 125 /* Table of random numbers used in handshake_id. */
126#ifdef TOX_ENABLE_IPV6
127 /* IPv6 (16) + port (2)*/
128 uint32_t randtable[18][256];
129#else
130 /* IPv4 (4) + port (2) */
126 uint32_t randtable[6][256]; 131 uint32_t randtable[6][256];
132#endif
127 133
128} Lossless_UDP; 134} Lossless_UDP;
129 135
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)
658 if ( ! m ) 658 if ( ! m )
659 return NULL; 659 return NULL;
660 660
661#ifdef NETWORK_IP_PORT_IS_IPV6 661 IP ip;
662 IPAny ip; 662 ip_init(&ip, ipv6enabled);
663 memset(&ip, 0, sizeof(ip));
664 ip.family = ipv6enabled ? AF_INET6 : AF_INET;
665#else
666 IP4 ip;
667 ip.uint32 = 0;
668#endif
669 m->net = new_networking(ip, PORT); 663 m->net = new_networking(ip, PORT);
670 664
671 if (m->net == NULL) { 665 if (m->net == NULL) {
@@ -749,11 +743,12 @@ void doFriends(Messenger *m)
749 } 743 }
750 } 744 }
751 745
752 IP_Port friendip = DHT_getfriendip(m->dht, m->friendlist[i].client_id); 746 IP_Port friendip;
747 int friendok = DHT_getfriendip(m->dht, m->friendlist[i].client_id, &friendip);
753 748
754 switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { 749 switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) {
755 case 0: 750 case 0:
756 if (friendip.ip.uint32 > 1) 751 if (friendok == 1)
757 m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip); 752 m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip);
758 753
759 break; 754 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
50 if (len == -1) 50 if (len == -1)
51 return -1; 51 return -1;
52 52
53 IP_Port ip_port = DHT_getfriendip(dht, public_key); 53 IP_Port ip_port;
54 int friendok = DHT_getfriendip(dht, public_key, &ip_port);
54 55
55 if (ip_port.ip.uint32 == 1) 56 // not a friend
57 if (friendok == -1)
56 return -1; 58 return -1;
57 59
58 if (ip_port.ip.uint32 != 0) { 60 // is a friend and we know how to reach him
61 if (friendok == 1) {
59 if (sendpacket(dht->c->lossless_udp->net, ip_port, packet, len) != -1) 62 if (sendpacket(dht->c->lossless_udp->net, ip_port, packet, len) != -1)
60 return 0; 63 return 0;
61 64
62 return -1; 65 return -1;
63 } 66 }
64 67
68 // is a friend, we DON'T know how to reach him
65 int num = route_tofriend(dht, public_key, packet, len); 69 int num = route_tofriend(dht, public_key, packet, len);
66 70
67 if (num == 0) 71 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,
204 uint64_t temp_time = unix_time(); 204 uint64_t temp_time = unix_time();
205 205
206 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { 206 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
207 if (chat->close[i].ip_port.ip.uint32 != 0 && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) { 207 if (ip_isset(&chat->close[i].ip_port.ip) && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) {
208 if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0) 208 if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0)
209 ++sent; 209 ++sent;
210 } 210 }
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)
439 if (id != -1) { 439 if (id != -1) {
440 IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number); 440 IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number);
441 441
442 if (c_ip.ip.uint32 == ip_port.ip.uint32 && c_ip.port == ip_port.port) 442 if (ipport_equal(&c_ip, &ip_port))
443 return -1; 443 return -1;
444 } 444 }
445 445
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)
66 */ 66 */
67int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length) 67int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length)
68{ 68{
69 ADDR addr = {AF_INET, ip_port.port, ip_port.ip, {0}}; 69#ifdef TOX_ENABLE_IPV6
70 return sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); 70 /* socket AF_INET, but target IP NOT: can't send */
71 if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET))
72 return 0;
73#endif
74
75 struct sockaddr_storage addr;
76 size_t addrsize = 0;
77
78#ifdef TOX_ENABLE_IPV6
79 if (ip_port.ip.family == AF_INET) {
80 if (net->family == AF_INET6) {
81 /* must convert to IPV4-in-IPV6 address */
82 addrsize = sizeof(struct sockaddr_in6);
83 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
84 addr6->sin6_family = AF_INET6;
85 addr6->sin6_port = ip_port.port;
86
87 /* there should be a macro for this in a standards compliant
88 * environment, not found */
89 addr6->sin6_addr.s6_addr32[0] = 0;
90 addr6->sin6_addr.s6_addr32[1] = 0;
91 addr6->sin6_addr.s6_addr32[2] = htonl(0xFFFF);
92 addr6->sin6_addr.s6_addr32[3] = ip_port.ip.ip4.uint32;
93
94 addr6->sin6_flowinfo = 0;
95 addr6->sin6_scope_id = 0;
96 }
97 else {
98 IP4 ip4 = ip_port.ip.ip4;
99#else
100 IP4 ip4 = ip_port.ip;
101#endif
102 addrsize = sizeof(struct sockaddr_in);
103 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
104 addr4->sin_family = AF_INET;
105 addr4->sin_addr = ip4.in_addr;
106 addr4->sin_port = ip_port.port;
107#ifdef TOX_ENABLE_IPV6
108 }
109 }
110 else if (ip_port.ip.family == AF_INET6) {
111 addrsize = sizeof(struct sockaddr_in6);
112 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
113 addr6->sin6_family = AF_INET6;
114 addr6->sin6_port = ip_port.port;
115 addr6->sin6_addr = ip_port.ip.ip6;
116
117 addr6->sin6_flowinfo = 0;
118 addr6->sin6_scope_id = 0;
119 } else {
120 /* unknown address type*/
121 return 0;
122 }
123#endif
124
125 return sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
71} 126}
72 127
73/* Function to receive data 128/* Function to receive data
@@ -82,7 +137,7 @@ static int receivepacket(unsigned int sock, IP_Port *ip_port, uint8_t *data, uin
82static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) 137static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
83#endif 138#endif
84{ 139{
85 ADDR addr; 140 struct sockaddr_storage addr;
86#ifdef WIN32 141#ifdef WIN32
87 int addrlen = sizeof(addr); 142 int addrlen = sizeof(addr);
88#else 143#else
@@ -93,8 +148,31 @@ static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *le
93 if (*(int32_t *)length <= 0) 148 if (*(int32_t *)length <= 0)
94 return -1; /* Nothing received or empty packet. */ 149 return -1; /* Nothing received or empty packet. */
95 150
96 ip_port->ip = addr.ip; 151#ifdef TOX_ENABLE_IPV6
97 ip_port->port = addr.port; 152 if (addr.ss_family == AF_INET) {
153 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
154 ip_port->ip.family = addr_in->sin_family;
155 ip_port->ip.ip4.in_addr = addr_in->sin_addr;
156 ip_port->port = addr_in->sin_port;
157 }
158 else if (addr.ss_family == AF_INET6) {
159 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
160 ip_port->ip.family = addr_in6->sin6_family;
161 ip_port->ip.ip6 = addr_in6->sin6_addr;
162 ip_port->port = addr_in6->sin6_port;
163 }
164 else
165 return -1;
166#else
167 if (addr.ss_family == AF_INET) {
168 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
169 ip_port->ip.in_addr = addr_in->sin_addr;
170 ip_port->port = addr_in->sin_port;
171 }
172 else
173 return -1;
174#endif
175
98 return 0; 176 return 0;
99} 177}
100 178
@@ -156,18 +234,32 @@ static void at_shutdown(void)
156 * return Networking_Core object if no problems 234 * return Networking_Core object if no problems
157 * return NULL if there are problems. 235 * return NULL if there are problems.
158 */ 236 */
159Networking_Core *new_networking(IP4 ip, uint16_t port) 237Networking_Core *new_networking(IP ip, uint16_t port)
160{ 238{
239#ifdef TOX_ENABLE_IPV6
240 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
241 if (ip.family != AF_INET && ip.family != AF_INET6)
242 return NULL;
243#endif
244
161 if (at_startup() != 0) 245 if (at_startup() != 0)
162 return NULL; 246 return NULL;
163 247
164 /* Initialize our socket. */
165 Networking_Core *temp = calloc(1, sizeof(Networking_Core)); 248 Networking_Core *temp = calloc(1, sizeof(Networking_Core));
166
167 if (temp == NULL) 249 if (temp == NULL)
168 return NULL; 250 return NULL;
169 251
170 temp->family = AF_INET; 252 sa_family_t family = 0;
253#ifdef TOX_ENABLE_IPV6
254 family = ip.family;
255#else
256 family = AF_INET;
257#endif
258 temp->family = family;
259 temp->port = 0;
260
261 /* Initialize our socket. */
262 /* add log message what we're creating */
171 temp->sock = socket(temp->family, SOCK_DGRAM, IPPROTO_UDP); 263 temp->sock = socket(temp->family, SOCK_DGRAM, IPPROTO_UDP);
172 264
173 /* Check for socket error. */ 265 /* Check for socket error. */
@@ -201,7 +293,7 @@ Networking_Core *new_networking(IP4 ip, uint16_t port)
201 return -1; 293 return -1;
202 */ 294 */
203 295
204 /* Enable broadcast on socket. */ 296 /* Enable broadcast on socket? */
205 int broadcast = 1; 297 int broadcast = 1;
206 setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); 298 setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast));
207 299
@@ -216,11 +308,72 @@ Networking_Core *new_networking(IP4 ip, uint16_t port)
216#endif 308#endif
217 309
218 /* Bind our socket to port PORT and address 0.0.0.0 */ 310 /* Bind our socket to port PORT and address 0.0.0.0 */
219 ADDR addr = {temp->family, htons(port), ip, {0}}; 311 uint16_t *portptr = NULL;
220 if (!bind(temp->sock, (struct sockaddr *)&addr, sizeof(addr))) 312 struct sockaddr_storage addr;
221 temp->port = port; 313 size_t addrsize;
314#ifdef TOX_ENABLE_IPV6
315 if (temp->family == AF_INET)
316 {
317 IP4 ip4 = ip.ip4;
318#else
319 IP4 ip4 = ip;
320#endif
321 addrsize = sizeof(struct sockaddr_in);
322 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
323 addr4->sin_family = AF_INET;
324 addr4->sin_port = htons(port);
325 addr4->sin_addr = ip4.in_addr;
326
327 portptr = &addr4->sin_port;
328#ifdef TOX_ENABLE_IPV6
329 }
330 else if (temp->family == AF_INET6)
331 {
332 addrsize = sizeof(struct sockaddr_in6);
333 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
334 addr6->sin6_family = AF_INET6;
335 addr6->sin6_port = htons(port);
336 addr6->sin6_addr = ip.ip6;
337
338 addr6->sin6_flowinfo = 0;
339 addr6->sin6_scope_id = 0;
340
341 portptr = &addr6->sin6_port;
342 }
343 else
344 return NULL;
222 345
223 return temp; 346 if (ip.family == AF_INET6) {
347 char ipv6only = 0;
348 int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only));
349 if (res < 0) {
350 /* add log message*/
351 }
352 }
353#endif
354
355 /* a hanging program or a different user might block the standard port;
356 * as long as it isn't a parameter coming from the commandline,
357 * try a few ports after it, to see if we can find a "free" one
358 */
359 int tries, res;
360 for(tries = 0; tries < 9; tries++)
361 {
362 res = bind(temp->sock, (struct sockaddr *)&addr, addrsize);
363 if (!res)
364 {
365 temp->port = *portptr;
366 return temp;
367 }
368
369 uint16_t port = ntohs(*portptr);
370 port++;
371 *portptr = htons(port);
372 }
373
374 printf("Failed to bind socket: %s (IP/Port: %s:%u\n", strerror(errno), ip_ntoa(&ip), port);
375 free(temp);
376 return NULL;
224} 377}
225 378
226/* Function to cleanup networking stuff. */ 379/* Function to cleanup networking stuff. */
@@ -241,11 +394,12 @@ void kill_networking(Networking_Core *net)
241 * 394 *
242 * returns 0 when not equal or when uninitialized 395 * returns 0 when not equal or when uninitialized
243 */ 396 */
244int ip_equal(IPAny *a, IPAny *b) 397int ip_equal(IP *a, IP *b)
245{ 398{
246 if (!a || !b) 399 if (!a || !b)
247 return 0; 400 return 0;
248 401
402#ifdef TOX_ENABLE_IPV6
249 if (a->family == AF_INET) 403 if (a->family == AF_INET)
250 return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr); 404 return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr);
251 405
@@ -253,6 +407,9 @@ int ip_equal(IPAny *a, IPAny *b)
253 return IN6_ARE_ADDR_EQUAL(&a->ip6, &b->ip6); 407 return IN6_ARE_ADDR_EQUAL(&a->ip6, &b->ip6);
254 408
255 return 0; 409 return 0;
410#else
411 return (a->uint32 == b->uint32);
412#endif
256}; 413};
257 414
258/* ipport_equal 415/* ipport_equal
@@ -261,7 +418,7 @@ int ip_equal(IPAny *a, IPAny *b)
261 * 418 *
262 * returns 0 when not equal or when uninitialized 419 * returns 0 when not equal or when uninitialized
263 */ 420 */
264int ipport_equal(IPAny_Port *a, IPAny_Port *b) 421int ipport_equal(IP_Port *a, IP_Port *b)
265{ 422{
266 if (!a || !b) 423 if (!a || !b)
267 return 0; 424 return 0;
@@ -272,15 +429,86 @@ int ipport_equal(IPAny_Port *a, IPAny_Port *b)
272 return ip_equal(&a->ip, &b->ip); 429 return ip_equal(&a->ip, &b->ip);
273}; 430};
274 431
275/* ipany_ntoa 432/* nulls out ip */
433void ip_reset(IP *ip)
434{
435 if (!ip)
436 return;
437
438#ifdef TOX_ENABLE_IPV6
439 memset(ip, 0, sizeof(*ip));
440#else
441 ip->uint32 = 0;
442#endif
443};
444
445/* nulls out ip, sets family according to flag */
446void ip_init(IP *ip, uint8_t ipv6enabled)
447{
448 if (!ip)
449 return;
450
451#ifdef TOX_ENABLE_IPV6
452 memset(ip, 0, sizeof(ip));
453 ip->family = ipv6enabled ? AF_INET6 : AF_INET;
454#else
455 ip->uint32 = 0;
456#endif
457};
458
459/* checks if ip is valid */
460int ip_isset(IP *ip)
461{
462 if (!ip)
463 return 0;
464
465#ifdef TOX_ENABLE_IPV6
466 return (ip->family != 0);
467#else
468 return (ip->uint32 != 0);
469#endif
470};
471
472/* checks if ip is valid */
473int ipport_isset(IP_Port *ipport)
474{
475 if (!ipport)
476 return 0;
477
478 if (!ipport->port)
479 return 0;
480
481 return ip_isset(&ipport->ip);
482};
483
484/* copies an ip structure (careful about direction!) */
485void ip_copy(IP *target, IP *source)
486{
487 if (!source || !target)
488 return;
489
490 memcpy(target, source, sizeof(IP));
491};
492
493/* copies an ip_port structure (careful about direction!) */
494void ipport_copy(IP_Port *target, IP_Port *source)
495{
496 if (!source || !target)
497 return;
498
499 memcpy(target, source, sizeof(IP_Port));
500};
501
502/* ip_ntoa
276 * converts ip into a string 503 * converts ip into a string
277 * uses a static buffer, so mustn't used multiple times in the same output 504 * uses a static buffer, so mustn't used multiple times in the same output
278 */ 505 */
279/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */ 506/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */
280static char addresstext[96]; 507static char addresstext[96];
281const char *ipany_ntoa(IPAny *ip) 508const char *ip_ntoa(IP *ip)
282{ 509{
283 if (ip) { 510 if (ip) {
511#ifdef TOX_ENABLE_IPV6
284 if (ip->family == AF_INET) { 512 if (ip->family == AF_INET) {
285 addresstext[0] = 0; 513 addresstext[0] = 0;
286 struct in_addr *addr = (struct in_addr *)&ip->ip4; 514 struct in_addr *addr = (struct in_addr *)&ip->ip4;
@@ -296,6 +524,11 @@ const char *ipany_ntoa(IPAny *ip)
296 } 524 }
297 else 525 else
298 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family); 526 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family);
527#else
528 addresstext[0] = 0;
529 struct in_addr *addr = (struct in_addr *)&ip;
530 inet_ntop(AF_INET, addr, addresstext, sizeof(addresstext));
531#endif
299 } 532 }
300 else 533 else
301 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)"); 534 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)");
@@ -318,8 +551,12 @@ const char *ipany_ntoa(IPAny *ip)
318 * returns 1 on success, 0 on failure 551 * returns 1 on success, 0 on failure
319 */ 552 */
320 553
321int addr_parse_ip(const char *address, IPAny *to) 554int addr_parse_ip(const char *address, IP *to)
322{ 555{
556 if (!address || !to)
557 return 0;
558
559#ifdef TOX_ENABLE_IPV6
323 struct in_addr addr4; 560 struct in_addr addr4;
324 if (1 == inet_pton(AF_INET, address, &addr4)) { 561 if (1 == inet_pton(AF_INET, address, &addr4)) {
325 to->family = AF_INET; 562 to->family = AF_INET;
@@ -333,6 +570,13 @@ int addr_parse_ip(const char *address, IPAny *to)
333 to->ip6 = addr6; 570 to->ip6 = addr6;
334 return 1; 571 return 1;
335 }; 572 };
573#else
574 struct in_addr addr4;
575 if (1 == inet_pton(AF_INET, address, &addr4)) {
576 to->in_addr = addr4;
577 return 1;
578 };
579#endif
336 580
337 return 0; 581 return 0;
338}; 582};
@@ -353,15 +597,25 @@ int addr_parse_ip(const char *address, IPAny *to)
353 * returns 0 on failure 597 * returns 0 on failure
354 */ 598 */
355 599
356int addr_resolve(const char *address, IPAny *ip) 600int addr_resolve(const char *address, IP *to)
357{ 601{
602 if (!address || !to)
603 return 0;
604
605 sa_family_t family;
606#ifdef TOX_ENABLE_IPV6
607 family = to->family;
608#else
609 family = AF_INET;
610#endif
611
358 struct addrinfo *server = NULL; 612 struct addrinfo *server = NULL;
359 struct addrinfo *walker = NULL; 613 struct addrinfo *walker = NULL;
360 struct addrinfo hints; 614 struct addrinfo hints;
361 int rc; 615 int rc;
362 616
363 memset(&hints, 0, sizeof(hints)); 617 memset(&hints, 0, sizeof(hints));
364 hints.ai_family = ip->family; 618 hints.ai_family = family;
365 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses. 619 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
366 620
367#ifdef __WIN32__ 621#ifdef __WIN32__
@@ -385,31 +639,40 @@ int addr_resolve(const char *address, IPAny *ip)
385 return 0; 639 return 0;
386 } 640 }
387 641
642#ifdef TOX_ENABLE_IPV6
388 IP4 ip4; 643 IP4 ip4;
389 memset(&ip4, 0, sizeof(ip4)); 644 memset(&ip4, 0, sizeof(ip4));
390 IP6 ip6; 645 IP6 ip6;
391 memset(&ip6, 0, sizeof(ip6)); 646 memset(&ip6, 0, sizeof(ip6));
647#endif
392 648
393 walker = server; 649 walker = server;
394 while (walker && (rc != 3)) { 650 while (walker && (rc != 3)) {
395 if (ip->family != AF_UNSPEC) { 651 if (family != AF_UNSPEC) {
396 if (walker->ai_family == ip->family) { 652 if (walker->ai_family == family) {
397 if (ip->family == AF_INET) { 653 if (family == AF_INET) {
398 if (walker->ai_addrlen == sizeof(struct sockaddr_in)) { 654 if (walker->ai_addrlen == sizeof(struct sockaddr_in)) {
399 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; 655 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
400 ip->ip4.in_addr = addr->sin_addr; 656#ifdef TOX_ENABLE_IPV6
657 to->ip4.in_addr = addr->sin_addr;
658#else
659 to->in_addr = addr->sin_addr;
660#endif
401 rc = 3; 661 rc = 3;
402 } 662 }
403 } 663 }
404 else if (ip->family == AF_INET6) { 664#ifdef TOX_ENABLE_IPV6
665 else if (family == AF_INET6) {
405 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { 666 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
406 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; 667 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
407 ip->ip6 = addr->sin6_addr; 668 to->ip6 = addr->sin6_addr;
408 rc = 3; 669 rc = 3;
409 } 670 }
410 } 671 }
672#endif
411 } 673 }
412 } 674 }
675#ifdef TOX_ENABLE_IPV6
413 else { 676 else {
414 if (walker->ai_family == AF_INET) { 677 if (walker->ai_family == AF_INET) {
415 if (walker->ai_addrlen == sizeof(struct sockaddr_in)) { 678 if (walker->ai_addrlen == sizeof(struct sockaddr_in)) {
@@ -426,22 +689,25 @@ int addr_resolve(const char *address, IPAny *ip)
426 } 689 }
427 } 690 }
428 } 691 }
692#endif
429 693
430 walker = walker->ai_next; 694 walker = walker->ai_next;
431 } 695 }
432 696
433 if (ip->family == AF_UNSPEC) { 697#ifdef TOX_ENABLE_IPV6
698 if (to->family == AF_UNSPEC) {
434 if (rc & 2) { 699 if (rc & 2) {
435 ip->family = AF_INET6; 700 to->family = AF_INET6;
436 ip->ip6 = ip6; 701 to->ip6 = ip6;
437 } 702 }
438 else if (rc & 1) { 703 else if (rc & 1) {
439 ip->family = AF_INET; 704 to->family = AF_INET;
440 ip->ip4 = ip4; 705 to->ip4 = ip4;
441 } 706 }
442 else 707 else
443 rc = 0; 708 rc = 0;
444 } 709 }
710#endif
445 711
446 712
447 freeaddrinfo(server); 713 freeaddrinfo(server);
@@ -458,7 +724,7 @@ int addr_resolve(const char *address, IPAny *ip)
458 * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6) 724 * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6)
459 * returns 1 on success, 0 on failure 725 * returns 1 on success, 0 on failure
460 */ 726 */
461int addr_resolve_or_parse_ip(const char *address, IPAny *to) 727int addr_resolve_or_parse_ip(const char *address, IP *to)
462{ 728{
463 if (!addr_resolve(address, to)) 729 if (!addr_resolve(address, to))
464 if (!addr_parse_ip(address, to)) 730 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 {
101 }; 101 };
102} IPAny; 102} IPAny;
103 103
104/* ipany_ntoa
105 * converts ip into a string
106 * uses a static buffer, so mustn't used multiple times in the same output
107 */
108const char *ipany_ntoa(IPAny *ip);
109
110typedef union { 104typedef union {
111 struct { 105 struct {
112 IP4 ip; 106 IP4 ip;
@@ -124,29 +118,43 @@ typedef struct {
124 uint16_t port; 118 uint16_t port;
125} IPAny_Port; 119} IPAny_Port;
126 120
127#ifdef NETWORK_IP_PORT_IS_IPV6 121#undef TOX_ENABLE_IPV6
122#ifdef TOX_ENABLE_IPV6
123#define TOX_ENABLE_IPV6_DEFAULT 1
124typedef IPAny IP;
128typedef IPAny_Port IP_Port; 125typedef IPAny_Port IP_Port;
129#else 126#else
127#define TOX_ENABLE_IPV6_DEFAULT 0
128typedef IP4 IP;
130typedef IP4_Port IP_Port; 129typedef IP4_Port IP_Port;
131#endif 130#endif
132 131
132/* ip_ntoa
133 * converts ip into a string
134 * uses a static buffer, so mustn't used multiple times in the same output
135 */
136const char *ip_ntoa(IP *ip);
137
133/* ipport_equal 138/* ipport_equal
134 * compares two IPAny_Port structures 139 * compares two IPAny_Port structures
135 * unset means unequal 140 * unset means unequal
136 * 141 *
137 * returns 0 when not equal or when uninitialized 142 * returns 0 when not equal or when uninitialized
138 */ 143 */
139int ipport_equal(IPAny_Port *a, IPAny_Port *b); 144int ipport_equal(IP_Port *a, IP_Port *b);
140 145
141typedef struct { 146/* nulls out ip */
142 int16_t family; 147void ip_reset(IP *ip);
143 uint16_t port; 148/* nulls out ip, sets family according to flag */
144 IP4 ip; 149void ip_init(IP *ip, uint8_t ipv6enabled);
145 uint8_t zeroes[8]; 150/* checks if ip is valid */
146#ifdef ENABLE_IPV6 151int ip_isset(IP *ip);
147 uint8_t zeroes2[12]; 152/* checks if ip is valid */
148#endif 153int ipport_isset(IP_Port *ipport);
149} ADDR; 154/* copies an ip structure */
155void ip_copy(IP *target, IP *source);
156/* copies an ip_port structure */
157void ipport_copy(IP_Port *target, IP_Port *source);
150 158
151/* 159/*
152 * addr_resolve_or_parse_ip 160 * addr_resolve_or_parse_ip
@@ -155,7 +163,7 @@ typedef struct {
155 * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6) 163 * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6)
156 * returns 1 on success, 0 on failure 164 * returns 1 on success, 0 on failure
157 */ 165 */
158int addr_resolve_or_parse_ip(const char *address, IPAny *to); 166int addr_resolve_or_parse_ip(const char *address, IP *to);
159 167
160/* Function to receive data, ip and port of sender is put into ip_port. 168/* Function to receive data, ip and port of sender is put into ip_port.
161 * Packet data is put into data. 169 * Packet data is put into data.
@@ -204,7 +212,7 @@ void networking_poll(Networking_Core *net);
204 * return 0 if no problems. 212 * return 0 if no problems.
205 * return -1 if there were problems. 213 * return -1 if there were problems.
206 */ 214 */
207Networking_Core *new_networking(IP4 ip, uint16_t port); 215Networking_Core *new_networking(IP ip, uint16_t port);
208 216
209/* Function to cleanup networking stuff (doesn't do much right now). */ 217/* Function to cleanup networking stuff (doesn't do much right now). */
210void kill_networking(Networking_Core *net); 218void 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
100{ 100{
101 PING *png = ping; 101 PING *png = ping;
102 102
103 if (ipp.ip.uint32 == 0 && ping_id == 0) 103 /* shouldn't that be an OR ? */
104 if (!ip_isset(&ipp.ip) && ping_id == 0)
104 return false; 105 return false;
105 106
106 size_t i, id; 107 size_t i, id;
@@ -111,7 +112,8 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl
111 id = (png->pos_pings + i) % PING_NUM_MAX; 112 id = (png->pos_pings + i) % PING_NUM_MAX;
112 113
113 /* ping_id = 0 means match any id. */ 114 /* ping_id = 0 means match any id. */
114 if ((ipp_eq(png->pings[id].ipp, ipp) || ipp.ip.uint32 == 0) && (png->pings[id].id == ping_id || ping_id == 0)) { 115 if ((!ip_isset(&ipp.ip) || ipport_equal(&png->pings[id].ipp, &ipp)) &&
116 (png->pings[id].id == ping_id || ping_id == 0)) {
115 return true; 117 return true;
116 } 118 }
117 } 119 }
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)
374 Messenger *m = tox; 374 Messenger *m = tox;
375 DHT_bootstrap(m->dht, ip_port, public_key); 375 DHT_bootstrap(m->dht, ip_port, public_key);
376} 376}
377void tox_bootstrap_ex(void *tox, const char *address, uint16_t port, uint8_t *public_key) 377void tox_bootstrap_ex(void *tox, const char *address, uint8_t ipv6enabled,
378 uint16_t port, uint8_t *public_key)
378{ 379{
379 Messenger *m = tox; 380 Messenger *m = tox;
380 DHT_bootstrap_ex(m->dht, address, port, public_key); 381 DHT_bootstrap_ex(m->dht, address, ipv6enabled, port, public_key);
381}; 382};
382 383
383/* return 0 if we are not connected to the DHT. 384/* 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" {
36 36
37#define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) 37#define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t))
38 38
39
40typedef union { 39typedef union {
41 uint8_t c[4]; 40 uint8_t c[4];
42 uint16_t s[2]; 41 uint16_t s[2];
43 uint32_t i; 42 uint32_t i;
44} tox_IP; 43} tox_IP4;
44
45
46typedef struct in6_addr tox_IP6;
45 47
46typedef struct { 48typedef struct {
47 tox_IP ip; 49 sa_family_t family;
50 union {
51 tox_IP4 ip4;
52 tox_IP6 ip6;
53 };
54} tox_IPAny;
55
56typedef union {
57 struct {
58 tox_IP4 ip;
59 uint16_t port;
60 /* Not used for anything right now. */
61 uint16_t padding;
62 };
63 uint8_t uint8[8];
64} tox_IP4_Port;
65
66/* will replace IP_Port as soon as the complete infrastructure is in place
67 * removed the unused union and padding also */
68typedef struct {
69 tox_IPAny ip;
48 uint16_t port; 70 uint16_t port;
49 /* Not used for anything right now. */ 71} tox_IPAny_Port;
50 uint16_t padding; 72
51} tox_IP_Port; 73#undef TOX_ENABLE_IPV6
74#ifdef TOX_ENABLE_IPV6
75#define TOX_ENABLE_IPV6_DEFAULT 1
76typedef tox_IPAny tox_IP;
77typedef tox_IPAny_Port tox_IP_Port;
78#else
79#define TOX_ENABLE_IPV6_DEFAULT 0
80typedef tox_IP4 tox_IP;
81typedef tox_IP4_Port tox_IP_Port;
82#endif
52 83
53#define TOX_IP_IS_IPV6 0
54 84
55/* Errors for m_addfriend 85/* Errors for m_addfriend
56 * FAERR - Friend Add Error 86 * FAERR - Friend Add Error
@@ -296,7 +326,8 @@ void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uin
296 * tox_bootstrap_ex converts the address into an IP_Port structure internally 326 * tox_bootstrap_ex converts the address into an IP_Port structure internally
297 */ 327 */
298void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); 328void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key);
299void tox_bootstrap_ex(Tox *tox, const char *address, uint16_t port, uint8_t *public_key); 329void tox_bootstrap_ex(Tox *tox, const char *address, uint8_t ipv6enabled,
330 uint16_t port, uint8_t *public_key);
300 331
301/* return 0 if we are not connected to the DHT. 332/* return 0 if we are not connected to the DHT.
302 * return 1 if we are. 333 * 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()
32 return r; 32 return r;
33} 33}
34 34
35bool ipp_eq(IP_Port a, IP_Port b)
36{
37 return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port);
38}
39
40bool id_eq(uint8_t *dest, uint8_t *src) 35bool id_eq(uint8_t *dest, uint8_t *src)
41{ 36{
42 return memcmp(dest, src, CLIENT_ID_SIZE) == 0; 37 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 @@
7 7
8uint64_t now(); 8uint64_t now();
9uint64_t random_64b(); 9uint64_t random_64b();
10bool ipp_eq(IP_Port a, IP_Port b);
11bool id_eq(uint8_t *dest, uint8_t *src); 10bool id_eq(uint8_t *dest, uint8_t *src);
12void id_cpy(uint8_t *dest, uint8_t *src); 11void id_cpy(uint8_t *dest, uint8_t *src);