diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/socket.c | 423 | ||||
| -rw-r--r-- | common/socket.h | 10 |
2 files changed, 386 insertions, 47 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 | ||
| 37 | static int wsa_init = 0; | 40 | static 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 | ||
| 262 | int socket_create(uint16_t port) | 272 | int 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 | |||
| 392 | struct 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 | |||
| 410 | static 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 | */ | ||
| 428 | static 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 | |||
| 347 | static int32_t _sockaddr_in6_scope_id(struct sockaddr_in6* addr) | 687 | static 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, | |||
| 825 | int socket_send(int fd, void *data, size_t length) | 1160 | int 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 |
diff --git a/common/socket.h b/common/socket.h index 38eeddf..9567270 100644 --- a/common/socket.h +++ b/common/socket.h | |||
| @@ -45,7 +45,7 @@ typedef enum fd_mode fd_mode; | |||
| 45 | int socket_create_unix(const char *filename); | 45 | int socket_create_unix(const char *filename); |
| 46 | int socket_connect_unix(const char *filename); | 46 | int socket_connect_unix(const char *filename); |
| 47 | #endif | 47 | #endif |
| 48 | int socket_create(uint16_t port); | 48 | int socket_create(const char *addr, uint16_t port); |
| 49 | int socket_connect_addr(struct sockaddr *addr, uint16_t port); | 49 | int socket_connect_addr(struct sockaddr *addr, uint16_t port); |
| 50 | int socket_connect(const char *addr, uint16_t port); | 50 | int socket_connect(const char *addr, uint16_t port); |
| 51 | int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout); | 51 | int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout); |
| @@ -54,12 +54,12 @@ int socket_accept(int fd, uint16_t port); | |||
| 54 | int socket_shutdown(int fd, int how); | 54 | int socket_shutdown(int fd, int how); |
| 55 | int socket_close(int fd); | 55 | int socket_close(int fd); |
| 56 | 56 | ||
| 57 | int socket_receive(int fd, void *data, size_t size); | 57 | int socket_receive(int fd, void *data, size_t length); |
| 58 | int socket_peek(int fd, void *data, size_t size); | 58 | int socket_peek(int fd, void *data, size_t length); |
| 59 | int socket_receive_timeout(int fd, void *data, size_t size, int flags, | 59 | int socket_receive_timeout(int fd, void *data, size_t length, int flags, |
| 60 | unsigned int timeout); | 60 | unsigned int timeout); |
| 61 | 61 | ||
| 62 | int socket_send(int fd, void *data, size_t size); | 62 | int socket_send(int fd, void *data, size_t length); |
| 63 | 63 | ||
| 64 | void socket_set_verbose(int level); | 64 | void socket_set_verbose(int level); |
| 65 | 65 | ||
