summaryrefslogtreecommitdiffstats
path: root/common/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/socket.c')
-rw-r--r--common/socket.c423
1 files changed, 381 insertions, 42 deletions
diff --git a/common/socket.c b/common/socket.c
index a5f9a33..354e6a4 100644
--- a/common/socket.c
+++ b/common/socket.c
@@ -34,7 +34,16 @@
34#include <winsock2.h> 34#include <winsock2.h>
35#include <ws2tcpip.h> 35#include <ws2tcpip.h>
36#include <windows.h> 36#include <windows.h>
37#ifndef HAVE_GETIFADDRS
38#include <iphlpapi.h>
39#endif
37static int wsa_init = 0; 40static int wsa_init = 0;
41#ifndef IFF_RUNNING
42#define IFF_RUNNING IFF_UP
43#endif
44#ifndef AI_NUMERICSERV
45#define AI_NUMERICSERV 0
46#endif
38#else 47#else
39#include <sys/socket.h> 48#include <sys/socket.h>
40#include <sys/un.h> 49#include <sys/un.h>
@@ -51,6 +60,7 @@ static int wsa_init = 0;
51#include "socket.h" 60#include "socket.h"
52 61
53#define RECV_TIMEOUT 20000 62#define RECV_TIMEOUT 20000
63#define SEND_TIMEOUT 10000
54#define CONNECT_TIMEOUT 5000 64#define CONNECT_TIMEOUT 5000
55 65
56#ifndef EAFNOSUPPORT 66#ifndef EAFNOSUPPORT
@@ -161,7 +171,7 @@ int socket_create_unix(const char *filename)
161 return -1; 171 return -1;
162 } 172 }
163 173
164 if (listen(sock, 10) < 0) { 174 if (listen(sock, 100) < 0) {
165 perror("listen"); 175 perror("listen");
166 socket_close(sock); 176 socket_close(sock);
167 return -1; 177 return -1;
@@ -259,10 +269,14 @@ int socket_connect_unix(const char *filename)
259} 269}
260#endif 270#endif
261 271
262int socket_create(uint16_t port) 272int socket_create(const char* addr, uint16_t port)
263{ 273{
264 int sfd = -1; 274 int sfd = -1;
265 int yes = 1; 275 int yes = 1;
276 struct addrinfo hints;
277 struct addrinfo *result, *rp;
278 char portstr[8];
279 int res;
266#ifdef WIN32 280#ifdef WIN32
267 WSADATA wsa_data; 281 WSADATA wsa_data;
268 if (!wsa_init) { 282 if (!wsa_init) {
@@ -273,41 +287,69 @@ int socket_create(uint16_t port)
273 wsa_init = 1; 287 wsa_init = 1;
274 } 288 }
275#endif 289#endif
276 struct sockaddr_in saddr;
277 290
278 if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) { 291 memset(&hints, '\0', sizeof(struct addrinfo));
279 perror("socket()"); 292 hints.ai_family = AF_UNSPEC;
280 return -1; 293 hints.ai_socktype = SOCK_STREAM;
281 } 294 hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
295 hints.ai_protocol = IPPROTO_TCP;
282 296
283 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) { 297 sprintf(portstr, "%d", port);
284 perror("setsockopt()"); 298
285 socket_close(sfd); 299 if (!addr) {
300 addr = "localhost";
301 }
302 res = getaddrinfo(addr, portstr, &hints, &result);
303 if (res != 0) {
304 fprintf(stderr, "%s: getaddrinfo: %s\n", __func__, gai_strerror(res));
286 return -1; 305 return -1;
287 } 306 }
288 307
308 for (rp = result; rp != NULL; rp = rp->ai_next) {
309 sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
310 if (sfd == -1) {
311 continue;
312 }
313
314 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) {
315 perror("setsockopt()");
316 socket_close(sfd);
317 continue;
318 }
319
289#ifdef SO_NOSIGPIPE 320#ifdef SO_NOSIGPIPE
290 if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) { 321 if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
291 perror("setsockopt()"); 322 perror("setsockopt()");
292 socket_close(sfd); 323 socket_close(sfd);
293 return -1; 324 continue;
294 } 325 }
326#endif
327
328#if defined(AF_INET6) && defined(IPV6_V6ONLY)
329 if (rp->ai_family == AF_INET6) {
330 if (setsockopt(sfd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&yes, sizeof(int)) == -1) {
331 perror("setsockopt() IPV6_V6ONLY");
332 }
333 }
295#endif 334#endif
296 335
297 memset((void *) &saddr, 0, sizeof(saddr)); 336 if (bind(sfd, rp->ai_addr, rp->ai_addrlen) < 0) {
298 saddr.sin_family = AF_INET; 337 perror("bind()");
299 saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 338 socket_close(sfd);
300 saddr.sin_port = htons(port); 339 continue;
340 }
301 341
302 if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) { 342 if (listen(sfd, 100) < 0) {
303 perror("bind()"); 343 perror("listen()");
304 socket_close(sfd); 344 socket_close(sfd);
305 return -1; 345 continue;
346 }
347 break;
306 } 348 }
307 349
308 if (listen(sfd, 1) == -1) { 350 freeaddrinfo(result);
309 perror("listen()"); 351
310 socket_close(sfd); 352 if (rp == NULL) {
311 return -1; 353 return -1;
312 } 354 }
313 355
@@ -344,10 +386,308 @@ static uint32_t _in6_addr_scope(struct in6_addr* addr)
344 return scope; 386 return scope;
345} 387}
346 388
389#ifndef HAVE_GETIFADDRS
390#ifdef WIN32
391
392struct ifaddrs {
393 struct ifaddrs *ifa_next; /* Next item in list */
394 char *ifa_name; /* Name of interface */
395 unsigned int ifa_flags; /* Flags from SIOCGIFFLAGS */
396 struct sockaddr *ifa_addr; /* Address of interface */
397 struct sockaddr *ifa_netmask; /* Netmask of interface */
398 union {
399 struct sockaddr *ifu_broadaddr; /* Broadcast address of interface */
400 struct sockaddr *ifu_dstaddr; /* Point-to-point destination address */
401 } ifa_ifu;
402#define ifa_broadaddr ifa_ifu.ifu_broadaddr
403#define ifa_dstaddr ifa_ifu.ifu_dstaddr
404 void *ifa_data; /* Address-specific data */
405};
406
407#define WORKING_BUFFER_SIZE 15000
408#define MAX_TRIES 3
409
410static void freeifaddrs(struct ifaddrs *ifa)
411{
412 if (!ifa) {
413 return;
414 }
415 free(ifa->ifa_name);
416 free(ifa->ifa_addr);
417 free(ifa->ifa_netmask);
418 free(ifa->ifa_dstaddr);
419 freeifaddrs(ifa->ifa_next);
420 free(ifa);
421}
422
423/*
424 * getifaddrs() reference implementation for win32.
425 * Heavily based on openpgm's implementation found here:
426 * https://github.com/steve-o/openpgm/blob/master/openpgm/pgm/getifaddrs.c
427 */
428static int getifaddrs(struct ifaddrs** ifap)
429{
430 struct ifaddrs* ifa = NULL;
431
432 DWORD dwRetVal = 0;
433
434 PIP_ADAPTER_ADDRESSES pAddresses = NULL;
435 ULONG outBufLen = 0;
436 ULONG Iterations = 0;
437
438 ULONG flags = GAA_FLAG_INCLUDE_PREFIX |
439 GAA_FLAG_SKIP_ANYCAST |
440 GAA_FLAG_SKIP_DNS_SERVER |
441 GAA_FLAG_SKIP_FRIENDLY_NAME |
442 GAA_FLAG_SKIP_MULTICAST;
443
444 PIP_ADAPTER_ADDRESSES adapter = NULL;
445
446 if (!ifap) {
447 errno = EINVAL;
448 return -1;
449 }
450 *ifap = NULL;
451
452 outBufLen = WORKING_BUFFER_SIZE;
453 do {
454 pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);
455 if (pAddresses == NULL) {
456 printf("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n");
457 return -1;
458 }
459 dwRetVal = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);
460 if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
461 free(pAddresses);
462 pAddresses = NULL;
463 } else {
464 break;
465 }
466 Iterations++;
467 } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));
468
469 if (dwRetVal != NO_ERROR) {
470 free(pAddresses);
471 return -1;
472 }
473
474 for (adapter = pAddresses; adapter; adapter = adapter->Next) {
475 int unicastIndex = 0;
476 for (IP_ADAPTER_UNICAST_ADDRESS *unicast = adapter->FirstUnicastAddress; unicast; unicast = unicast->Next, ++unicastIndex) {
477 /* ensure IP adapter */
478 if (AF_INET != unicast->Address.lpSockaddr->sa_family && AF_INET6 != unicast->Address.lpSockaddr->sa_family) {
479 continue;
480 }
481
482 if (!ifa) {
483 ifa = malloc(sizeof(struct ifaddrs));
484 if (!ifa) {
485 errno = ENOMEM;
486 free(pAddresses);
487 return -1;
488 }
489 *ifap = ifa;
490 ifa->ifa_next = NULL;
491 } else {
492 struct ifaddrs* ifanew = malloc(sizeof(struct ifaddrs));
493 if (!ifanew) {
494 freeifaddrs(*ifap);
495 free(pAddresses);
496 errno = ENOMEM;
497 return -1;
498 }
499 ifa->ifa_next = ifanew;
500 ifa = ifanew;
501 ifa->ifa_next = NULL;
502 }
503
504 /* name */
505 ifa->ifa_name = strdup(adapter->AdapterName);
506
507 /* flags */
508 ifa->ifa_flags = 0;
509 if (IfOperStatusUp == adapter->OperStatus)
510 ifa->ifa_flags |= IFF_UP;
511 if (IF_TYPE_SOFTWARE_LOOPBACK == adapter->IfType)
512 ifa->ifa_flags |= IFF_LOOPBACK;
513 if (!(adapter->Flags & IP_ADAPTER_NO_MULTICAST))
514 ifa->ifa_flags |= IFF_MULTICAST;
515
516 /* address */
517 ifa->ifa_addr = (struct sockaddr*)malloc(sizeof(struct sockaddr_storage));
518 memcpy(ifa->ifa_addr, unicast->Address.lpSockaddr, unicast->Address.iSockaddrLength);
519
520 /* netmask */
521 ifa->ifa_netmask = (struct sockaddr*)malloc(sizeof(struct sockaddr_storage));
522 memset(ifa->ifa_netmask, 0, sizeof(struct sockaddr_storage));
523
524/* pre-Vista must hunt for matching prefix in linked list, otherwise use
525 * OnLinkPrefixLength from IP_ADAPTER_UNICAST_ADDRESS structure.
526 * FirstPrefix requires Windows XP SP1, from SP1 to pre-Vista provides a
527 * single adapter prefix for each IP address. Vista and later provides
528 * host IP address prefix, subnet IP address, and subnet broadcast IP
529 * address. In addition there is a multicast and broadcast address prefix.
530 */
531 ULONG prefixLength = 0;
532
533#if defined( _WIN32 ) && ( _WIN32_WINNT >= 0x0600 )
534/* For a unicast IPv4 address, any value greater than 32 is an illegal
535 * value. For a unicast IPv6 address, any value greater than 128 is an
536 * illegal value. A value of 255 is commonly used to represent an illegal
537 * value.
538 *
539 * Windows 7 SP1 returns 64 for Teredo links which is incorrect.
540 */
541
542#define IN6_IS_ADDR_TEREDO(addr) \
543 (((const uint32_t *)(addr))[0] == ntohl (0x20010000))
544
545 if (AF_INET6 == unicast->Address.lpSockaddr->sa_family &&
546/* TunnelType only applies to one interface on the adapter and no
547 * convenient method is provided to determine which.
548 */
549 TUNNEL_TYPE_TEREDO == adapter->TunnelType &&
550/* Test the interface with the known Teredo network prefix.
551 */
552 IN6_IS_ADDR_TEREDO( &((struct sockaddr_in6*)(unicast->Address.lpSockaddr))->sin6_addr) &&
553/* Test that this version is actually wrong, subsequent releases from Microsoft
554 * may resolve the issue.
555 */
556 32 != unicast->OnLinkPrefixLength)
557 {
558 prefixLength = 32;
559 }
560 else
561 prefixLength = unicast->OnLinkPrefixLength;
562#else
563/* The order of linked IP_ADAPTER_UNICAST_ADDRESS structures pointed to by
564 * the FirstUnicastAddress member does not have any relationship with the
565 * order of linked IP_ADAPTER_PREFIX structures pointed to by the FirstPrefix
566 * member.
567 *
568 * Example enumeration:
569 * [ no subnet ]
570 * ::1/128 - address
571 * ff00::%1/8 - multicast (no IPv6 broadcast)
572 * 127.0.0.0/8 - subnet
573 * 127.0.0.1/32 - address
574 * 127.255.255.255/32 - subnet broadcast
575 * 224.0.0.0/4 - multicast
576 * 255.255.255.255/32 - broadcast
577 *
578 * Which differs from most adapters listing three IPv6:
579 * fe80::%10/64 - subnet
580 * fe80::51e9:5fe5:4202:325a%10/128 - address
581 * ff00::%10/8 - multicast
582 *
583 * !IfOperStatusUp IPv4 addresses are skipped:
584 * fe80::%13/64 - subnet
585 * fe80::d530:946d:e8df:8c91%13/128 - address
586 * ff00::%13/8 - multicast
587 * [ no subnet ]
588 * [ no address ]
589 * 224.0.0.0/4 - multicast
590 * 255.255.255.255/32 - broadcast
591 *
592 * On PTP links no multicast or broadcast addresses are returned:
593 * [ no subnet ]
594 * fe80::5efe:10.203.9.30/128 - address
595 * [ no multicast ]
596 * [ no multicast ]
597 * [ no broadcast ]
598 *
599 * Active primary IPv6 interfaces are a bit overloaded:
600 * ::/0 - default route
601 * 2001::/32 - global subnet
602 * 2001:0:4137:9e76:2443:d6:ba87:1a2a/128 - global address
603 * fe80::/64 - link-local subnet
604 * fe80::2443:d6:ba87:1a2a/128 - link-local address
605 * ff00::/8 - multicast
606 */
607
608#define IN_LINKLOCAL(a) ((((uint32_t) (a)) & 0xaffff0000) == 0xa9fe0000)
609
610 for (IP_ADAPTER_PREFIX *prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) {
611 LPSOCKADDR lpSockaddr = prefix->Address.lpSockaddr;
612 if (lpSockaddr->sa_family != unicast->Address.lpSockaddr->sa_family)
613 continue;
614/* special cases */
615/* RFC2863: IPv4 interface not up */
616 if (AF_INET == lpSockaddr->sa_family && adapter->OperStatus != IfOperStatusUp) {
617/* RFC3927: link-local IPv4 always has 16-bit CIDR */
618 if (IN_LINKLOCAL( ntohl (((struct sockaddr_in*)(unicast->Address.lpSockaddr))->sin_addr.s_addr))) {
619 prefixLength = 16;
620 }
621 break;
622 }
623/* default IPv6 route */
624 if (AF_INET6 == lpSockaddr->sa_family && 0 == prefix->PrefixLength && IN6_IS_ADDR_UNSPECIFIED( &((struct sockaddr_in6*)(lpSockaddr))->sin6_addr)) {
625 continue;
626 }
627/* Assume unicast address for first prefix of operational adapter */
628 if (AF_INET == lpSockaddr->sa_family)
629 if (IN_MULTICAST( ntohl (((struct sockaddr_in*)(lpSockaddr))->sin_addr.s_addr))) {
630 fprintf(stderr, "FATAL: first prefix is non a unicast address\n");
631 break;
632 }
633 if (AF_INET6 == lpSockaddr->sa_family)
634 if (IN6_IS_ADDR_MULTICAST( &((struct sockaddr_in6*)(lpSockaddr))->sin6_addr)) {
635 fprintf(stderr, "FATAL: first prefix is not a unicast address\n");
636 break;
637 }
638/* Assume subnet or host IP address for XP backward compatibility */
639
640 prefixLength = prefix->PrefixLength;
641 break;
642 }
643#endif /* defined( _WIN32 ) && ( _WIN32_WINNT >= 0x0600 ) */
644
645/* map prefix to netmask */
646 ifa->ifa_netmask->sa_family = unicast->Address.lpSockaddr->sa_family;
647 switch (unicast->Address.lpSockaddr->sa_family) {
648 case AF_INET:
649 if (0 == prefixLength || prefixLength > 32) {
650 prefixLength = 32;
651 }
652#if defined( _WIN32) && ( _WIN32_WINNT >= 0x0600 )
653/* Added in Vista, but no IPv6 equivalent. */
654 {
655 ULONG Mask;
656 ConvertLengthToIpv4Mask (prefixLength, &Mask);
657 ((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr = Mask; /* network order */
658 }
659#else
660/* NB: left-shift of full bit-width is undefined in C standard. */
661 ((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr = htonl( 0xffffffffU << ( 32 - prefixLength ) );
662#endif
663 break;
664
665 case AF_INET6:
666 if (0 == prefixLength || prefixLength > 128) {
667 prefixLength = 128;
668 }
669 for (LONG i = prefixLength, j = 0; i > 0; i -= 8, ++j) {
670 ((struct sockaddr_in6*)ifa->ifa_netmask)->sin6_addr.s6_addr[ j ] = i >= 8 ? 0xff : (ULONG)(( 0xffU << ( 8 - i ) ) & 0xffU );
671 }
672 break;
673 default:
674 break;
675 }
676 }
677 }
678 free(pAddresses);
679
680 return 0;
681}
682#else
683#error No reference implementation for getifaddrs available for this platform.
684#endif
685#endif
686
347static int32_t _sockaddr_in6_scope_id(struct sockaddr_in6* addr) 687static int32_t _sockaddr_in6_scope_id(struct sockaddr_in6* addr)
348{ 688{
349 int32_t res = -1; 689 int32_t res = -1;
350 struct ifaddrs *ifaddr, *ifa; 690 struct ifaddrs *ifaddr = NULL, *ifa = NULL;
351 uint32_t addr_scope; 691 uint32_t addr_scope;
352 692
353 /* get scope for requested address */ 693 /* get scope for requested address */
@@ -398,14 +738,14 @@ static int32_t _sockaddr_in6_scope_id(struct sockaddr_in6* addr)
398 if (addr->sin6_scope_id == addr_in->sin6_scope_id) { 738 if (addr->sin6_scope_id == addr_in->sin6_scope_id) {
399 res = addr_in->sin6_scope_id; 739 res = addr_in->sin6_scope_id;
400 break; 740 break;
401 } else {
402 if ((addr_in->sin6_scope_id > addr->sin6_scope_id) && (res >= 0)) {
403 // use last valid scope id as we're past the requested scope id
404 break;
405 }
406 res = addr_in->sin6_scope_id;
407 continue;
408 } 741 }
742
743 if ((addr_in->sin6_scope_id > addr->sin6_scope_id) && (res >= 0)) {
744 // use last valid scope id as we're past the requested scope id
745 break;
746 }
747 res = addr_in->sin6_scope_id;
748 continue;
409 } 749 }
410 750
411 /* skip loopback interface if not already matched exactly above */ 751 /* skip loopback interface if not already matched exactly above */
@@ -594,7 +934,7 @@ int socket_connect(const char *addr, uint16_t port)
594 memset(&hints, '\0', sizeof(struct addrinfo)); 934 memset(&hints, '\0', sizeof(struct addrinfo));
595 hints.ai_family = AF_UNSPEC; 935 hints.ai_family = AF_UNSPEC;
596 hints.ai_socktype = SOCK_STREAM; 936 hints.ai_socktype = SOCK_STREAM;
597 hints.ai_flags = 0; 937 hints.ai_flags = AI_NUMERICSERV;
598 hints.ai_protocol = IPPROTO_TCP; 938 hints.ai_protocol = IPPROTO_TCP;
599 939
600 sprintf(portstr, "%d", port); 940 sprintf(portstr, "%d", port);
@@ -761,14 +1101,9 @@ int socket_accept(int fd, uint16_t port)
761 socklen_t addr_len; 1101 socklen_t addr_len;
762#endif 1102#endif
763 int result; 1103 int result;
764 struct sockaddr_in addr; 1104 struct sockaddr_storage addr;
765
766 memset(&addr, 0, sizeof(addr));
767 addr.sin_family = AF_INET;
768 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
769 addr.sin_port = htons(port);
770
771 addr_len = sizeof(addr); 1105 addr_len = sizeof(addr);
1106
772 result = accept(fd, (struct sockaddr*)&addr, &addr_len); 1107 result = accept(fd, (struct sockaddr*)&addr, &addr_len);
773 1108
774 return result; 1109 return result;
@@ -825,6 +1160,10 @@ int socket_receive_timeout(int fd, void *data, size_t length, int flags,
825int socket_send(int fd, void *data, size_t length) 1160int socket_send(int fd, void *data, size_t length)
826{ 1161{
827 int flags = 0; 1162 int flags = 0;
1163 int res = socket_check_fd(fd, FDM_WRITE, SEND_TIMEOUT);
1164 if (res <= 0) {
1165 return res;
1166 }
828#ifdef MSG_NOSIGNAL 1167#ifdef MSG_NOSIGNAL
829 flags |= MSG_NOSIGNAL; 1168 flags |= MSG_NOSIGNAL;
830#endif 1169#endif