summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toxcore/DHT.c165
-rw-r--r--toxcore/Lossless_UDP.c27
-rw-r--r--toxcore/network.c198
3 files changed, 224 insertions, 166 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 8557a5e0..df3b2f76 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -31,7 +31,6 @@
31#include "network.h" 31#include "network.h"
32#include "ping.h" 32#include "ping.h"
33#include "misc_tools.h" 33#include "misc_tools.h"
34#include "Messenger.h"
35#include "util.h" 34#include "util.h"
36 35
37/* The number of seconds for a non responsive node to become bad. */ 36/* The number of seconds for a non responsive node to become bad. */
@@ -197,73 +196,75 @@ static int friend_number(DHT *dht, uint8_t *client_id)
197 * helper for get_close_nodes(). argument list is a monster :D 196 * helper for get_close_nodes(). argument list is a monster :D
198 */ 197 */
199static int get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list, 198static int get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list,
200 sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, 199 sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length,
201 time_t timestamp, int *num_nodes_ptr) 200 time_t timestamp, int *num_nodes_ptr)
202{ 201{
203 int num_nodes = 0; 202 int num_nodes = 0;
204 int i, tout, inlist, ipv46x, j, closest; 203 int i, tout, inlist, ipv46x, j, closest;
205 for(i = 0; i < client_list_length; i++) { 204
206 Client_data *client = &client_list[i]; 205 for (i = 0; i < client_list_length; i++) {
207 tout = is_timeout(timestamp, client->timestamp, BAD_NODE_TIMEOUT); 206 Client_data *client = &client_list[i];
208 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id); 207 tout = is_timeout(timestamp, client->timestamp, BAD_NODE_TIMEOUT);
208 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id);
209 209
210#ifdef TOX_ENABLE_IPV6 210#ifdef TOX_ENABLE_IPV6
211 IP *client_ip = &client->ip_port.ip; 211 IP *client_ip = &client->ip_port.ip;
212 212
213 /* 213 /*
214 * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for 214 * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for
215 * our connections, instead we have to look if it is an embedded 215 * our connections, instead we have to look if it is an embedded
216 * IPv4-in-IPv6 here and convert it down in sendnodes(). 216 * IPv4-in-IPv6 here and convert it down in sendnodes().
217 */ 217 */
218 sa_family_t ip_treat_as_family = client_ip->family; 218 sa_family_t ip_treat_as_family = client_ip->family;
219 if ((dht->c->lossless_udp->net->family == AF_INET6) && 219
220 (client_ip->family == AF_INET6)) { 220 if ((dht->c->lossless_udp->net->family == AF_INET6) &&
221 /* socket is AF_INET6, address claims AF_INET6: 221 (client_ip->family == AF_INET6)) {
222 * check for embedded IPv4-in-IPv6 */ 222 /* socket is AF_INET6, address claims AF_INET6:
223 if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6)) 223 * check for embedded IPv4-in-IPv6 */
224 ip_treat_as_family = AF_INET; 224 if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6))
225 } 225 ip_treat_as_family = AF_INET;
226 226 }
227 ipv46x = !(sa_family == ip_treat_as_family); 227
228 ipv46x = !(sa_family == ip_treat_as_family);
228#else 229#else
229 ipv46x = !(sa_family == AF_INET); 230 ipv46x = !(sa_family == AF_INET);
230#endif 231#endif
231 232
232 /* If node isn't good or is already in list. */ 233 /* If node isn't good or is already in list. */
233 if (tout || inlist || ipv46x) 234 if (tout || inlist || ipv46x)
234 continue; 235 continue;
235 236
236 if (num_nodes < MAX_SENT_NODES) { 237 if (num_nodes < MAX_SENT_NODES) {
237 memcpy(nodes_list[num_nodes].client_id, 238 memcpy(nodes_list[num_nodes].client_id,
238 client->client_id, 239 client->client_id,
239 CLIENT_ID_SIZE ); 240 CLIENT_ID_SIZE );
240 241
241 nodes_list[num_nodes].ip_port = client->ip_port; 242 nodes_list[num_nodes].ip_port = client->ip_port;
242 num_nodes++; 243 num_nodes++;
243 } else { 244 } else {
244 /* see if node_list contains a client_id that's "further away" 245 /* see if node_list contains a client_id that's "further away"
245 * compared to the one we're looking at at the moment, if there 246 * compared to the one we're looking at at the moment, if there
246 * is, replace it 247 * is, replace it
247 */ 248 */
248 for (j = 0; j < MAX_SENT_NODES; ++j) { 249 for (j = 0; j < MAX_SENT_NODES; ++j) {
249 closest = id_closest( client_id, 250 closest = id_closest( client_id,
250 nodes_list[j].client_id, 251 nodes_list[j].client_id,
251 client->client_id ); 252 client->client_id );
252 253
253 /* second client_id is closer than current: change to it */ 254 /* second client_id is closer than current: change to it */
254 if (closest == 2) { 255 if (closest == 2) {
255 memcpy( nodes_list[j].client_id, 256 memcpy( nodes_list[j].client_id,
256 client->client_id, 257 client->client_id,
257 CLIENT_ID_SIZE); 258 CLIENT_ID_SIZE);
258 259
259 nodes_list[j].ip_port = client->ip_port; 260 nodes_list[j].ip_port = client->ip_port;
260 break; 261 break;
261 } 262 }
262 } 263 }
263 } 264 }
264 } 265 }
265 266
266 *num_nodes_ptr = num_nodes; 267 *num_nodes_ptr = num_nodes;
267} 268}
268 269
269/* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: 270/* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request:
@@ -274,15 +275,15 @@ static int get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *node
274 */ 275 */
275static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family) 276static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family)
276{ 277{
277 time_t timestamp = unix_time(); 278 time_t timestamp = unix_time();
278 int num_nodes = 0, i; 279 int num_nodes = 0, i;
279 get_close_nodes_inner(dht, client_id, nodes_list, sa_family, 280 get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
280 dht->close_clientlist, LCLIENT_LIST, timestamp, &num_nodes); 281 dht->close_clientlist, LCLIENT_LIST, timestamp, &num_nodes);
281 282
282 for (i = 0; i < dht->num_friends; ++i) 283 for (i = 0; i < dht->num_friends; ++i)
283 get_close_nodes_inner(dht, client_id, nodes_list, sa_family, 284 get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
284 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 285 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
285 timestamp, &num_nodes); 286 timestamp, &num_nodes);
286 287
287 return num_nodes; 288 return num_nodes;
288} 289}
@@ -554,11 +555,13 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
554#ifdef TOX_ENABLE_IPV6 555#ifdef TOX_ENABLE_IPV6
555 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); 556 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
556 int i, num_nodes_ok = 0; 557 int i, num_nodes_ok = 0;
557 for(i = 0; i < num_nodes; i++) { 558
559 for (i = 0; i < num_nodes; i++) {
558 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); 560 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
559 nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; 561 nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port;
560 562
561 IP *node_ip = &nodes_list[i].ip_port.ip; 563 IP *node_ip = &nodes_list[i].ip_port.ip;
564
562 if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6)) 565 if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6))
563 /* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */ 566 /* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */
564 nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.s6_addr32[3]; 567 nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.s6_addr32[3];
@@ -574,6 +577,7 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
574 /* shouldn't happen */ 577 /* shouldn't happen */
575 num_nodes = num_nodes_ok; 578 num_nodes = num_nodes_ok;
576 } 579 }
580
577#else 581#else
578 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size); 582 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size);
579#endif 583#endif
@@ -620,7 +624,7 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_
620 uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES]; 624 uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES];
621 uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; 625 uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
622 uint8_t nonce[crypto_box_NONCEBYTES]; 626 uint8_t nonce[crypto_box_NONCEBYTES];
623 random_nonce(nonce); 627 new_nonce(nonce);
624 628
625 memcpy(plain, &ping_id, sizeof(ping_id)); 629 memcpy(plain, &ping_id, sizeof(ping_id));
626 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size); 630 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size);
@@ -691,6 +695,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
691 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; 695 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
692 696
693 size_t Node4_format_size = sizeof(Node4_format); 697 size_t Node4_format_size = sizeof(Node4_format);
698
694 if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) || 699 if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) ||
695 ((length - cid_size) % Node4_format_size) != 0 || 700 ((length - cid_size) % Node4_format_size) != 0 ||
696 (length < cid_size + Node4_format_size)) 701 (length < cid_size + Node4_format_size))
@@ -721,7 +726,8 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
721 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); 726 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
722 727
723 int num_nodes_ok = 0; 728 int num_nodes_ok = 0;
724 for(i = 0; i < num_nodes; i++) 729
730 for (i = 0; i < num_nodes; i++)
725 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) { 731 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) {
726 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); 732 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
727 nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; 733 nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET;
@@ -735,6 +741,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
735 /* shouldn't happen */ 741 /* shouldn't happen */
736 num_nodes = num_nodes_ok; 742 num_nodes = num_nodes_ok;
737 } 743 }
744
738#else 745#else
739 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); 746 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
740#endif 747#endif
@@ -758,6 +765,7 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet,
758 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; 765 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
759 766
760 size_t Node_format_size = sizeof(Node4_format); 767 size_t Node_format_size = sizeof(Node4_format);
768
761 if (length > (cid_size + Node_format_size * MAX_SENT_NODES) || 769 if (length > (cid_size + Node_format_size * MAX_SENT_NODES) ||
762 ((length - cid_size) % Node_format_size) != 0 || 770 ((length - cid_size) % Node_format_size) != 0 ||
763 (length < cid_size + Node_format_size)) 771 (length < cid_size + Node_format_size))
@@ -964,17 +972,19 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key)
964 send_ping_request(dht->ping, dht->c, ip_port, public_key); 972 send_ping_request(dht->ping, dht->c, ip_port, public_key);
965} 973}
966int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, 974int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
967 uint16_t port, uint8_t *public_key) 975 uint16_t port, uint8_t *public_key)
968{ 976{
969 IP_Port ip_port_v64, ip_port_v4; 977 IP_Port ip_port_v64, ip_port_v4;
970 IP *ip_extra = NULL; 978 IP *ip_extra = NULL;
971#ifdef TOX_ENABLE_IPV6 979#ifdef TOX_ENABLE_IPV6
972 ip_init(&ip_port_v64.ip, ipv6enabled); 980 ip_init(&ip_port_v64.ip, ipv6enabled);
981
973 if (ipv6enabled) { 982 if (ipv6enabled) {
974 ip_port_v64.ip.family = AF_UNSPEC; 983 ip_port_v64.ip.family = AF_UNSPEC;
975 ip_reset(&ip_port_v4.ip); 984 ip_reset(&ip_port_v4.ip);
976 ip_extra = &ip_port_v4.ip; 985 ip_extra = &ip_port_v4.ip;
977 } 986 }
987
978#else 988#else
979 ip_init(&ip_port_v64.ip, 0); 989 ip_init(&ip_port_v64.ip, 0);
980#endif 990#endif
@@ -983,14 +993,15 @@ int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enable
983 ip_port_v64.port = port; 993 ip_port_v64.port = port;
984 DHT_bootstrap(dht, ip_port_v64, public_key); 994 DHT_bootstrap(dht, ip_port_v64, public_key);
985#ifdef TOX_ENABLE_IPV6 995#ifdef TOX_ENABLE_IPV6
996
986 if ((ip_extra != NULL) && ip_isset(ip_extra)) { 997 if ((ip_extra != NULL) && ip_isset(ip_extra)) {
987 ip_port_v4.port = port; 998 ip_port_v4.port = port;
988 DHT_bootstrap(dht, ip_port_v4, public_key); 999 DHT_bootstrap(dht, ip_port_v4, public_key);
989 } 1000 }
1001
990#endif 1002#endif
991 return 1; 1003 return 1;
992 } 1004 } else
993 else
994 return 0; 1005 return 0;
995} 1006}
996 1007
@@ -1303,6 +1314,7 @@ static void do_NAT(DHT *dht)
1303 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { 1314 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
1304 1315
1305 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 1316 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
1317
1306 if (!ip_isset(&ip)) 1318 if (!ip_isset(&ip))
1307 continue; 1319 continue;
1308 1320
@@ -1443,12 +1455,13 @@ void DHT_save(DHT *dht, uint8_t *data)
1443 */ 1455 */
1444int DHT_load(DHT *dht, uint8_t *data, uint32_t size) 1456int DHT_load(DHT *dht, uint8_t *data, uint32_t size)
1445{ 1457{
1446 if (size < sizeof(dht->close_clientlist)) { 1458 if (size < sizeof(dht->close_clientlist)) {
1447 fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); 1459 fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size);
1448 return -1; 1460 return -1;
1449 } 1461 }
1450 1462
1451 uint32_t friendlistsize = size - sizeof(dht->close_clientlist); 1463 uint32_t friendlistsize = size - sizeof(dht->close_clientlist);
1464
1452 if (friendlistsize % sizeof(DHT_Friend) != 0) { 1465 if (friendlistsize % sizeof(DHT_Friend) != 0) {
1453 fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); 1466 fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize);
1454 return -1; 1467 return -1;
@@ -1457,6 +1470,7 @@ int DHT_load(DHT *dht, uint8_t *data, uint32_t size)
1457 uint32_t i, j; 1470 uint32_t i, j;
1458 Client_data *client; 1471 Client_data *client;
1459 uint16_t friends_num = friendlistsize / sizeof(DHT_Friend); 1472 uint16_t friends_num = friendlistsize / sizeof(DHT_Friend);
1473
1460 if (friends_num != 0) { 1474 if (friends_num != 0) {
1461 DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); 1475 DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist));
1462 1476
@@ -1473,6 +1487,7 @@ int DHT_load(DHT *dht, uint8_t *data, uint32_t size)
1473 } 1487 }
1474 1488
1475 Client_data *tempclose_clientlist = (Client_data *)data; 1489 Client_data *tempclose_clientlist = (Client_data *)data;
1490
1476 for (i = 0; i < LCLIENT_LIST; ++i) { 1491 for (i = 0; i < LCLIENT_LIST; ++i) {
1477 if (tempclose_clientlist[i].timestamp != 0) 1492 if (tempclose_clientlist[i].timestamp != 0)
1478 DHT_bootstrap(dht, tempclose_clientlist[i].ip_port, 1493 DHT_bootstrap(dht, tempclose_clientlist[i].ip_port,
diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c
index ca874562..f942d8e5 100644
--- a/toxcore/Lossless_UDP.c
+++ b/toxcore/Lossless_UDP.c
@@ -80,26 +80,30 @@ static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
80 i++; 80 i++;
81 81
82#ifdef TOX_ENABLE_IPV6 82#ifdef TOX_ENABLE_IPV6
83 if (source.ip.family == AF_INET) 83
84 { 84 if (source.ip.family == AF_INET) {
85 IP4 ip4 = source.ip.ip4; 85 IP4 ip4 = source.ip.ip4;
86#else 86#else
87 IP4 ip4 = source.ip; 87 IP4 ip4 = source.ip;
88#endif 88#endif
89 int k; 89 int k;
90
90 for (k = 0; k < 4; k++) { 91 for (k = 0; k < 4; k++) {
91 id ^= randtable_initget(ludp, i++, ip4.uint8[k]); 92 id ^= randtable_initget(ludp, i++, ip4.uint8[k]);
92 } 93 }
94
93#ifdef TOX_ENABLE_IPV6 95#ifdef TOX_ENABLE_IPV6
94 } 96 }
95 97
96 if (source.ip.family == AF_INET6) 98 if (source.ip.family == AF_INET6)
97 { 99 {
98 int k; 100 int k;
101
99 for (k = 0; k < 16; k++) { 102 for (k = 0; k < 16; k++) {
100 id ^= randtable_initget(ludp, i++, source.ip.ip6.s6_addr[k]); 103 id ^= randtable_initget(ludp, i++, source.ip.ip6.s6_addr[k]);
101 } 104 }
102 } 105 }
106
103#endif 107#endif
104 108
105 /* id can't be zero. */ 109 /* id can't be zero. */
@@ -116,8 +120,21 @@ static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
116 */ 120 */
117static void change_handshake(Lossless_UDP *ludp, IP_Port source) 121static void change_handshake(Lossless_UDP *ludp, IP_Port source)
118{ 122{
119 uint8_t rand = random_int() % 4; 123#ifdef TOX_ENABLE_IPV6
120 ludp->randtable[rand][((uint8_t *)&source)[rand]] = random_int(); 124 uint8_t rand;
125
126 if (source.ip.family == AF_INET) {
127 rand = 2 + random_int() % 4;
128 } else if (source.ip.family == AF_INET6) {
129 rand = 2 + random_int() % 16;
130 } else {
131 return;
132 }
133
134#else
135 uint8_t rand = 2 + random_int() % 4;
136#endif
137 ludp->randtable[rand][((uint8_t *)&source.ip)[rand]] = random_int();
121} 138}
122 139
123/* 140/*
diff --git a/toxcore/network.c b/toxcore/network.c
index 6ae13160..5aa17cd0 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -73,15 +73,18 @@ static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *i
73int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length) 73int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length)
74{ 74{
75#ifdef TOX_ENABLE_IPV6 75#ifdef TOX_ENABLE_IPV6
76
76 /* socket AF_INET, but target IP NOT: can't send */ 77 /* socket AF_INET, but target IP NOT: can't send */
77 if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET)) 78 if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET))
78 return 0; 79 return -1;
80
79#endif 81#endif
80 82
81 struct sockaddr_storage addr; 83 struct sockaddr_storage addr;
82 size_t addrsize = 0; 84 size_t addrsize = 0;
83 85
84#ifdef TOX_ENABLE_IPV6 86#ifdef TOX_ENABLE_IPV6
87
85 if (ip_port.ip.family == AF_INET) { 88 if (ip_port.ip.family == AF_INET) {
86 if (net->family == AF_INET6) { 89 if (net->family == AF_INET6) {
87 /* must convert to IPV4-in-IPV6 address */ 90 /* must convert to IPV4-in-IPV6 address */
@@ -99,11 +102,10 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le
99 102
100 addr6->sin6_flowinfo = 0; 103 addr6->sin6_flowinfo = 0;
101 addr6->sin6_scope_id = 0; 104 addr6->sin6_scope_id = 0;
102 } 105 } else {
103 else {
104 IP4 ip4 = ip_port.ip.ip4; 106 IP4 ip4 = ip_port.ip.ip4;
105#else 107#else
106 IP4 ip4 = ip_port.ip; 108 IP4 ip4 = ip_port.ip;
107#endif 109#endif
108 addrsize = sizeof(struct sockaddr_in); 110 addrsize = sizeof(struct sockaddr_in);
109 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; 111 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
@@ -112,8 +114,8 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le
112 addr4->sin_port = ip_port.port; 114 addr4->sin_port = ip_port.port;
113#ifdef TOX_ENABLE_IPV6 115#ifdef TOX_ENABLE_IPV6
114 } 116 }
115 } 117 } else if (ip_port.ip.family == AF_INET6)
116 else if (ip_port.ip.family == AF_INET6) { 118 {
117 addrsize = sizeof(struct sockaddr_in6); 119 addrsize = sizeof(struct sockaddr_in6);
118 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 120 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
119 addr6->sin6_family = AF_INET6; 121 addr6->sin6_family = AF_INET6;
@@ -122,10 +124,12 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le
122 124
123 addr6->sin6_flowinfo = 0; 125 addr6->sin6_flowinfo = 0;
124 addr6->sin6_scope_id = 0; 126 addr6->sin6_scope_id = 0;
125 } else { 127 } else
128 {
126 /* unknown address type*/ 129 /* unknown address type*/
127 return 0; 130 return -1;
128 } 131 }
132
129#endif 133#endif
130 134
131 int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize); 135 int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
@@ -153,37 +157,40 @@ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t
153 157
154 if (*(int32_t *)length <= 0) { 158 if (*(int32_t *)length <= 0) {
155#ifdef LOGGING 159#ifdef LOGGING
160
156 if ((length < 0) && (errno != EWOULDBLOCK)) { 161 if ((length < 0) && (errno != EWOULDBLOCK)) {
157 sprintf(logbuffer, "Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); 162 sprintf(logbuffer, "Unexpected error reading from socket: %u, %s\n", errno, strerror(errno));
158 loglog(logbuffer); 163 loglog(logbuffer);
159 } 164 }
165
160#endif 166#endif
161 return -1; /* Nothing received or empty packet. */ 167 return -1; /* Nothing received or empty packet. */
162 } 168 }
163 169
164#ifdef TOX_ENABLE_IPV6 170#ifdef TOX_ENABLE_IPV6
171
165 if (addr.ss_family == AF_INET) { 172 if (addr.ss_family == AF_INET) {
166 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; 173 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
167 ip_port->ip.family = addr_in->sin_family; 174 ip_port->ip.family = addr_in->sin_family;
168 ip_port->ip.ip4.in_addr = addr_in->sin_addr; 175 ip_port->ip.ip4.in_addr = addr_in->sin_addr;
169 ip_port->port = addr_in->sin_port; 176 ip_port->port = addr_in->sin_port;
170 } 177 } else if (addr.ss_family == AF_INET6) {
171 else if (addr.ss_family == AF_INET6) {
172 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr; 178 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
173 ip_port->ip.family = addr_in6->sin6_family; 179 ip_port->ip.family = addr_in6->sin6_family;
174 ip_port->ip.ip6 = addr_in6->sin6_addr; 180 ip_port->ip.ip6 = addr_in6->sin6_addr;
175 ip_port->port = addr_in6->sin6_port; 181 ip_port->port = addr_in6->sin6_port;
176 } 182 } else
177 else
178 return -1; 183 return -1;
184
179#else 185#else
186
180 if (addr.ss_family == AF_INET) { 187 if (addr.ss_family == AF_INET) {
181 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; 188 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
182 ip_port->ip.in_addr = addr_in->sin_addr; 189 ip_port->ip.in_addr = addr_in->sin_addr;
183 ip_port->port = addr_in->sin_port; 190 ip_port->port = addr_in->sin_port;
184 } 191 } else
185 else
186 return -1; 192 return -1;
193
187#endif 194#endif
188 195
189#ifdef LOGGING 196#ifdef LOGGING
@@ -261,17 +268,20 @@ static void at_shutdown(void)
261Networking_Core *new_networking(IP ip, uint16_t port) 268Networking_Core *new_networking(IP ip, uint16_t port)
262{ 269{
263#ifdef TOX_ENABLE_IPV6 270#ifdef TOX_ENABLE_IPV6
271
264 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */ 272 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
265 if (ip.family != AF_INET && ip.family != AF_INET6) { 273 if (ip.family != AF_INET && ip.family != AF_INET6) {
266 fprintf(stderr, "Invalid address family: %u\n", ip.family); 274 fprintf(stderr, "Invalid address family: %u\n", ip.family);
267 return NULL; 275 return NULL;
268 } 276 }
277
269#endif 278#endif
270 279
271 if (at_startup() != 0) 280 if (at_startup() != 0)
272 return NULL; 281 return NULL;
273 282
274 Networking_Core *temp = calloc(1, sizeof(Networking_Core)); 283 Networking_Core *temp = calloc(1, sizeof(Networking_Core));
284
275 if (temp == NULL) 285 if (temp == NULL)
276 return NULL; 286 return NULL;
277 287
@@ -341,11 +351,11 @@ Networking_Core *new_networking(IP ip, uint16_t port)
341 struct sockaddr_storage addr; 351 struct sockaddr_storage addr;
342 size_t addrsize; 352 size_t addrsize;
343#ifdef TOX_ENABLE_IPV6 353#ifdef TOX_ENABLE_IPV6
344 if (temp->family == AF_INET) 354
345 { 355 if (temp->family == AF_INET) {
346 IP4 ip4 = ip.ip4; 356 IP4 ip4 = ip.ip4;
347#else 357#else
348 IP4 ip4 = ip; 358 IP4 ip4 = ip;
349#endif 359#endif
350 addrsize = sizeof(struct sockaddr_in); 360 addrsize = sizeof(struct sockaddr_in);
351 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; 361 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
@@ -355,8 +365,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
355 365
356 portptr = &addr4->sin_port; 366 portptr = &addr4->sin_port;
357#ifdef TOX_ENABLE_IPV6 367#ifdef TOX_ENABLE_IPV6
358 } 368 } else if (temp->family == AF_INET6)
359 else if (temp->family == AF_INET6)
360 { 369 {
361 addrsize = sizeof(struct sockaddr_in6); 370 addrsize = sizeof(struct sockaddr_in6);
362 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 371 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
@@ -368,21 +377,23 @@ Networking_Core *new_networking(IP ip, uint16_t port)
368 addr6->sin6_scope_id = 0; 377 addr6->sin6_scope_id = 0;
369 378
370 portptr = &addr6->sin6_port; 379 portptr = &addr6->sin6_port;
371 } 380 } else
372 else
373 return NULL; 381 return NULL;
374 382
375 if (ip.family == AF_INET6) { 383 if (ip.family == AF_INET6)
384 {
376 char ipv6only = 0; 385 char ipv6only = 0;
377 int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)); 386 int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only));
378#ifdef LOGGING 387#ifdef LOGGING
388
379 if (res < 0) { 389 if (res < 0) {
380 sprintf(logbuffer, "Failed to enable dual-stack on IPv6 socket, won't be able to receive from/send to IPv4 addresses. (%u, %s)\n", 390 sprintf(logbuffer,
391 "Failed to enable dual-stack on IPv6 socket, won't be able to receive from/send to IPv4 addresses. (%u, %s)\n",
381 errno, strerror(errno)); 392 errno, strerror(errno));
382 loglog(logbuffer); 393 loglog(logbuffer);
383 } 394 } else
384 else
385 loglog("Embedded IPv4 addresses enabled successfully.\n"); 395 loglog("Embedded IPv4 addresses enabled successfully.\n");
396
386#endif 397#endif
387 398
388 /* multicast local nodes */ 399 /* multicast local nodes */
@@ -394,15 +405,17 @@ Networking_Core *new_networking(IP ip, uint16_t port)
394 mreq.ipv6mr_interface = 0; 405 mreq.ipv6mr_interface = 0;
395 res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); 406 res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
396#ifdef LOGGING 407#ifdef LOGGING
408
397 if (res < 0) { 409 if (res < 0) {
398 sprintf(logbuffer, "Failed to activate local multicast membership. (%u, %s)\n", 410 sprintf(logbuffer, "Failed to activate local multicast membership. (%u, %s)\n",
399 errno, strerror(errno)); 411 errno, strerror(errno));
400 loglog(logbuffer); 412 loglog(logbuffer);
401 } 413 } else
402 else
403 loglog("Local multicast group FF02::1 joined successfully.\n"); 414 loglog("Local multicast group FF02::1 joined successfully.\n");
415
404#endif 416#endif
405 } 417 }
418
406#endif 419#endif
407 420
408 /* a hanging program or a different user might block the standard port; 421 /* a hanging program or a different user might block the standard port;
@@ -424,16 +437,18 @@ Networking_Core *new_networking(IP ip, uint16_t port)
424 uint16_t port_to_try = port; 437 uint16_t port_to_try = port;
425 *portptr = htons(port_to_try); 438 *portptr = htons(port_to_try);
426 int tries, res; 439 int tries, res;
427 for(tries = TOX_PORTRANGE_FROM; tries <= TOX_PORTRANGE_TO; tries++) 440
441 for (tries = TOX_PORTRANGE_FROM; tries <= TOX_PORTRANGE_TO; tries++)
428 { 442 {
429 res = bind(temp->sock, (struct sockaddr *)&addr, addrsize); 443 res = bind(temp->sock, (struct sockaddr *)&addr, addrsize);
430 if (!res) 444
431 { 445 if (!res) {
432 temp->port = *portptr; 446 temp->port = *portptr;
433#ifdef LOGGING 447#ifdef LOGGING
434 sprintf(logbuffer, "Bound successfully to %s:%u.\n", ip_ntoa(&ip), ntohs(temp->port)); 448 sprintf(logbuffer, "Bound successfully to %s:%u.\n", ip_ntoa(&ip), ntohs(temp->port));
435 loglog(logbuffer); 449 loglog(logbuffer);
436#endif 450#endif
451
437 /* errno isn't reset on success, only set on failure, the failed 452 /* errno isn't reset on success, only set on failure, the failed
438 * binds with parallel clients yield a -EPERM to the outside if 453 * binds with parallel clients yield a -EPERM to the outside if
439 * errno isn't cleared here */ 454 * errno isn't cleared here */
@@ -444,6 +459,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
444 } 459 }
445 460
446 port_to_try++; 461 port_to_try++;
462
447 if (port_to_try > TOX_PORTRANGE_TO) 463 if (port_to_try > TOX_PORTRANGE_TO)
448 port_to_try = TOX_PORTRANGE_FROM; 464 port_to_try = TOX_PORTRANGE_FROM;
449 465
@@ -451,7 +467,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
451 } 467 }
452 468
453 fprintf(stderr, "Failed to bind socket: %u, %s (IP/Port: %s:%u\n", errno, 469 fprintf(stderr, "Failed to bind socket: %u, %s (IP/Port: %s:%u\n", errno,
454 strerror(errno), ip_ntoa(&ip), port); 470 strerror(errno), ip_ntoa(&ip), port);
455 free(temp); 471 free(temp);
456 return NULL; 472 return NULL;
457} 473}
@@ -480,6 +496,7 @@ int ip_equal(IP *a, IP *b)
480 return 0; 496 return 0;
481 497
482#ifdef TOX_ENABLE_IPV6 498#ifdef TOX_ENABLE_IPV6
499
483 if (a->family == AF_INET) 500 if (a->family == AF_INET)
484 return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr); 501 return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr);
485 502
@@ -589,28 +606,27 @@ const char *ip_ntoa(IP *ip)
589{ 606{
590 if (ip) { 607 if (ip) {
591#ifdef TOX_ENABLE_IPV6 608#ifdef TOX_ENABLE_IPV6
609
592 if (ip->family == AF_INET) { 610 if (ip->family == AF_INET) {
593 addresstext[0] = 0; 611 addresstext[0] = 0;
594 struct in_addr *addr = (struct in_addr *)&ip->ip4; 612 struct in_addr *addr = (struct in_addr *)&ip->ip4;
595 inet_ntop(ip->family, addr, addresstext, sizeof(addresstext)); 613 inet_ntop(ip->family, addr, addresstext, sizeof(addresstext));
596 } 614 } else if (ip->family == AF_INET6) {
597 else if (ip->family == AF_INET6) {
598 addresstext[0] = '['; 615 addresstext[0] = '[';
599 struct in6_addr *addr = (struct in6_addr *)&ip->ip6; 616 struct in6_addr *addr = (struct in6_addr *)&ip->ip6;
600 inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3); 617 inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3);
601 size_t len = strlen(addresstext); 618 size_t len = strlen(addresstext);
602 addresstext[len] = ']'; 619 addresstext[len] = ']';
603 addresstext[len + 1] = 0; 620 addresstext[len + 1] = 0;
604 } 621 } else
605 else
606 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family); 622 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family);
623
607#else 624#else
608 addresstext[0] = 0; 625 addresstext[0] = 0;
609 struct in_addr *addr = (struct in_addr *)&ip; 626 struct in_addr *addr = (struct in_addr *)&ip;
610 inet_ntop(AF_INET, addr, addresstext, sizeof(addresstext)); 627 inet_ntop(AF_INET, addr, addresstext, sizeof(addresstext));
611#endif 628#endif
612 } 629 } else
613 else
614 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)"); 630 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)");
615 631
616 /* brute force protection against lacking termination */ 632 /* brute force protection against lacking termination */
@@ -639,6 +655,7 @@ int addr_parse_ip(const char *address, IP *to)
639 655
640#ifdef TOX_ENABLE_IPV6 656#ifdef TOX_ENABLE_IPV6
641 struct in_addr addr4; 657 struct in_addr addr4;
658
642 if (1 == inet_pton(AF_INET, address, &addr4)) { 659 if (1 == inet_pton(AF_INET, address, &addr4)) {
643 to->family = AF_INET; 660 to->family = AF_INET;
644 to->ip4.in_addr = addr4; 661 to->ip4.in_addr = addr4;
@@ -646,17 +663,21 @@ int addr_parse_ip(const char *address, IP *to)
646 }; 663 };
647 664
648 struct in6_addr addr6; 665 struct in6_addr addr6;
666
649 if (1 == inet_pton(AF_INET6, address, &addr6)) { 667 if (1 == inet_pton(AF_INET6, address, &addr6)) {
650 to->family = AF_INET6; 668 to->family = AF_INET6;
651 to->ip6 = addr6; 669 to->ip6 = addr6;
652 return 1; 670 return 1;
653 }; 671 };
672
654#else 673#else
655 struct in_addr addr4; 674 struct in_addr addr4;
675
656 if (1 == inet_pton(AF_INET, address, &addr4)) { 676 if (1 == inet_pton(AF_INET, address, &addr4)) {
657 to->in_addr = addr4; 677 to->in_addr = addr4;
658 return 1; 678 return 1;
659 }; 679 };
680
660#endif 681#endif
661 682
662 return 0; 683 return 0;
@@ -714,6 +735,7 @@ int addr_resolve(const char *address, IP *to, IP *extra)
714#endif 735#endif
715 736
716 rc = getaddrinfo(address, NULL, &hints, &server); 737 rc = getaddrinfo(address, NULL, &hints, &server);
738
717 // Lookup failed. 739 // Lookup failed.
718 if (rc != 0) { 740 if (rc != 0) {
719#ifdef __WIN32__ 741#ifdef __WIN32__
@@ -729,67 +751,71 @@ int addr_resolve(const char *address, IP *to, IP *extra)
729 memset(&ip6, 0, sizeof(ip6)); 751 memset(&ip6, 0, sizeof(ip6));
730#endif 752#endif
731 753
732 for(walker = server; (walker != NULL) && (rc != 3); walker = walker->ai_next) { 754 for (walker = server; (walker != NULL) && (rc != 3); walker = walker->ai_next) {
733 switch(walker->ai_family) { 755 switch (walker->ai_family) {
734 case AF_INET: 756 case AF_INET:
735 if (walker->ai_family == family) { 757 if (walker->ai_family == family) {
736 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; 758 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
737#ifdef TOX_ENABLE_IPV6 759#ifdef TOX_ENABLE_IPV6
738 to->ip4.in_addr = addr->sin_addr; 760 to->ip4.in_addr = addr->sin_addr;
739#else 761#else
740 to->in_addr = addr->sin_addr; 762 to->in_addr = addr->sin_addr;
741#endif
742 rc = 3;
743 }
744#ifdef TOX_ENABLE_IPV6
745 else if (!(rc & 1)) {
746 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
747 to->ip4.in_addr = addr->sin_addr;
748 rc |= 1;
749 }
750#endif 763#endif
751 break; /* switch */ 764 rc = 3;
765 }
752 766
753#ifdef TOX_ENABLE_IPV6 767#ifdef TOX_ENABLE_IPV6
754 case AF_INET6: 768 else if (!(rc & 1)) {
755 if (walker->ai_family == family) { 769 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
756 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { 770 to->ip4.in_addr = addr->sin_addr;
757 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; 771 rc |= 1;
758 to->ip6 = addr->sin6_addr;
759 rc = 3;
760 } 772 }
761 } else if (!(rc & 2)) { 773
762 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { 774#endif
763 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; 775 break; /* switch */
764 ip6 = addr->sin6_addr; 776#ifdef TOX_ENABLE_IPV6
765 rc |= 2; 777
778 case AF_INET6:
779 if (walker->ai_family == family) {
780 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
781 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
782 to->ip6 = addr->sin6_addr;
783 rc = 3;
784 }
785 } else if (!(rc & 2)) {
786 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
787 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
788 ip6 = addr->sin6_addr;
789 rc |= 2;
790 }
766 } 791 }
767 } 792
768 break; /* switch */ 793 break; /* switch */
769#endif 794#endif
770 } 795 }
771 } 796 }
772 797
773#ifdef TOX_ENABLE_IPV6 798#ifdef TOX_ENABLE_IPV6
799
774 if (to->family == AF_UNSPEC) { 800 if (to->family == AF_UNSPEC) {
775 if (rc & 2) { 801 if (rc & 2) {
776 to->family = AF_INET6; 802 to->family = AF_INET6;
777 to->ip6 = ip6; 803 to->ip6 = ip6;
804
778 if ((rc & 1) && (extra != NULL)) { 805 if ((rc & 1) && (extra != NULL)) {
779 extra->family = AF_INET; 806 extra->family = AF_INET;
780 extra->ip4 = ip4; 807 extra->ip4 = ip4;
781 } 808 }
782 } 809 } else if (rc & 1) {
783 else if (rc & 1) {
784 to->family = AF_INET; 810 to->family = AF_INET;
785 to->ip4 = ip4; 811 to->ip4 = ip4;
786 } 812 } else
787 else
788 rc = 0; 813 rc = 0;
789 } 814 }
815
790#endif 816#endif
791 817
792 818
793 freeaddrinfo(server); 819 freeaddrinfo(server);
794#ifdef __WIN32__ 820#ifdef __WIN32__
795 WSACleanup(); 821 WSACleanup();
@@ -826,22 +852,22 @@ static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *i
826{ 852{
827 if (res < 0) 853 if (res < 0)
828 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x\n", 854 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x\n",
829 buffer[0], message, buflen < 999 ? buflen : 999, 'E', 855 buffer[0], message, buflen < 999 ? buflen : 999, 'E',
830 ip_ntoa(&ip_port->ip), ntohs(ip_port->port), errno, 856 ip_ntoa(&ip_port->ip), ntohs(ip_port->port), errno,
831 strerror(errno), buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0, 857 strerror(errno), buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0,
832 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0); 858 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0);
833 else if ((res > 0) && (res <= buflen)) 859 else if ((res > 0) && (res <= buflen))
834 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x\n", 860 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x\n",
835 buffer[0], message, res < 999 ? res : 999, res < buflen ? '<' : '=', 861 buffer[0], message, res < 999 ? res : 999, res < buflen ? '<' : '=',
836 ip_ntoa(&ip_port->ip), ntohs(ip_port->port), 0, 862 ip_ntoa(&ip_port->ip), ntohs(ip_port->port), 0,
837 "OK", buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0, 863 "OK", buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0,
838 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0); 864 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0);
839 else /* empty or overwrite */ 865 else /* empty or overwrite */
840 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %u%c%u %s:%u (%u: %s) | %04x%04x\n", 866 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %u%c%u %s:%u (%u: %s) | %04x%04x\n",
841 buffer[0], message, res, !res ? '0' : '>', buflen, 867 buffer[0], message, res, !res ? '0' : '>', buflen,
842 ip_ntoa(&ip_port->ip), ntohs(ip_port->port), 0, 868 ip_ntoa(&ip_port->ip), ntohs(ip_port->port), 0,
843 "OK", buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0, 869 "OK", buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0,
844 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0); 870 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0);
845 871
846 logbuffer[sizeof(logbuffer) - 1] = 0; 872 logbuffer[sizeof(logbuffer) - 1] = 0;
847 loglog(logbuffer); 873 loglog(logbuffer);