summaryrefslogtreecommitdiff
path: root/toxcore/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/network.c')
-rw-r--r--toxcore/network.c604
1 files changed, 581 insertions, 23 deletions
diff --git a/toxcore/network.c b/toxcore/network.c
index ed3dff8a..0b5eba61 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -26,6 +26,7 @@
26#endif 26#endif
27 27
28#include "network.h" 28#include "network.h"
29#include "util.h"
29 30
30/* return current UNIX time in microseconds (us). */ 31/* return current UNIX time in microseconds (us). */
31uint64_t current_time(void) 32uint64_t current_time(void)
@@ -61,17 +62,76 @@ uint32_t random_int(void)
61#endif 62#endif
62} 63}
63 64
65#ifdef LOGGING
66static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res);
67#endif
68
64/* Basic network functions: 69/* Basic network functions:
65 * Function to send packet(data) of length length to ip_port. 70 * Function to send packet(data) of length length to ip_port.
66 */ 71 */
67#ifdef WIN32 72int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length)
68int sendpacket(unsigned int sock, IP_Port ip_port, uint8_t *data, uint32_t length) 73{
74#ifdef TOX_ENABLE_IPV6
75 /* socket AF_INET, but target IP NOT: can't send */
76 if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET))
77 return 0;
78#endif
79
80 struct sockaddr_storage addr;
81 size_t addrsize = 0;
82
83#ifdef TOX_ENABLE_IPV6
84 if (ip_port.ip.family == AF_INET) {
85 if (net->family == AF_INET6) {
86 /* must convert to IPV4-in-IPV6 address */
87 addrsize = sizeof(struct sockaddr_in6);
88 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
89 addr6->sin6_family = AF_INET6;
90 addr6->sin6_port = ip_port.port;
91
92 /* there should be a macro for this in a standards compliant
93 * environment, not found */
94 addr6->sin6_addr.s6_addr32[0] = 0;
95 addr6->sin6_addr.s6_addr32[1] = 0;
96 addr6->sin6_addr.s6_addr32[2] = htonl(0xFFFF);
97 addr6->sin6_addr.s6_addr32[3] = ip_port.ip.ip4.uint32;
98
99 addr6->sin6_flowinfo = 0;
100 addr6->sin6_scope_id = 0;
101 }
102 else {
103 IP4 ip4 = ip_port.ip.ip4;
69#else 104#else
70int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length) 105 IP4 ip4 = ip_port.ip;
71#endif 106#endif
72{ 107 addrsize = sizeof(struct sockaddr_in);
73 ADDR addr = {AF_INET, ip_port.port, ip_port.ip, {0}}; 108 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
74 return sendto(sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); 109 addr4->sin_family = AF_INET;
110 addr4->sin_addr = ip4.in_addr;
111 addr4->sin_port = ip_port.port;
112#ifdef TOX_ENABLE_IPV6
113 }
114 }
115 else if (ip_port.ip.family == AF_INET6) {
116 addrsize = sizeof(struct sockaddr_in6);
117 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
118 addr6->sin6_family = AF_INET6;
119 addr6->sin6_port = ip_port.port;
120 addr6->sin6_addr = ip_port.ip.ip6;
121
122 addr6->sin6_flowinfo = 0;
123 addr6->sin6_scope_id = 0;
124 } else {
125 /* unknown address type*/
126 return 0;
127 }
128#endif
129
130 int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
131#ifdef LOGGING
132 loglogdata("O=>", data, length, &ip_port, res);
133#endif
134 return res;
75} 135}
76 136
77/* Function to receive data 137/* Function to receive data
@@ -80,13 +140,9 @@ int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length)
80 * Packet length is put into length. 140 * Packet length is put into length.
81 * Dump all empty packets. 141 * Dump all empty packets.
82 */ 142 */
83#ifdef WIN32 143static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
84static int receivepacket(unsigned int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
85#else
86static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
87#endif
88{ 144{
89 ADDR addr; 145 struct sockaddr_storage addr;
90#ifdef WIN32 146#ifdef WIN32
91 int addrlen = sizeof(addr); 147 int addrlen = sizeof(addr);
92#else 148#else
@@ -94,11 +150,43 @@ static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *le
94#endif 150#endif
95 (*(int32_t *)length) = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); 151 (*(int32_t *)length) = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
96 152
97 if (*(int32_t *)length <= 0) 153 if (*(int32_t *)length <= 0) {
154#ifdef LOGGING
155 if ((length < 0) && (errno != EWOULDBLOCK))
156 sprintf(logbuffer, "Unexpected error reading from socket: %u, %s\n", errno, strerror(errno));
157#endif
98 return -1; /* Nothing received or empty packet. */ 158 return -1; /* Nothing received or empty packet. */
159 }
160
161#ifdef TOX_ENABLE_IPV6
162 if (addr.ss_family == AF_INET) {
163 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
164 ip_port->ip.family = addr_in->sin_family;
165 ip_port->ip.ip4.in_addr = addr_in->sin_addr;
166 ip_port->port = addr_in->sin_port;
167 }
168 else if (addr.ss_family == AF_INET6) {
169 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
170 ip_port->ip.family = addr_in6->sin6_family;
171 ip_port->ip.ip6 = addr_in6->sin6_addr;
172 ip_port->port = addr_in6->sin6_port;
173 }
174 else
175 return -1;
176#else
177 if (addr.ss_family == AF_INET) {
178 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
179 ip_port->ip.in_addr = addr_in->sin_addr;
180 ip_port->port = addr_in->sin_port;
181 }
182 else
183 return -1;
184#endif
185
186#ifdef LOGGING
187 loglogdata("=>O", data, *length, ip_port, 0);
188#endif
99 189
100 ip_port->ip = addr.ip;
101 ip_port->port = addr.port;
102 return 0; 190 return 0;
103} 191}
104 192
@@ -162,16 +250,31 @@ static void at_shutdown(void)
162 */ 250 */
163Networking_Core *new_networking(IP ip, uint16_t port) 251Networking_Core *new_networking(IP ip, uint16_t port)
164{ 252{
253#ifdef TOX_ENABLE_IPV6
254 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
255 if (ip.family != AF_INET && ip.family != AF_INET6)
256 return NULL;
257#endif
258
165 if (at_startup() != 0) 259 if (at_startup() != 0)
166 return NULL; 260 return NULL;
167 261
168 /* Initialize our socket. */
169 Networking_Core *temp = calloc(1, sizeof(Networking_Core)); 262 Networking_Core *temp = calloc(1, sizeof(Networking_Core));
170
171 if (temp == NULL) 263 if (temp == NULL)
172 return NULL; 264 return NULL;
173 265
174 temp->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 266 sa_family_t family = 0;
267#ifdef TOX_ENABLE_IPV6
268 family = ip.family;
269#else
270 family = AF_INET;
271#endif
272 temp->family = family;
273 temp->port = 0;
274
275 /* Initialize our socket. */
276 /* add log message what we're creating */
277 temp->sock = socket(temp->family, SOCK_DGRAM, IPPROTO_UDP);
175 278
176 /* Check for socket error. */ 279 /* Check for socket error. */
177#ifdef WIN32 280#ifdef WIN32
@@ -204,7 +307,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
204 return -1; 307 return -1;
205 */ 308 */
206 309
207 /* Enable broadcast on socket. */ 310 /* Enable broadcast on socket? */
208 int broadcast = 1; 311 int broadcast = 1;
209 setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); 312 setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast));
210 313
@@ -218,10 +321,106 @@ Networking_Core *new_networking(IP ip, uint16_t port)
218 fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1); 321 fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1);
219#endif 322#endif
220 323
221 /* Bind our socket to port PORT and address 0.0.0.0 */ 324#ifdef LOGGING
222 ADDR addr = {AF_INET, htons(port), ip, {0}}; 325 loginit(ntohs(port));
223 bind(temp->sock, (struct sockaddr *)&addr, sizeof(addr)); 326#endif
224 return temp; 327
328 /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
329 uint16_t *portptr = NULL;
330 struct sockaddr_storage addr;
331 size_t addrsize;
332#ifdef TOX_ENABLE_IPV6
333 if (temp->family == AF_INET)
334 {
335 IP4 ip4 = ip.ip4;
336#else
337 IP4 ip4 = ip;
338#endif
339 addrsize = sizeof(struct sockaddr_in);
340 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
341 addr4->sin_family = AF_INET;
342 addr4->sin_port = htons(port);
343 addr4->sin_addr = ip4.in_addr;
344
345 portptr = &addr4->sin_port;
346#ifdef TOX_ENABLE_IPV6
347 }
348 else if (temp->family == AF_INET6)
349 {
350 addrsize = sizeof(struct sockaddr_in6);
351 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
352 addr6->sin6_family = AF_INET6;
353 addr6->sin6_port = htons(port);
354 addr6->sin6_addr = ip.ip6;
355
356 addr6->sin6_flowinfo = 0;
357 addr6->sin6_scope_id = 0;
358
359 portptr = &addr6->sin6_port;
360 }
361 else
362 return NULL;
363
364 if (ip.family == AF_INET6) {
365 char ipv6only = 0;
366 int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only));
367#ifdef LOGGING
368 if (res < 0) {
369 sprintf(logbuffer, "Failed to enable dual-stack on IPv6 socket, won't be able to receive from/send to IPv4 addresses. (%u, %s)\n",
370 errno, strerror(errno));
371 loglog(logbuffer);
372 }
373 else
374 loglog("Embedded IPv4 addresses enabled successfully.\n");
375#endif
376
377 /* multicast local nodes */
378 struct ipv6_mreq mreq;
379 memset(&mreq, 0, sizeof(mreq));
380 mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF;
381 mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
382 mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
383 mreq.ipv6mr_interface = 0;
384 res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
385#ifdef LOGGING
386 if (res < 0) {
387 sprintf(logbuffer, "Failed to activate local multicast membership. (%u, %s)\n",
388 errno, strerror(errno));
389 loglog(logbuffer);
390 }
391 else
392 loglog("Local multicast group FF02::1 joined successfully.\n");
393#endif
394 }
395#endif
396
397 /* a hanging program or a different user might block the standard port;
398 * as long as it isn't a parameter coming from the commandline,
399 * try a few ports after it, to see if we can find a "free" one
400 */
401 int tries, res;
402 for(tries = 0; tries < 9; tries++)
403 {
404 res = bind(temp->sock, (struct sockaddr *)&addr, addrsize);
405 if (!res)
406 {
407 temp->port = *portptr;
408#ifdef LOGGING
409 sprintf(logbuffer, "Bound successfully to %s:%u.\n", ip_ntoa(&ip), ntohs(temp->port));
410 loglog(logbuffer);
411#endif
412 return temp;
413 }
414
415 uint16_t port = ntohs(*portptr);
416 port++;
417 *portptr = htons(port);
418 }
419
420 fprintf(stderr, "Failed to bind socket: %u, %s (IP/Port: %s:%u\n", errno,
421 strerror(errno), ip_ntoa(&ip), port);
422 free(temp);
423 return NULL;
225} 424}
226 425
227/* Function to cleanup networking stuff. */ 426/* Function to cleanup networking stuff. */
@@ -235,3 +434,362 @@ void kill_networking(Networking_Core *net)
235 free(net); 434 free(net);
236 return; 435 return;
237} 436}
437
438/* ip_equal
439 * compares two IPAny structures
440 * unset means unequal
441 *
442 * returns 0 when not equal or when uninitialized
443 */
444int ip_equal(IP *a, IP *b)
445{
446 if (!a || !b)
447 return 0;
448
449#ifdef TOX_ENABLE_IPV6
450 if (a->family == AF_INET)
451 return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr);
452
453 if (a->family == AF_INET6)
454 return IN6_ARE_ADDR_EQUAL(&a->ip6, &b->ip6);
455
456 return 0;
457#else
458 return (a->uint32 == b->uint32);
459#endif
460};
461
462/* ipport_equal
463 * compares two IPAny_Port structures
464 * unset means unequal
465 *
466 * returns 0 when not equal or when uninitialized
467 */
468int ipport_equal(IP_Port *a, IP_Port *b)
469{
470 if (!a || !b)
471 return 0;
472
473 if (!a->port || (a->port != b->port))
474 return 0;
475
476 return ip_equal(&a->ip, &b->ip);
477};
478
479/* nulls out ip */
480void ip_reset(IP *ip)
481{
482 if (!ip)
483 return;
484
485#ifdef TOX_ENABLE_IPV6
486 memset(ip, 0, sizeof(IP));
487#else
488 ip->uint32 = 0;
489#endif
490};
491
492/* nulls out ip, sets family according to flag */
493void ip_init(IP *ip, uint8_t ipv6enabled)
494{
495 if (!ip)
496 return;
497
498#ifdef TOX_ENABLE_IPV6
499 memset(ip, 0, sizeof(IP));
500 ip->family = ipv6enabled ? AF_INET6 : AF_INET;
501#else
502 ip->uint32 = 0;
503#endif
504};
505
506/* checks if ip is valid */
507int ip_isset(IP *ip)
508{
509 if (!ip)
510 return 0;
511
512#ifdef TOX_ENABLE_IPV6
513 return (ip->family != 0);
514#else
515 return (ip->uint32 != 0);
516#endif
517};
518
519/* checks if ip is valid */
520int ipport_isset(IP_Port *ipport)
521{
522 if (!ipport)
523 return 0;
524
525 if (!ipport->port)
526 return 0;
527
528 return ip_isset(&ipport->ip);
529};
530
531/* copies an ip structure (careful about direction!) */
532void ip_copy(IP *target, IP *source)
533{
534 if (!source || !target)
535 return;
536
537 memcpy(target, source, sizeof(IP));
538};
539
540/* copies an ip_port structure (careful about direction!) */
541void ipport_copy(IP_Port *target, IP_Port *source)
542{
543 if (!source || !target)
544 return;
545
546 memcpy(target, source, sizeof(IP_Port));
547};
548
549/* ip_ntoa
550 * converts ip into a string
551 * uses a static buffer, so mustn't used multiple times in the same output
552 */
553/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */
554static char addresstext[96];
555const char *ip_ntoa(IP *ip)
556{
557 if (ip) {
558#ifdef TOX_ENABLE_IPV6
559 if (ip->family == AF_INET) {
560 addresstext[0] = 0;
561 struct in_addr *addr = (struct in_addr *)&ip->ip4;
562 inet_ntop(ip->family, addr, addresstext, sizeof(addresstext));
563 }
564 else if (ip->family == AF_INET6) {
565 addresstext[0] = '[';
566 struct in6_addr *addr = (struct in6_addr *)&ip->ip6;
567 inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3);
568 size_t len = strlen(addresstext);
569 addresstext[len] = ']';
570 addresstext[len + 1] = 0;
571 }
572 else
573 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family);
574#else
575 addresstext[0] = 0;
576 struct in_addr *addr = (struct in_addr *)&ip;
577 inet_ntop(AF_INET, addr, addresstext, sizeof(addresstext));
578#endif
579 }
580 else
581 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)");
582
583 addresstext[INET6_ADDRSTRLEN + 2] = 0;
584 return addresstext;
585};
586
587/*
588 * addr_parse_ip
589 * directly parses the input into an IP structure
590 * tries IPv4 first, then IPv6
591 *
592 * input
593 * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
594 *
595 * output
596 * IP: family and the value is set on success
597 *
598 * returns 1 on success, 0 on failure
599 */
600
601int addr_parse_ip(const char *address, IP *to)
602{
603 if (!address || !to)
604 return 0;
605
606#ifdef TOX_ENABLE_IPV6
607 struct in_addr addr4;
608 if (1 == inet_pton(AF_INET, address, &addr4)) {
609 to->family = AF_INET;
610 to->ip4.in_addr = addr4;
611 return 1;
612 };
613
614 struct in6_addr addr6;
615 if (1 == inet_pton(AF_INET6, address, &addr6)) {
616 to->family = AF_INET6;
617 to->ip6 = addr6;
618 return 1;
619 };
620#else
621 struct in_addr addr4;
622 if (1 == inet_pton(AF_INET, address, &addr4)) {
623 to->in_addr = addr4;
624 return 1;
625 };
626#endif
627
628 return 0;
629};
630
631/*
632 * addr_resolve():
633 * uses getaddrinfo to resolve an address into an IP address
634 * uses the first IPv4/IPv6 addresses returned by getaddrinfo
635 *
636 * input
637 * address: a hostname (or something parseable to an IP address)
638 * ip: ip.family MUST be initialized, either set to a specific IP version
639 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
640 * IP versions are acceptable
641 *
642 * returns in ip a valid IPAny (v4/v6),
643 * prefers v6 if ip.family was AF_UNSPEC and both available
644 * returns 0 on failure
645 */
646
647int addr_resolve(const char *address, IP *to)
648{
649 if (!address || !to)
650 return 0;
651
652 sa_family_t family;
653#ifdef TOX_ENABLE_IPV6
654 family = to->family;
655#else
656 family = AF_INET;
657#endif
658
659 struct addrinfo *server = NULL;
660 struct addrinfo *walker = NULL;
661 struct addrinfo hints;
662 int rc;
663
664 memset(&hints, 0, sizeof(hints));
665 hints.ai_family = family;
666 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
667
668#ifdef __WIN32__
669 WSADATA wsa_data;
670
671 /* CLEANUP: really not the best place to put this */
672 rc = WSAStartup(MAKEWORD(2, 2), &wsa_data);
673
674 if (rc != 0) {
675 return 0;
676 }
677
678#endif
679
680 rc = getaddrinfo(address, NULL, &hints, &server);
681 // Lookup failed.
682 if (rc != 0) {
683#ifdef __WIN32__
684 WSACleanup();
685#endif
686 return 0;
687 }
688
689#ifdef TOX_ENABLE_IPV6
690 IP4 ip4;
691 memset(&ip4, 0, sizeof(ip4));
692 IP6 ip6;
693 memset(&ip6, 0, sizeof(ip6));
694#endif
695
696 walker = server;
697 while (walker && (rc != 3)) {
698 if (family != AF_UNSPEC) {
699 if (walker->ai_family == family) {
700 if (family == AF_INET) {
701 if (walker->ai_addrlen == sizeof(struct sockaddr_in)) {
702 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
703#ifdef TOX_ENABLE_IPV6
704 to->ip4.in_addr = addr->sin_addr;
705#else
706 to->in_addr = addr->sin_addr;
707#endif
708 rc = 3;
709 }
710 }
711#ifdef TOX_ENABLE_IPV6
712 else if (family == AF_INET6) {
713 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
714 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
715 to->ip6 = addr->sin6_addr;
716 rc = 3;
717 }
718 }
719#endif
720 }
721 }
722#ifdef TOX_ENABLE_IPV6
723 else {
724 if (walker->ai_family == AF_INET) {
725 if (walker->ai_addrlen == sizeof(struct sockaddr_in)) {
726 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
727 ip4.in_addr = addr->sin_addr;
728 rc |= 1;
729 }
730 }
731 else if (walker->ai_family == AF_INET6) {
732 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
733 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
734 ip6 = addr->sin6_addr;
735 rc |= 2;
736 }
737 }
738 }
739#endif
740
741 walker = walker->ai_next;
742 }
743
744#ifdef TOX_ENABLE_IPV6
745 if (to->family == AF_UNSPEC) {
746 if (rc & 2) {
747 to->family = AF_INET6;
748 to->ip6 = ip6;
749 }
750 else if (rc & 1) {
751 to->family = AF_INET;
752 to->ip4 = ip4;
753 }
754 else
755 rc = 0;
756 }
757#endif
758
759
760 freeaddrinfo(server);
761#ifdef __WIN32__
762 WSACleanup();
763#endif
764 return rc;
765}
766
767/*
768 * addr_resolve_or_parse_ip
769 * resolves string into an IP address
770 *
771 * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6)
772 * returns 1 on success, 0 on failure
773 */
774int addr_resolve_or_parse_ip(const char *address, IP *to)
775{
776 if (!addr_resolve(address, to))
777 if (!addr_parse_ip(address, to))
778 return 0;
779
780 return 1;
781};
782
783#ifdef LOGGING
784static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res)
785{
786 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %3u%c %s %s:%u (%u: %s) | %04x%04x\n",
787 buffer[0], res < 0 ? (buflen & 0xFF) : res,
788 res < 0 ? '-' : (res == buflen ? '=' : '+'),
789 message, ip_ntoa(&ip_port->ip), ntohs(ip_port->port), res < 0 ? errno : 0,
790 res < 0 ? strerror(errno) : "OK", buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0,
791 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0);
792 logbuffer[sizeof(logbuffer) - 1] = 0;
793 loglog(logbuffer);
794}
795#endif