This extracts a lot of the helper functions that do not
actually work on sockets, but instead on addresses or
similar.
This includes
- openvpn_getaddrinfo and related functions
- print_*
- setenv_*
And lots of the inline functions.
This move will make it easier to add unit tests
for these moved functions.
Change-Id: I7393459b975fb9b3e0a42743f58645f769d1be5a
Signed-off-by: Frank Lichtenheld <frank@lichtenheld.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20250831155939.29240-1-gert@greenie.muc.de>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg32727.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
| ... | ... |
@@ -72,27 +72,6 @@ set_std_files_to_null(bool stdin_only) |
| 72 | 72 |
#endif |
| 73 | 73 |
} |
| 74 | 74 |
|
| 75 |
-/* |
|
| 76 |
- * Prepend a random string to hostname to prevent DNS caching. |
|
| 77 |
- * For example, foo.bar.gov would be modified to <random-chars>.foo.bar.gov. |
|
| 78 |
- * Of course, this requires explicit support in the DNS server (wildcard). |
|
| 79 |
- */ |
|
| 80 |
-const char * |
|
| 81 |
-hostname_randomize(const char *hostname, struct gc_arena *gc) |
|
| 82 |
-{
|
|
| 83 |
-#define n_rnd_bytes 6 |
|
| 84 |
- |
|
| 85 |
- uint8_t rnd_bytes[n_rnd_bytes]; |
|
| 86 |
- const char *rnd_str; |
|
| 87 |
- struct buffer hname = alloc_buf_gc(strlen(hostname) + sizeof(rnd_bytes) * 2 + 4, gc); |
|
| 88 |
- |
|
| 89 |
- prng_bytes(rnd_bytes, sizeof(rnd_bytes)); |
|
| 90 |
- rnd_str = format_hex_ex(rnd_bytes, sizeof(rnd_bytes), 40, 0, NULL, gc); |
|
| 91 |
- buf_printf(&hname, "%s.%s", rnd_str, hostname); |
|
| 92 |
- return BSTR(&hname); |
|
| 93 |
-#undef n_rnd_bytes |
|
| 94 |
-} |
|
| 95 |
- |
|
| 96 | 75 |
#ifdef ENABLE_MANAGEMENT |
| 97 | 76 |
/* Get username/password from the management interface */ |
| 98 | 77 |
static bool |
| ... | ... |
@@ -44,9 +44,6 @@ const char **make_arg_array(const char *first, const char *parms, struct gc_aren |
| 44 | 44 |
|
| 45 | 45 |
const char **make_extended_arg_array(char **p, bool is_inline, struct gc_arena *gc); |
| 46 | 46 |
|
| 47 |
-/* prepend a random prefix to hostname */ |
|
| 48 |
-const char *hostname_randomize(const char *hostname, struct gc_arena *gc); |
|
| 49 |
- |
|
| 50 | 47 |
/* |
| 51 | 48 |
* Get and store a username/password |
| 52 | 49 |
*/ |
| ... | ... |
@@ -405,428 +405,6 @@ err: |
| 405 | 405 |
throw_signal_soft(SIGHUP, "Preresolving failed"); |
| 406 | 406 |
} |
| 407 | 407 |
|
| 408 |
-/** |
|
| 409 |
- * Small helper function for openvpn_getaddrinfo to print the address |
|
| 410 |
- * family when resolving fails |
|
| 411 |
- */ |
|
| 412 |
-static const char * |
|
| 413 |
-getaddrinfo_addr_family_name(int af) |
|
| 414 |
-{
|
|
| 415 |
- switch (af) |
|
| 416 |
- {
|
|
| 417 |
- case AF_INET: |
|
| 418 |
- return "[AF_INET]"; |
|
| 419 |
- |
|
| 420 |
- case AF_INET6: |
|
| 421 |
- return "[AF_INET6]"; |
|
| 422 |
- } |
|
| 423 |
- return ""; |
|
| 424 |
-} |
|
| 425 |
- |
|
| 426 |
-/* |
|
| 427 |
- * Translate IPv4/IPv6 addr or hostname into struct addrinfo |
|
| 428 |
- * If resolve error, try again for resolve_retry_seconds seconds. |
|
| 429 |
- */ |
|
| 430 |
-int |
|
| 431 |
-openvpn_getaddrinfo(unsigned int flags, const char *hostname, const char *servname, |
|
| 432 |
- int resolve_retry_seconds, struct signal_info *sig_info, int ai_family, |
|
| 433 |
- struct addrinfo **res) |
|
| 434 |
-{
|
|
| 435 |
- struct addrinfo hints; |
|
| 436 |
- int status; |
|
| 437 |
- struct signal_info sigrec = { 0 };
|
|
| 438 |
- int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS; |
|
| 439 |
- struct gc_arena gc = gc_new(); |
|
| 440 |
- const char *print_hostname; |
|
| 441 |
- const char *print_servname; |
|
| 442 |
- |
|
| 443 |
- ASSERT(res); |
|
| 444 |
- |
|
| 445 |
- ASSERT(hostname || servname); |
|
| 446 |
- ASSERT(!(flags & GETADDR_HOST_ORDER)); |
|
| 447 |
- |
|
| 448 |
- if (servname) |
|
| 449 |
- {
|
|
| 450 |
- print_servname = servname; |
|
| 451 |
- } |
|
| 452 |
- else |
|
| 453 |
- {
|
|
| 454 |
- print_servname = ""; |
|
| 455 |
- } |
|
| 456 |
- |
|
| 457 |
- if (flags & GETADDR_MSG_VIRT_OUT) |
|
| 458 |
- {
|
|
| 459 |
- msglevel |= M_MSG_VIRT_OUT; |
|
| 460 |
- } |
|
| 461 |
- |
|
| 462 |
- if ((flags & (GETADDR_FATAL_ON_SIGNAL | GETADDR_WARN_ON_SIGNAL)) && !sig_info) |
|
| 463 |
- {
|
|
| 464 |
- sig_info = &sigrec; |
|
| 465 |
- } |
|
| 466 |
- |
|
| 467 |
- /* try numeric ip addr first */ |
|
| 468 |
- CLEAR(hints); |
|
| 469 |
- hints.ai_flags = AI_NUMERICHOST; |
|
| 470 |
- |
|
| 471 |
- if (flags & GETADDR_PASSIVE) |
|
| 472 |
- {
|
|
| 473 |
- hints.ai_flags |= AI_PASSIVE; |
|
| 474 |
- } |
|
| 475 |
- |
|
| 476 |
- if (flags & GETADDR_DATAGRAM) |
|
| 477 |
- {
|
|
| 478 |
- hints.ai_socktype = SOCK_DGRAM; |
|
| 479 |
- } |
|
| 480 |
- else |
|
| 481 |
- {
|
|
| 482 |
- hints.ai_socktype = SOCK_STREAM; |
|
| 483 |
- } |
|
| 484 |
- |
|
| 485 |
- /* if hostname is not set, we want to bind to 'ANY', with |
|
| 486 |
- * the correct address family - v4-only or v6/v6-dual-stack */ |
|
| 487 |
- if (!hostname) |
|
| 488 |
- {
|
|
| 489 |
- hints.ai_family = ai_family; |
|
| 490 |
- } |
|
| 491 |
- |
|
| 492 |
- status = getaddrinfo(hostname, servname, &hints, res); |
|
| 493 |
- |
|
| 494 |
- if (status != 0) /* parse as numeric address failed? */ |
|
| 495 |
- {
|
|
| 496 |
- const int fail_wait_interval = 5; /* seconds */ |
|
| 497 |
- /* Add +4 to cause integer division rounding up (1 + 4) = 5, (0+4)/5=0 */ |
|
| 498 |
- int resolve_retries = |
|
| 499 |
- (flags & GETADDR_TRY_ONCE) ? 1 : ((resolve_retry_seconds + 4) / fail_wait_interval); |
|
| 500 |
- const char *fmt; |
|
| 501 |
- int level = 0; |
|
| 502 |
- |
|
| 503 |
- /* this is not a numeric IP, therefore force resolution using the |
|
| 504 |
- * provided ai_family */ |
|
| 505 |
- hints.ai_family = ai_family; |
|
| 506 |
- |
|
| 507 |
- if (hostname && (flags & GETADDR_RANDOMIZE)) |
|
| 508 |
- {
|
|
| 509 |
- hostname = hostname_randomize(hostname, &gc); |
|
| 510 |
- } |
|
| 511 |
- |
|
| 512 |
- if (hostname) |
|
| 513 |
- {
|
|
| 514 |
- print_hostname = hostname; |
|
| 515 |
- } |
|
| 516 |
- else |
|
| 517 |
- {
|
|
| 518 |
- print_hostname = "undefined"; |
|
| 519 |
- } |
|
| 520 |
- |
|
| 521 |
- fmt = "RESOLVE: Cannot resolve host address: %s:%s%s (%s)"; |
|
| 522 |
- if ((flags & GETADDR_MENTION_RESOLVE_RETRY) && !resolve_retry_seconds) |
|
| 523 |
- {
|
|
| 524 |
- fmt = "RESOLVE: Cannot resolve host address: %s:%s%s (%s)" |
|
| 525 |
- "(I would have retried this name query if you had " |
|
| 526 |
- "specified the --resolv-retry option.)"; |
|
| 527 |
- } |
|
| 528 |
- |
|
| 529 |
- if (!(flags & GETADDR_RESOLVE) || status == EAI_FAIL) |
|
| 530 |
- {
|
|
| 531 |
- msg(msglevel, "RESOLVE: Cannot parse IP address: %s:%s (%s)", print_hostname, |
|
| 532 |
- print_servname, gai_strerror(status)); |
|
| 533 |
- goto done; |
|
| 534 |
- } |
|
| 535 |
- |
|
| 536 |
-#ifdef ENABLE_MANAGEMENT |
|
| 537 |
- if (flags & GETADDR_UPDATE_MANAGEMENT_STATE) |
|
| 538 |
- {
|
|
| 539 |
- if (management) |
|
| 540 |
- {
|
|
| 541 |
- management_set_state(management, OPENVPN_STATE_RESOLVE, NULL, NULL, NULL, NULL, |
|
| 542 |
- NULL); |
|
| 543 |
- } |
|
| 544 |
- } |
|
| 545 |
-#endif |
|
| 546 |
- |
|
| 547 |
- /* |
|
| 548 |
- * Resolve hostname |
|
| 549 |
- */ |
|
| 550 |
- while (true) |
|
| 551 |
- {
|
|
| 552 |
-#ifndef _WIN32 |
|
| 553 |
- /* force resolv.conf reload */ |
|
| 554 |
- res_init(); |
|
| 555 |
-#endif |
|
| 556 |
- /* try hostname lookup */ |
|
| 557 |
- hints.ai_flags &= ~AI_NUMERICHOST; |
|
| 558 |
- dmsg(D_SOCKET_DEBUG, "GETADDRINFO flags=0x%04x ai_family=%d ai_socktype=%d", flags, |
|
| 559 |
- hints.ai_family, hints.ai_socktype); |
|
| 560 |
- status = getaddrinfo(hostname, servname, &hints, res); |
|
| 561 |
- |
|
| 562 |
- if (sig_info) |
|
| 563 |
- {
|
|
| 564 |
- get_signal(&sig_info->signal_received); |
|
| 565 |
- if (sig_info->signal_received) /* were we interrupted by a signal? */ |
|
| 566 |
- {
|
|
| 567 |
- /* why are we overwriting SIGUSR1 ? */ |
|
| 568 |
- if (signal_reset(sig_info, SIGUSR1) == SIGUSR1) /* ignore SIGUSR1 */ |
|
| 569 |
- {
|
|
| 570 |
- msg(level, "RESOLVE: Ignored SIGUSR1 signal received during " |
|
| 571 |
- "DNS resolution attempt"); |
|
| 572 |
- } |
|
| 573 |
- else |
|
| 574 |
- {
|
|
| 575 |
- /* turn success into failure (interrupted syscall) */ |
|
| 576 |
- if (0 == status) |
|
| 577 |
- {
|
|
| 578 |
- ASSERT(res); |
|
| 579 |
- freeaddrinfo(*res); |
|
| 580 |
- *res = NULL; |
|
| 581 |
- status = EAI_AGAIN; /* = temporary failure */ |
|
| 582 |
- errno = EINTR; |
|
| 583 |
- } |
|
| 584 |
- goto done; |
|
| 585 |
- } |
|
| 586 |
- } |
|
| 587 |
- } |
|
| 588 |
- |
|
| 589 |
- /* success? */ |
|
| 590 |
- if (0 == status) |
|
| 591 |
- {
|
|
| 592 |
- break; |
|
| 593 |
- } |
|
| 594 |
- |
|
| 595 |
- /* resolve lookup failed, should we |
|
| 596 |
- * continue or fail? */ |
|
| 597 |
- level = msglevel; |
|
| 598 |
- if (resolve_retries > 0) |
|
| 599 |
- {
|
|
| 600 |
- level = D_RESOLVE_ERRORS; |
|
| 601 |
- } |
|
| 602 |
- |
|
| 603 |
- msg(level, fmt, print_hostname, print_servname, getaddrinfo_addr_family_name(ai_family), |
|
| 604 |
- gai_strerror(status)); |
|
| 605 |
- |
|
| 606 |
- if (--resolve_retries <= 0) |
|
| 607 |
- {
|
|
| 608 |
- goto done; |
|
| 609 |
- } |
|
| 610 |
- |
|
| 611 |
- management_sleep(fail_wait_interval); |
|
| 612 |
- } |
|
| 613 |
- |
|
| 614 |
- ASSERT(res); |
|
| 615 |
- |
|
| 616 |
- /* hostname resolve succeeded */ |
|
| 617 |
- |
|
| 618 |
- /* |
|
| 619 |
- * Do not choose an IP Addresse by random or change the order * |
|
| 620 |
- * of IP addresses, doing so will break RFC 3484 address selection * |
|
| 621 |
- */ |
|
| 622 |
- } |
|
| 623 |
- else |
|
| 624 |
- {
|
|
| 625 |
- /* IP address parse succeeded */ |
|
| 626 |
- if (flags & GETADDR_RANDOMIZE) |
|
| 627 |
- {
|
|
| 628 |
- msg(M_WARN, "WARNING: ignoring --remote-random-hostname because the " |
|
| 629 |
- "hostname is an IP address"); |
|
| 630 |
- } |
|
| 631 |
- } |
|
| 632 |
- |
|
| 633 |
-done: |
|
| 634 |
- if (sig_info && sig_info->signal_received) |
|
| 635 |
- {
|
|
| 636 |
- int level = 0; |
|
| 637 |
- if (flags & GETADDR_FATAL_ON_SIGNAL) |
|
| 638 |
- {
|
|
| 639 |
- level = M_FATAL; |
|
| 640 |
- } |
|
| 641 |
- else if (flags & GETADDR_WARN_ON_SIGNAL) |
|
| 642 |
- {
|
|
| 643 |
- level = M_WARN; |
|
| 644 |
- } |
|
| 645 |
- msg(level, "RESOLVE: signal received during DNS resolution attempt"); |
|
| 646 |
- } |
|
| 647 |
- |
|
| 648 |
- gc_free(&gc); |
|
| 649 |
- return status; |
|
| 650 |
-} |
|
| 651 |
- |
|
| 652 |
-/* |
|
| 653 |
- * We do our own inet_aton because the glibc function |
|
| 654 |
- * isn't very good about error checking. |
|
| 655 |
- */ |
|
| 656 |
-int |
|
| 657 |
-openvpn_inet_aton(const char *dotted_quad, struct in_addr *addr) |
|
| 658 |
-{
|
|
| 659 |
- unsigned int a, b, c, d; |
|
| 660 |
- |
|
| 661 |
- CLEAR(*addr); |
|
| 662 |
- if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) == 4) |
|
| 663 |
- {
|
|
| 664 |
- if (a < 256 && b < 256 && c < 256 && d < 256) |
|
| 665 |
- {
|
|
| 666 |
- addr->s_addr = htonl(a << 24 | b << 16 | c << 8 | d); |
|
| 667 |
- return OIA_IP; /* good dotted quad */ |
|
| 668 |
- } |
|
| 669 |
- } |
|
| 670 |
- if (string_class(dotted_quad, CC_DIGIT | CC_DOT, 0)) |
|
| 671 |
- {
|
|
| 672 |
- return OIA_ERROR; /* probably a badly formatted dotted quad */ |
|
| 673 |
- } |
|
| 674 |
- else |
|
| 675 |
- {
|
|
| 676 |
- return OIA_HOSTNAME; /* probably a hostname */ |
|
| 677 |
- } |
|
| 678 |
-} |
|
| 679 |
- |
|
| 680 |
-bool |
|
| 681 |
-ip_addr_dotted_quad_safe(const char *dotted_quad) |
|
| 682 |
-{
|
|
| 683 |
- /* verify non-NULL */ |
|
| 684 |
- if (!dotted_quad) |
|
| 685 |
- {
|
|
| 686 |
- return false; |
|
| 687 |
- } |
|
| 688 |
- |
|
| 689 |
- /* verify length is within limits */ |
|
| 690 |
- if (strlen(dotted_quad) > 15) |
|
| 691 |
- {
|
|
| 692 |
- return false; |
|
| 693 |
- } |
|
| 694 |
- |
|
| 695 |
- /* verify that all chars are either numeric or '.' and that no numeric |
|
| 696 |
- * substring is greater than 3 chars */ |
|
| 697 |
- {
|
|
| 698 |
- int nnum = 0; |
|
| 699 |
- const char *p = dotted_quad; |
|
| 700 |
- int c; |
|
| 701 |
- |
|
| 702 |
- while ((c = *p++)) |
|
| 703 |
- {
|
|
| 704 |
- if (c >= '0' && c <= '9') |
|
| 705 |
- {
|
|
| 706 |
- ++nnum; |
|
| 707 |
- if (nnum > 3) |
|
| 708 |
- {
|
|
| 709 |
- return false; |
|
| 710 |
- } |
|
| 711 |
- } |
|
| 712 |
- else if (c == '.') |
|
| 713 |
- {
|
|
| 714 |
- nnum = 0; |
|
| 715 |
- } |
|
| 716 |
- else |
|
| 717 |
- {
|
|
| 718 |
- return false; |
|
| 719 |
- } |
|
| 720 |
- } |
|
| 721 |
- } |
|
| 722 |
- |
|
| 723 |
- /* verify that string will convert to IP address */ |
|
| 724 |
- {
|
|
| 725 |
- struct in_addr a; |
|
| 726 |
- return openvpn_inet_aton(dotted_quad, &a) == OIA_IP; |
|
| 727 |
- } |
|
| 728 |
-} |
|
| 729 |
- |
|
| 730 |
-bool |
|
| 731 |
-ipv6_addr_safe(const char *ipv6_text_addr) |
|
| 732 |
-{
|
|
| 733 |
- /* verify non-NULL */ |
|
| 734 |
- if (!ipv6_text_addr) |
|
| 735 |
- {
|
|
| 736 |
- return false; |
|
| 737 |
- } |
|
| 738 |
- |
|
| 739 |
- /* verify length is within limits */ |
|
| 740 |
- if (strlen(ipv6_text_addr) > INET6_ADDRSTRLEN) |
|
| 741 |
- {
|
|
| 742 |
- return false; |
|
| 743 |
- } |
|
| 744 |
- |
|
| 745 |
- /* verify that string will convert to IPv6 address */ |
|
| 746 |
- {
|
|
| 747 |
- struct in6_addr a6; |
|
| 748 |
- return inet_pton(AF_INET6, ipv6_text_addr, &a6) == 1; |
|
| 749 |
- } |
|
| 750 |
-} |
|
| 751 |
- |
|
| 752 |
-static bool |
|
| 753 |
-dns_addr_safe(const char *addr) |
|
| 754 |
-{
|
|
| 755 |
- if (addr) |
|
| 756 |
- {
|
|
| 757 |
- const size_t len = strlen(addr); |
|
| 758 |
- return len > 0 && len <= 255 && string_class(addr, CC_ALNUM | CC_DASH | CC_DOT, 0); |
|
| 759 |
- } |
|
| 760 |
- else |
|
| 761 |
- {
|
|
| 762 |
- return false; |
|
| 763 |
- } |
|
| 764 |
-} |
|
| 765 |
- |
|
| 766 |
-bool |
|
| 767 |
-ip_or_dns_addr_safe(const char *addr, const bool allow_fqdn) |
|
| 768 |
-{
|
|
| 769 |
- if (ip_addr_dotted_quad_safe(addr)) |
|
| 770 |
- {
|
|
| 771 |
- return true; |
|
| 772 |
- } |
|
| 773 |
- else if (allow_fqdn) |
|
| 774 |
- {
|
|
| 775 |
- return dns_addr_safe(addr); |
|
| 776 |
- } |
|
| 777 |
- else |
|
| 778 |
- {
|
|
| 779 |
- return false; |
|
| 780 |
- } |
|
| 781 |
-} |
|
| 782 |
- |
|
| 783 |
-bool |
|
| 784 |
-mac_addr_safe(const char *mac_addr) |
|
| 785 |
-{
|
|
| 786 |
- /* verify non-NULL */ |
|
| 787 |
- if (!mac_addr) |
|
| 788 |
- {
|
|
| 789 |
- return false; |
|
| 790 |
- } |
|
| 791 |
- |
|
| 792 |
- /* verify length is within limits */ |
|
| 793 |
- if (strlen(mac_addr) > 17) |
|
| 794 |
- {
|
|
| 795 |
- return false; |
|
| 796 |
- } |
|
| 797 |
- |
|
| 798 |
- /* verify that all chars are either alphanumeric or ':' and that no |
|
| 799 |
- * alphanumeric substring is greater than 2 chars */ |
|
| 800 |
- {
|
|
| 801 |
- int nnum = 0; |
|
| 802 |
- const char *p = mac_addr; |
|
| 803 |
- int c; |
|
| 804 |
- |
|
| 805 |
- while ((c = *p++)) |
|
| 806 |
- {
|
|
| 807 |
- if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) |
|
| 808 |
- {
|
|
| 809 |
- ++nnum; |
|
| 810 |
- if (nnum > 2) |
|
| 811 |
- {
|
|
| 812 |
- return false; |
|
| 813 |
- } |
|
| 814 |
- } |
|
| 815 |
- else if (c == ':') |
|
| 816 |
- {
|
|
| 817 |
- nnum = 0; |
|
| 818 |
- } |
|
| 819 |
- else |
|
| 820 |
- {
|
|
| 821 |
- return false; |
|
| 822 |
- } |
|
| 823 |
- } |
|
| 824 |
- } |
|
| 825 |
- |
|
| 826 |
- /* error-checking is left to script invoked in lladdr.c */ |
|
| 827 |
- return true; |
|
| 828 |
-} |
|
| 829 |
- |
|
| 830 | 408 |
static int |
| 831 | 409 |
socket_get_sndbuf(socket_descriptor_t sd) |
| 832 | 410 |
{
|
| ... | ... |
@@ -2670,467 +2248,6 @@ socket_listen_event_handle(struct link_socket *s) |
| 2670 | 2670 |
#endif |
| 2671 | 2671 |
} |
| 2672 | 2672 |
|
| 2673 |
-/* |
|
| 2674 |
- * Format IP addresses in ascii |
|
| 2675 |
- */ |
|
| 2676 |
- |
|
| 2677 |
-const char * |
|
| 2678 |
-print_sockaddr_ex(const struct sockaddr *sa, const char *separator, const unsigned int flags, |
|
| 2679 |
- struct gc_arena *gc) |
|
| 2680 |
-{
|
|
| 2681 |
- struct buffer out = alloc_buf_gc(128, gc); |
|
| 2682 |
- bool addr_is_defined = false; |
|
| 2683 |
- char hostaddr[NI_MAXHOST] = ""; |
|
| 2684 |
- char servname[NI_MAXSERV] = ""; |
|
| 2685 |
- int status; |
|
| 2686 |
- |
|
| 2687 |
- socklen_t salen = 0; |
|
| 2688 |
- switch (sa->sa_family) |
|
| 2689 |
- {
|
|
| 2690 |
- case AF_INET: |
|
| 2691 |
- if (!(flags & PS_DONT_SHOW_FAMILY)) |
|
| 2692 |
- {
|
|
| 2693 |
- buf_puts(&out, "[AF_INET]"); |
|
| 2694 |
- } |
|
| 2695 |
- salen = sizeof(struct sockaddr_in); |
|
| 2696 |
- addr_is_defined = ((struct sockaddr_in *)sa)->sin_addr.s_addr != 0; |
|
| 2697 |
- break; |
|
| 2698 |
- |
|
| 2699 |
- case AF_INET6: |
|
| 2700 |
- if (!(flags & PS_DONT_SHOW_FAMILY)) |
|
| 2701 |
- {
|
|
| 2702 |
- buf_puts(&out, "[AF_INET6]"); |
|
| 2703 |
- } |
|
| 2704 |
- salen = sizeof(struct sockaddr_in6); |
|
| 2705 |
- addr_is_defined = !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)sa)->sin6_addr); |
|
| 2706 |
- break; |
|
| 2707 |
- |
|
| 2708 |
- case AF_UNSPEC: |
|
| 2709 |
- if (!(flags & PS_DONT_SHOW_FAMILY)) |
|
| 2710 |
- {
|
|
| 2711 |
- return "[AF_UNSPEC]"; |
|
| 2712 |
- } |
|
| 2713 |
- else |
|
| 2714 |
- {
|
|
| 2715 |
- return ""; |
|
| 2716 |
- } |
|
| 2717 |
- |
|
| 2718 |
- default: |
|
| 2719 |
- ASSERT(0); |
|
| 2720 |
- } |
|
| 2721 |
- |
|
| 2722 |
- status = getnameinfo(sa, salen, hostaddr, sizeof(hostaddr), servname, sizeof(servname), |
|
| 2723 |
- NI_NUMERICHOST | NI_NUMERICSERV); |
|
| 2724 |
- |
|
| 2725 |
- if (status != 0) |
|
| 2726 |
- {
|
|
| 2727 |
- buf_printf(&out, "[nameinfo() err: %s]", gai_strerror(status)); |
|
| 2728 |
- return BSTR(&out); |
|
| 2729 |
- } |
|
| 2730 |
- |
|
| 2731 |
- if (!(flags & PS_DONT_SHOW_ADDR)) |
|
| 2732 |
- {
|
|
| 2733 |
- if (addr_is_defined) |
|
| 2734 |
- {
|
|
| 2735 |
- buf_puts(&out, hostaddr); |
|
| 2736 |
- } |
|
| 2737 |
- else |
|
| 2738 |
- {
|
|
| 2739 |
- buf_puts(&out, "[undef]"); |
|
| 2740 |
- } |
|
| 2741 |
- } |
|
| 2742 |
- |
|
| 2743 |
- if ((flags & PS_SHOW_PORT) || (flags & PS_SHOW_PORT_IF_DEFINED)) |
|
| 2744 |
- {
|
|
| 2745 |
- if (separator) |
|
| 2746 |
- {
|
|
| 2747 |
- buf_puts(&out, separator); |
|
| 2748 |
- } |
|
| 2749 |
- |
|
| 2750 |
- buf_puts(&out, servname); |
|
| 2751 |
- } |
|
| 2752 |
- |
|
| 2753 |
- return BSTR(&out); |
|
| 2754 |
-} |
|
| 2755 |
- |
|
| 2756 |
-const char * |
|
| 2757 |
-print_link_socket_actual(const struct link_socket_actual *act, struct gc_arena *gc) |
|
| 2758 |
-{
|
|
| 2759 |
- return print_link_socket_actual_ex(act, ":", PS_SHOW_PORT | PS_SHOW_PKTINFO, gc); |
|
| 2760 |
-} |
|
| 2761 |
- |
|
| 2762 |
-#ifndef IF_NAMESIZE |
|
| 2763 |
-#define IF_NAMESIZE 16 |
|
| 2764 |
-#endif |
|
| 2765 |
- |
|
| 2766 |
-const char * |
|
| 2767 |
-print_link_socket_actual_ex(const struct link_socket_actual *act, const char *separator, |
|
| 2768 |
- const unsigned int flags, struct gc_arena *gc) |
|
| 2769 |
-{
|
|
| 2770 |
- if (act) |
|
| 2771 |
- {
|
|
| 2772 |
- struct buffer out = alloc_buf_gc(128, gc); |
|
| 2773 |
- buf_printf(&out, "%s", print_sockaddr_ex(&act->dest.addr.sa, separator, flags, gc)); |
|
| 2774 |
-#if ENABLE_IP_PKTINFO |
|
| 2775 |
- char ifname[IF_NAMESIZE] = "[undef]"; |
|
| 2776 |
- |
|
| 2777 |
- if ((flags & PS_SHOW_PKTINFO) && addr_defined_ipi(act)) |
|
| 2778 |
- {
|
|
| 2779 |
- switch (act->dest.addr.sa.sa_family) |
|
| 2780 |
- {
|
|
| 2781 |
- case AF_INET: |
|
| 2782 |
- {
|
|
| 2783 |
- struct openvpn_sockaddr sa; |
|
| 2784 |
- CLEAR(sa); |
|
| 2785 |
- sa.addr.in4.sin_family = AF_INET; |
|
| 2786 |
-#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) |
|
| 2787 |
- sa.addr.in4.sin_addr = act->pi.in4.ipi_spec_dst; |
|
| 2788 |
- if_indextoname(act->pi.in4.ipi_ifindex, ifname); |
|
| 2789 |
-#elif defined(IP_RECVDSTADDR) |
|
| 2790 |
- sa.addr.in4.sin_addr = act->pi.in4; |
|
| 2791 |
- ifname[0] = 0; |
|
| 2792 |
-#else /* if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) */ |
|
| 2793 |
-#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h) |
|
| 2794 |
-#endif |
|
| 2795 |
- buf_printf(&out, " (via %s%%%s)", |
|
| 2796 |
- print_sockaddr_ex(&sa.addr.sa, separator, 0, gc), ifname); |
|
| 2797 |
- } |
|
| 2798 |
- break; |
|
| 2799 |
- |
|
| 2800 |
- case AF_INET6: |
|
| 2801 |
- {
|
|
| 2802 |
- struct sockaddr_in6 sin6; |
|
| 2803 |
- char buf[INET6_ADDRSTRLEN] = "[undef]"; |
|
| 2804 |
- CLEAR(sin6); |
|
| 2805 |
- sin6.sin6_family = AF_INET6; |
|
| 2806 |
- sin6.sin6_addr = act->pi.in6.ipi6_addr; |
|
| 2807 |
- if_indextoname(act->pi.in6.ipi6_ifindex, ifname); |
|
| 2808 |
- if (getnameinfo((struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), buf, |
|
| 2809 |
- sizeof(buf), NULL, 0, NI_NUMERICHOST) |
|
| 2810 |
- == 0) |
|
| 2811 |
- {
|
|
| 2812 |
- buf_printf(&out, " (via %s%%%s)", buf, ifname); |
|
| 2813 |
- } |
|
| 2814 |
- else |
|
| 2815 |
- {
|
|
| 2816 |
- buf_printf(&out, " (via [getnameinfo() err]%%%s)", ifname); |
|
| 2817 |
- } |
|
| 2818 |
- } |
|
| 2819 |
- break; |
|
| 2820 |
- } |
|
| 2821 |
- } |
|
| 2822 |
-#endif /* if ENABLE_IP_PKTINFO */ |
|
| 2823 |
- return BSTR(&out); |
|
| 2824 |
- } |
|
| 2825 |
- else |
|
| 2826 |
- {
|
|
| 2827 |
- return "[NULL]"; |
|
| 2828 |
- } |
|
| 2829 |
-} |
|
| 2830 |
- |
|
| 2831 |
-/* |
|
| 2832 |
- * Convert an in_addr_t in host byte order |
|
| 2833 |
- * to an ascii dotted quad. |
|
| 2834 |
- */ |
|
| 2835 |
-const char * |
|
| 2836 |
-print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc) |
|
| 2837 |
-{
|
|
| 2838 |
- struct in_addr ia; |
|
| 2839 |
- char *out = gc_malloc(INET_ADDRSTRLEN, true, gc); |
|
| 2840 |
- |
|
| 2841 |
- if (addr || !(flags & IA_EMPTY_IF_UNDEF)) |
|
| 2842 |
- {
|
|
| 2843 |
- CLEAR(ia); |
|
| 2844 |
- ia.s_addr = (flags & IA_NET_ORDER) ? addr : htonl(addr); |
|
| 2845 |
- |
|
| 2846 |
- inet_ntop(AF_INET, &ia, out, INET_ADDRSTRLEN); |
|
| 2847 |
- } |
|
| 2848 |
- return out; |
|
| 2849 |
-} |
|
| 2850 |
- |
|
| 2851 |
-/* |
|
| 2852 |
- * Convert an in6_addr in host byte order |
|
| 2853 |
- * to an ascii representation of an IPv6 address |
|
| 2854 |
- */ |
|
| 2855 |
-const char * |
|
| 2856 |
-print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc) |
|
| 2857 |
-{
|
|
| 2858 |
- char *out = gc_malloc(INET6_ADDRSTRLEN, true, gc); |
|
| 2859 |
- |
|
| 2860 |
- if (memcmp(&a6, &in6addr_any, sizeof(a6)) != 0 || !(flags & IA_EMPTY_IF_UNDEF)) |
|
| 2861 |
- {
|
|
| 2862 |
- inet_ntop(AF_INET6, &a6, out, INET6_ADDRSTRLEN); |
|
| 2863 |
- } |
|
| 2864 |
- return out; |
|
| 2865 |
-} |
|
| 2866 |
- |
|
| 2867 |
-/* |
|
| 2868 |
- * Convert an in_port_t in host byte order to a string |
|
| 2869 |
- */ |
|
| 2870 |
-const char * |
|
| 2871 |
-print_in_port_t(in_port_t port, struct gc_arena *gc) |
|
| 2872 |
-{
|
|
| 2873 |
- struct buffer buffer = alloc_buf_gc(8, gc); |
|
| 2874 |
- buf_printf(&buffer, "%hu", port); |
|
| 2875 |
- return BSTR(&buffer); |
|
| 2876 |
-} |
|
| 2877 |
- |
|
| 2878 |
-/* add some offset to an ipv6 address |
|
| 2879 |
- * (add in steps of 8 bits, taking overflow into next round) |
|
| 2880 |
- */ |
|
| 2881 |
-struct in6_addr |
|
| 2882 |
-add_in6_addr(struct in6_addr base, uint32_t add) |
|
| 2883 |
-{
|
|
| 2884 |
- int i; |
|
| 2885 |
- |
|
| 2886 |
- for (i = 15; i >= 0 && add > 0; i--) |
|
| 2887 |
- {
|
|
| 2888 |
- register int carry; |
|
| 2889 |
- register uint32_t h; |
|
| 2890 |
- |
|
| 2891 |
- h = (unsigned char)base.s6_addr[i]; |
|
| 2892 |
- base.s6_addr[i] = (h + add) & UINT8_MAX; |
|
| 2893 |
- |
|
| 2894 |
- /* using explicit carry for the 8-bit additions will catch |
|
| 2895 |
- * 8-bit and(!) 32-bit overruns nicely |
|
| 2896 |
- */ |
|
| 2897 |
- carry = ((h & 0xff) + (add & 0xff)) >> 8; |
|
| 2898 |
- add = (add >> 8) + carry; |
|
| 2899 |
- } |
|
| 2900 |
- return base; |
|
| 2901 |
-} |
|
| 2902 |
- |
|
| 2903 |
-/* set environmental variables for ip/port in *addr */ |
|
| 2904 |
-void |
|
| 2905 |
-setenv_sockaddr(struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr, |
|
| 2906 |
- const unsigned int flags) |
|
| 2907 |
-{
|
|
| 2908 |
- char name_buf[256]; |
|
| 2909 |
- |
|
| 2910 |
- char buf[INET6_ADDRSTRLEN]; |
|
| 2911 |
- switch (addr->addr.sa.sa_family) |
|
| 2912 |
- {
|
|
| 2913 |
- case AF_INET: |
|
| 2914 |
- if (flags & SA_IP_PORT) |
|
| 2915 |
- {
|
|
| 2916 |
- snprintf(name_buf, sizeof(name_buf), "%s_ip", name_prefix); |
|
| 2917 |
- } |
|
| 2918 |
- else |
|
| 2919 |
- {
|
|
| 2920 |
- snprintf(name_buf, sizeof(name_buf), "%s", name_prefix); |
|
| 2921 |
- } |
|
| 2922 |
- |
|
| 2923 |
- inet_ntop(AF_INET, &addr->addr.in4.sin_addr, buf, sizeof(buf)); |
|
| 2924 |
- setenv_str(es, name_buf, buf); |
|
| 2925 |
- |
|
| 2926 |
- if ((flags & SA_IP_PORT) && addr->addr.in4.sin_port) |
|
| 2927 |
- {
|
|
| 2928 |
- snprintf(name_buf, sizeof(name_buf), "%s_port", name_prefix); |
|
| 2929 |
- setenv_int(es, name_buf, ntohs(addr->addr.in4.sin_port)); |
|
| 2930 |
- } |
|
| 2931 |
- break; |
|
| 2932 |
- |
|
| 2933 |
- case AF_INET6: |
|
| 2934 |
- if (IN6_IS_ADDR_V4MAPPED(&addr->addr.in6.sin6_addr)) |
|
| 2935 |
- {
|
|
| 2936 |
- struct in_addr ia; |
|
| 2937 |
- memcpy(&ia.s_addr, &addr->addr.in6.sin6_addr.s6_addr[12], sizeof(ia.s_addr)); |
|
| 2938 |
- snprintf(name_buf, sizeof(name_buf), "%s_ip", name_prefix); |
|
| 2939 |
- inet_ntop(AF_INET, &ia, buf, sizeof(buf)); |
|
| 2940 |
- } |
|
| 2941 |
- else |
|
| 2942 |
- {
|
|
| 2943 |
- snprintf(name_buf, sizeof(name_buf), "%s_ip6", name_prefix); |
|
| 2944 |
- inet_ntop(AF_INET6, &addr->addr.in6.sin6_addr, buf, sizeof(buf)); |
|
| 2945 |
- } |
|
| 2946 |
- setenv_str(es, name_buf, buf); |
|
| 2947 |
- |
|
| 2948 |
- if ((flags & SA_IP_PORT) && addr->addr.in6.sin6_port) |
|
| 2949 |
- {
|
|
| 2950 |
- snprintf(name_buf, sizeof(name_buf), "%s_port", name_prefix); |
|
| 2951 |
- setenv_int(es, name_buf, ntohs(addr->addr.in6.sin6_port)); |
|
| 2952 |
- } |
|
| 2953 |
- break; |
|
| 2954 |
- } |
|
| 2955 |
-} |
|
| 2956 |
- |
|
| 2957 |
-void |
|
| 2958 |
-setenv_in_addr_t(struct env_set *es, const char *name_prefix, in_addr_t addr, |
|
| 2959 |
- const unsigned int flags) |
|
| 2960 |
-{
|
|
| 2961 |
- if (addr || !(flags & SA_SET_IF_NONZERO)) |
|
| 2962 |
- {
|
|
| 2963 |
- struct openvpn_sockaddr si; |
|
| 2964 |
- CLEAR(si); |
|
| 2965 |
- si.addr.in4.sin_family = AF_INET; |
|
| 2966 |
- si.addr.in4.sin_addr.s_addr = htonl(addr); |
|
| 2967 |
- setenv_sockaddr(es, name_prefix, &si, flags); |
|
| 2968 |
- } |
|
| 2969 |
-} |
|
| 2970 |
- |
|
| 2971 |
-void |
|
| 2972 |
-setenv_in6_addr(struct env_set *es, const char *name_prefix, const struct in6_addr *addr, |
|
| 2973 |
- const unsigned int flags) |
|
| 2974 |
-{
|
|
| 2975 |
- if (!IN6_IS_ADDR_UNSPECIFIED(addr) || !(flags & SA_SET_IF_NONZERO)) |
|
| 2976 |
- {
|
|
| 2977 |
- struct openvpn_sockaddr si; |
|
| 2978 |
- CLEAR(si); |
|
| 2979 |
- si.addr.in6.sin6_family = AF_INET6; |
|
| 2980 |
- si.addr.in6.sin6_addr = *addr; |
|
| 2981 |
- setenv_sockaddr(es, name_prefix, &si, flags); |
|
| 2982 |
- } |
|
| 2983 |
-} |
|
| 2984 |
- |
|
| 2985 |
-void |
|
| 2986 |
-setenv_link_socket_actual(struct env_set *es, const char *name_prefix, |
|
| 2987 |
- const struct link_socket_actual *act, const unsigned int flags) |
|
| 2988 |
-{
|
|
| 2989 |
- setenv_sockaddr(es, name_prefix, &act->dest, flags); |
|
| 2990 |
-} |
|
| 2991 |
- |
|
| 2992 |
-/* |
|
| 2993 |
- * Convert protocol names between index and ascii form. |
|
| 2994 |
- */ |
|
| 2995 |
- |
|
| 2996 |
-struct proto_names |
|
| 2997 |
-{
|
|
| 2998 |
- const char *short_form; |
|
| 2999 |
- const char *display_form; |
|
| 3000 |
- sa_family_t proto_af; |
|
| 3001 |
- int proto; |
|
| 3002 |
-}; |
|
| 3003 |
- |
|
| 3004 |
-/* Indexed by PROTO_x */ |
|
| 3005 |
-static const struct proto_names proto_names[] = {
|
|
| 3006 |
- { "proto-uninitialized", "proto-NONE", AF_UNSPEC, PROTO_NONE },
|
|
| 3007 |
- /* try IPv4 and IPv6 (client), bind dual-stack (server) */ |
|
| 3008 |
- { "udp", "UDP", AF_UNSPEC, PROTO_UDP },
|
|
| 3009 |
- { "tcp-server", "TCP_SERVER", AF_UNSPEC, PROTO_TCP_SERVER },
|
|
| 3010 |
- { "tcp-client", "TCP_CLIENT", AF_UNSPEC, PROTO_TCP_CLIENT },
|
|
| 3011 |
- { "tcp", "TCP", AF_UNSPEC, PROTO_TCP },
|
|
| 3012 |
- /* force IPv4 */ |
|
| 3013 |
- { "udp4", "UDPv4", AF_INET, PROTO_UDP },
|
|
| 3014 |
- { "tcp4-server", "TCPv4_SERVER", AF_INET, PROTO_TCP_SERVER },
|
|
| 3015 |
- { "tcp4-client", "TCPv4_CLIENT", AF_INET, PROTO_TCP_CLIENT },
|
|
| 3016 |
- { "tcp4", "TCPv4", AF_INET, PROTO_TCP },
|
|
| 3017 |
- /* force IPv6 */ |
|
| 3018 |
- { "udp6", "UDPv6", AF_INET6, PROTO_UDP },
|
|
| 3019 |
- { "tcp6-server", "TCPv6_SERVER", AF_INET6, PROTO_TCP_SERVER },
|
|
| 3020 |
- { "tcp6-client", "TCPv6_CLIENT", AF_INET6, PROTO_TCP_CLIENT },
|
|
| 3021 |
- { "tcp6", "TCPv6", AF_INET6, PROTO_TCP },
|
|
| 3022 |
-}; |
|
| 3023 |
- |
|
| 3024 |
-int |
|
| 3025 |
-ascii2proto(const char *proto_name) |
|
| 3026 |
-{
|
|
| 3027 |
- for (size_t i = 0; i < SIZE(proto_names); ++i) |
|
| 3028 |
- {
|
|
| 3029 |
- if (!strcmp(proto_name, proto_names[i].short_form)) |
|
| 3030 |
- {
|
|
| 3031 |
- return proto_names[i].proto; |
|
| 3032 |
- } |
|
| 3033 |
- } |
|
| 3034 |
- return -1; |
|
| 3035 |
-} |
|
| 3036 |
- |
|
| 3037 |
-sa_family_t |
|
| 3038 |
-ascii2af(const char *proto_name) |
|
| 3039 |
-{
|
|
| 3040 |
- for (size_t i = 0; i < SIZE(proto_names); ++i) |
|
| 3041 |
- {
|
|
| 3042 |
- if (!strcmp(proto_name, proto_names[i].short_form)) |
|
| 3043 |
- {
|
|
| 3044 |
- return proto_names[i].proto_af; |
|
| 3045 |
- } |
|
| 3046 |
- } |
|
| 3047 |
- return 0; |
|
| 3048 |
-} |
|
| 3049 |
- |
|
| 3050 |
-const char * |
|
| 3051 |
-proto2ascii(int proto, sa_family_t af, bool display_form) |
|
| 3052 |
-{
|
|
| 3053 |
- for (size_t i = 0; i < SIZE(proto_names); ++i) |
|
| 3054 |
- {
|
|
| 3055 |
- if (proto_names[i].proto_af == af && proto_names[i].proto == proto) |
|
| 3056 |
- {
|
|
| 3057 |
- if (display_form) |
|
| 3058 |
- {
|
|
| 3059 |
- return proto_names[i].display_form; |
|
| 3060 |
- } |
|
| 3061 |
- else |
|
| 3062 |
- {
|
|
| 3063 |
- return proto_names[i].short_form; |
|
| 3064 |
- } |
|
| 3065 |
- } |
|
| 3066 |
- } |
|
| 3067 |
- |
|
| 3068 |
- return "[unknown protocol]"; |
|
| 3069 |
-} |
|
| 3070 |
- |
|
| 3071 |
-const char * |
|
| 3072 |
-proto2ascii_all(struct gc_arena *gc) |
|
| 3073 |
-{
|
|
| 3074 |
- struct buffer out = alloc_buf_gc(256, gc); |
|
| 3075 |
- |
|
| 3076 |
- for (size_t i = 0; i < SIZE(proto_names); ++i) |
|
| 3077 |
- {
|
|
| 3078 |
- if (i) |
|
| 3079 |
- {
|
|
| 3080 |
- buf_printf(&out, " "); |
|
| 3081 |
- } |
|
| 3082 |
- buf_printf(&out, "[%s]", proto_names[i].short_form); |
|
| 3083 |
- } |
|
| 3084 |
- return BSTR(&out); |
|
| 3085 |
-} |
|
| 3086 |
- |
|
| 3087 |
-const char * |
|
| 3088 |
-addr_family_name(int af) |
|
| 3089 |
-{
|
|
| 3090 |
- switch (af) |
|
| 3091 |
- {
|
|
| 3092 |
- case AF_INET: |
|
| 3093 |
- return "AF_INET"; |
|
| 3094 |
- |
|
| 3095 |
- case AF_INET6: |
|
| 3096 |
- return "AF_INET6"; |
|
| 3097 |
- } |
|
| 3098 |
- return "AF_UNSPEC"; |
|
| 3099 |
-} |
|
| 3100 |
- |
|
| 3101 |
-/* |
|
| 3102 |
- * Given a local proto, return local proto |
|
| 3103 |
- * if !remote, or compatible remote proto |
|
| 3104 |
- * if remote. |
|
| 3105 |
- * |
|
| 3106 |
- * This is used for options compatibility |
|
| 3107 |
- * checking. |
|
| 3108 |
- * |
|
| 3109 |
- * IPv6 and IPv4 protocols are comptabile but OpenVPN |
|
| 3110 |
- * has always sent UDPv4, TCPv4 over the wire. Keep these |
|
| 3111 |
- * strings for backward compatibility |
|
| 3112 |
- */ |
|
| 3113 |
-const char * |
|
| 3114 |
-proto_remote(int proto, bool remote) |
|
| 3115 |
-{
|
|
| 3116 |
- ASSERT(proto >= 0 && proto < PROTO_N); |
|
| 3117 |
- if (proto == PROTO_UDP) |
|
| 3118 |
- {
|
|
| 3119 |
- return "UDPv4"; |
|
| 3120 |
- } |
|
| 3121 |
- |
|
| 3122 |
- if ((remote && proto == PROTO_TCP_CLIENT) || (!remote && proto == PROTO_TCP_SERVER)) |
|
| 3123 |
- {
|
|
| 3124 |
- return "TCPv4_SERVER"; |
|
| 3125 |
- } |
|
| 3126 |
- if ((remote && proto == PROTO_TCP_SERVER) || (!remote && proto == PROTO_TCP_CLIENT)) |
|
| 3127 |
- {
|
|
| 3128 |
- return "TCPv4_CLIENT"; |
|
| 3129 |
- } |
|
| 3130 |
- |
|
| 3131 |
- ASSERT(0); |
|
| 3132 |
- return ""; /* Make the compiler happy */ |
|
| 3133 |
-} |
|
| 3134 | 2673 |
|
| 3135 | 2674 |
/* |
| 3136 | 2675 |
* Bad incoming address lengths that differ from what |
| ... | ... |
@@ -34,6 +34,7 @@ |
| 34 | 34 |
#include "socks.h" |
| 35 | 35 |
#include "misc.h" |
| 36 | 36 |
#include "tun.h" |
| 37 |
+#include "socket_util.h" |
|
| 37 | 38 |
|
| 38 | 39 |
/* |
| 39 | 40 |
* OpenVPN's default port number as assigned by IANA. |
| ... | ... |
@@ -60,18 +61,6 @@ typedef uint16_t packet_size_type; |
| 60 | 60 |
/* convert a packet_size_type from network to host order */ |
| 61 | 61 |
#define ntohps(x) ntohs(x) |
| 62 | 62 |
|
| 63 |
-/* OpenVPN sockaddr struct */ |
|
| 64 |
-struct openvpn_sockaddr |
|
| 65 |
-{
|
|
| 66 |
- /*int dummy;*/ /* add offset to force a bug if sa not explicitly dereferenced */ |
|
| 67 |
- union |
|
| 68 |
- {
|
|
| 69 |
- struct sockaddr sa; |
|
| 70 |
- struct sockaddr_in in4; |
|
| 71 |
- struct sockaddr_in6 in6; |
|
| 72 |
- } addr; |
|
| 73 |
-}; |
|
| 74 |
- |
|
| 75 | 63 |
/* struct to hold preresolved host names */ |
| 76 | 64 |
struct cached_dns_entry |
| 77 | 65 |
{
|
| ... | ... |
@@ -83,25 +72,6 @@ struct cached_dns_entry |
| 83 | 83 |
struct cached_dns_entry *next; |
| 84 | 84 |
}; |
| 85 | 85 |
|
| 86 |
-/* actual address of remote, based on source address of received packets */ |
|
| 87 |
-struct link_socket_actual |
|
| 88 |
-{
|
|
| 89 |
- /*int dummy;*/ /* add offset to force a bug if dest not explicitly dereferenced */ |
|
| 90 |
- |
|
| 91 |
- struct openvpn_sockaddr dest; |
|
| 92 |
-#if ENABLE_IP_PKTINFO |
|
| 93 |
- union |
|
| 94 |
- {
|
|
| 95 |
-#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) |
|
| 96 |
- struct in_pktinfo in4; |
|
| 97 |
-#elif defined(IP_RECVDSTADDR) |
|
| 98 |
- struct in_addr in4; |
|
| 99 |
-#endif |
|
| 100 |
- struct in6_pktinfo in6; |
|
| 101 |
- } pi; |
|
| 102 |
-#endif |
|
| 103 |
-}; |
|
| 104 |
- |
|
| 105 | 86 |
/* IP addresses which are persistent across SIGUSR1s */ |
| 106 | 87 |
struct link_socket_addr |
| 107 | 88 |
{
|
| ... | ... |
@@ -349,58 +319,6 @@ void link_socket_close(struct link_socket *sock); |
| 349 | 349 |
|
| 350 | 350 |
void sd_close(socket_descriptor_t *sd); |
| 351 | 351 |
|
| 352 |
-#define PS_SHOW_PORT_IF_DEFINED (1 << 0) |
|
| 353 |
-#define PS_SHOW_PORT (1 << 1) |
|
| 354 |
-#define PS_SHOW_PKTINFO (1 << 2) |
|
| 355 |
-#define PS_DONT_SHOW_ADDR (1 << 3) |
|
| 356 |
-#define PS_DONT_SHOW_FAMILY (1 << 4) |
|
| 357 |
- |
|
| 358 |
-const char *print_sockaddr_ex(const struct sockaddr *addr, const char *separator, |
|
| 359 |
- const unsigned int flags, struct gc_arena *gc); |
|
| 360 |
- |
|
| 361 |
-static inline const char * |
|
| 362 |
-print_openvpn_sockaddr(const struct openvpn_sockaddr *addr, struct gc_arena *gc) |
|
| 363 |
-{
|
|
| 364 |
- return print_sockaddr_ex(&addr->addr.sa, ":", PS_SHOW_PORT, gc); |
|
| 365 |
-} |
|
| 366 |
- |
|
| 367 |
-static inline const char * |
|
| 368 |
-print_sockaddr(const struct sockaddr *addr, struct gc_arena *gc) |
|
| 369 |
-{
|
|
| 370 |
- return print_sockaddr_ex(addr, ":", PS_SHOW_PORT, gc); |
|
| 371 |
-} |
|
| 372 |
- |
|
| 373 |
- |
|
| 374 |
-const char *print_link_socket_actual_ex(const struct link_socket_actual *act, const char *separator, |
|
| 375 |
- const unsigned int flags, struct gc_arena *gc); |
|
| 376 |
- |
|
| 377 |
-const char *print_link_socket_actual(const struct link_socket_actual *act, struct gc_arena *gc); |
|
| 378 |
- |
|
| 379 |
- |
|
| 380 |
-#define IA_EMPTY_IF_UNDEF (1 << 0) |
|
| 381 |
-#define IA_NET_ORDER (1 << 1) |
|
| 382 |
-const char *print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc); |
|
| 383 |
- |
|
| 384 |
-const char *print_in6_addr(struct in6_addr addr6, unsigned int flags, struct gc_arena *gc); |
|
| 385 |
- |
|
| 386 |
-const char *print_in_port_t(in_port_t port, struct gc_arena *gc); |
|
| 387 |
- |
|
| 388 |
-struct in6_addr add_in6_addr(struct in6_addr base, uint32_t add); |
|
| 389 |
- |
|
| 390 |
-#define SA_IP_PORT (1 << 0) |
|
| 391 |
-#define SA_SET_IF_NONZERO (1 << 1) |
|
| 392 |
-void setenv_sockaddr(struct env_set *es, const char *name_prefix, |
|
| 393 |
- const struct openvpn_sockaddr *addr, const unsigned int flags); |
|
| 394 |
- |
|
| 395 |
-void setenv_in_addr_t(struct env_set *es, const char *name_prefix, in_addr_t addr, |
|
| 396 |
- const unsigned int flags); |
|
| 397 |
- |
|
| 398 |
-void setenv_in6_addr(struct env_set *es, const char *name_prefix, const struct in6_addr *addr, |
|
| 399 |
- const unsigned int flags); |
|
| 400 |
- |
|
| 401 |
-void setenv_link_socket_actual(struct env_set *es, const char *name_prefix, |
|
| 402 |
- const struct link_socket_actual *act, const unsigned int flags); |
|
| 403 |
- |
|
| 404 | 352 |
void bad_address_length(int actual, int expected); |
| 405 | 353 |
|
| 406 | 354 |
/* IPV4_INVALID_ADDR: returned by link_socket_current_remote() |
| ... | ... |
@@ -432,21 +350,6 @@ void link_socket_update_buffer_sizes(struct link_socket *sock, int rcvbuf, int s |
| 432 | 432 |
* Low-level functions |
| 433 | 433 |
*/ |
| 434 | 434 |
|
| 435 |
-/* return values of openvpn_inet_aton */ |
|
| 436 |
-#define OIA_HOSTNAME 0 |
|
| 437 |
-#define OIA_IP 1 |
|
| 438 |
-#define OIA_ERROR -1 |
|
| 439 |
-int openvpn_inet_aton(const char *dotted_quad, struct in_addr *addr); |
|
| 440 |
- |
|
| 441 |
-/* integrity validation on pulled options */ |
|
| 442 |
-bool ip_addr_dotted_quad_safe(const char *dotted_quad); |
|
| 443 |
- |
|
| 444 |
-bool ip_or_dns_addr_safe(const char *addr, const bool allow_fqdn); |
|
| 445 |
- |
|
| 446 |
-bool mac_addr_safe(const char *mac_addr); |
|
| 447 |
- |
|
| 448 |
-bool ipv6_addr_safe(const char *ipv6_text_addr); |
|
| 449 |
- |
|
| 450 | 435 |
socket_descriptor_t create_socket_tcp(struct addrinfo *); |
| 451 | 436 |
|
| 452 | 437 |
socket_descriptor_t socket_do_accept(socket_descriptor_t sd, struct link_socket_actual *act, |
| ... | ... |
@@ -472,134 +375,6 @@ bool unix_socket_get_peer_uid_gid(const socket_descriptor_t sd, int *uid, int *g |
| 472 | 472 |
|
| 473 | 473 |
#endif /* if UNIX_SOCK_SUPPORT */ |
| 474 | 474 |
|
| 475 |
-/* |
|
| 476 |
- * DNS resolution |
|
| 477 |
- */ |
|
| 478 |
- |
|
| 479 |
-#define GETADDR_RESOLVE (1 << 0) |
|
| 480 |
-#define GETADDR_FATAL (1 << 1) |
|
| 481 |
-#define GETADDR_HOST_ORDER (1 << 2) |
|
| 482 |
-#define GETADDR_MENTION_RESOLVE_RETRY (1 << 3) |
|
| 483 |
-#define GETADDR_FATAL_ON_SIGNAL (1 << 4) |
|
| 484 |
-#define GETADDR_WARN_ON_SIGNAL (1 << 5) |
|
| 485 |
-#define GETADDR_MSG_VIRT_OUT (1 << 6) |
|
| 486 |
-#define GETADDR_TRY_ONCE (1 << 7) |
|
| 487 |
-#define GETADDR_UPDATE_MANAGEMENT_STATE (1 << 8) |
|
| 488 |
-#define GETADDR_RANDOMIZE (1 << 9) |
|
| 489 |
-#define GETADDR_PASSIVE (1 << 10) |
|
| 490 |
-#define GETADDR_DATAGRAM (1 << 11) |
|
| 491 |
- |
|
| 492 |
-#define GETADDR_CACHE_MASK (GETADDR_DATAGRAM | GETADDR_PASSIVE) |
|
| 493 |
- |
|
| 494 |
-/** |
|
| 495 |
- * Translate an IPv4 addr or hostname from string form to in_addr_t |
|
| 496 |
- * |
|
| 497 |
- * In case of resolve error, it will try again for |
|
| 498 |
- * resolve_retry_seconds seconds. |
|
| 499 |
- */ |
|
| 500 |
-in_addr_t getaddr(unsigned int flags, const char *hostname, int resolve_retry_seconds, |
|
| 501 |
- bool *succeeded, struct signal_info *sig_info); |
|
| 502 |
- |
|
| 503 |
-/** |
|
| 504 |
- * Translate an IPv6 addr or hostname from string form to in6_addr |
|
| 505 |
- */ |
|
| 506 |
-bool get_ipv6_addr(const char *hostname, struct in6_addr *network, unsigned int *netbits, |
|
| 507 |
- int msglevel); |
|
| 508 |
- |
|
| 509 |
-int openvpn_getaddrinfo(unsigned int flags, const char *hostname, const char *servname, |
|
| 510 |
- int resolve_retry_seconds, struct signal_info *sig_info, int ai_family, |
|
| 511 |
- struct addrinfo **res); |
|
| 512 |
- |
|
| 513 |
-/* |
|
| 514 |
- * Transport protocol naming and other details. |
|
| 515 |
- */ |
|
| 516 |
- |
|
| 517 |
-/* |
|
| 518 |
- * Use enum's instead of #define to allow for easier |
|
| 519 |
- * optional proto support |
|
| 520 |
- */ |
|
| 521 |
-enum proto_num |
|
| 522 |
-{
|
|
| 523 |
- PROTO_NONE, /* catch for uninitialized */ |
|
| 524 |
- PROTO_UDP, |
|
| 525 |
- PROTO_TCP, |
|
| 526 |
- PROTO_TCP_SERVER, |
|
| 527 |
- PROTO_TCP_CLIENT, |
|
| 528 |
- PROTO_N |
|
| 529 |
-}; |
|
| 530 |
- |
|
| 531 |
-static inline bool |
|
| 532 |
-proto_is_net(int proto) |
|
| 533 |
-{
|
|
| 534 |
- ASSERT(proto >= 0 && proto < PROTO_N); |
|
| 535 |
- return proto != PROTO_NONE; |
|
| 536 |
-} |
|
| 537 |
- |
|
| 538 |
-/** |
|
| 539 |
- * @brief Returns if the protocol being used is UDP |
|
| 540 |
- */ |
|
| 541 |
-static inline bool |
|
| 542 |
-proto_is_udp(int proto) |
|
| 543 |
-{
|
|
| 544 |
- ASSERT(proto >= 0 && proto < PROTO_N); |
|
| 545 |
- return proto == PROTO_UDP; |
|
| 546 |
-} |
|
| 547 |
- |
|
| 548 |
-/** |
|
| 549 |
- * @brief Return if the protocol is datagram (UDP) |
|
| 550 |
- * |
|
| 551 |
- */ |
|
| 552 |
-static inline bool |
|
| 553 |
-proto_is_dgram(int proto) |
|
| 554 |
-{
|
|
| 555 |
- return proto_is_udp(proto); |
|
| 556 |
-} |
|
| 557 |
- |
|
| 558 |
-/** |
|
| 559 |
- * @brief returns if the proto is a TCP variant (tcp-server, tcp-client or tcp) |
|
| 560 |
- */ |
|
| 561 |
-static inline bool |
|
| 562 |
-proto_is_tcp(int proto) |
|
| 563 |
-{
|
|
| 564 |
- ASSERT(proto >= 0 && proto < PROTO_N); |
|
| 565 |
- return proto == PROTO_TCP_CLIENT || proto == PROTO_TCP_SERVER; |
|
| 566 |
-} |
|
| 567 |
- |
|
| 568 |
- |
|
| 569 |
-int ascii2proto(const char *proto_name); |
|
| 570 |
- |
|
| 571 |
-sa_family_t ascii2af(const char *proto_name); |
|
| 572 |
- |
|
| 573 |
-const char *proto2ascii(int proto, sa_family_t af, bool display_form); |
|
| 574 |
- |
|
| 575 |
-const char *proto2ascii_all(struct gc_arena *gc); |
|
| 576 |
- |
|
| 577 |
-const char *proto_remote(int proto, bool remote); |
|
| 578 |
- |
|
| 579 |
-const char *addr_family_name(int af); |
|
| 580 |
- |
|
| 581 |
-/* |
|
| 582 |
- * Overhead added to packets by various protocols. |
|
| 583 |
- */ |
|
| 584 |
-static inline int |
|
| 585 |
-datagram_overhead(sa_family_t af, int proto) |
|
| 586 |
-{
|
|
| 587 |
- int overhead = 0; |
|
| 588 |
- overhead += (proto == PROTO_UDP) ? 8 : 20; |
|
| 589 |
- overhead += (af == AF_INET) ? 20 : 40; |
|
| 590 |
- return overhead; |
|
| 591 |
-} |
|
| 592 |
- |
|
| 593 |
-/* |
|
| 594 |
- * Misc inline functions |
|
| 595 |
- */ |
|
| 596 |
- |
|
| 597 |
-static inline bool |
|
| 598 |
-link_socket_proto_connection_oriented(int proto) |
|
| 599 |
-{
|
|
| 600 |
- return !proto_is_dgram(proto); |
|
| 601 |
-} |
|
| 602 |
- |
|
| 603 | 475 |
static inline bool |
| 604 | 476 |
link_socket_connection_oriented(const struct link_socket *sock) |
| 605 | 477 |
{
|
| ... | ... |
@@ -613,242 +388,6 @@ link_socket_connection_oriented(const struct link_socket *sock) |
| 613 | 613 |
} |
| 614 | 614 |
} |
| 615 | 615 |
|
| 616 |
-static inline bool |
|
| 617 |
-addr_defined(const struct openvpn_sockaddr *addr) |
|
| 618 |
-{
|
|
| 619 |
- if (!addr) |
|
| 620 |
- {
|
|
| 621 |
- return 0; |
|
| 622 |
- } |
|
| 623 |
- switch (addr->addr.sa.sa_family) |
|
| 624 |
- {
|
|
| 625 |
- case AF_INET: |
|
| 626 |
- return addr->addr.in4.sin_addr.s_addr != 0; |
|
| 627 |
- |
|
| 628 |
- case AF_INET6: |
|
| 629 |
- return !IN6_IS_ADDR_UNSPECIFIED(&addr->addr.in6.sin6_addr); |
|
| 630 |
- |
|
| 631 |
- default: |
|
| 632 |
- return 0; |
|
| 633 |
- } |
|
| 634 |
-} |
|
| 635 |
- |
|
| 636 |
-static inline bool |
|
| 637 |
-addr_local(const struct sockaddr *addr) |
|
| 638 |
-{
|
|
| 639 |
- if (!addr) |
|
| 640 |
- {
|
|
| 641 |
- return false; |
|
| 642 |
- } |
|
| 643 |
- switch (addr->sa_family) |
|
| 644 |
- {
|
|
| 645 |
- case AF_INET: |
|
| 646 |
- return ((const struct sockaddr_in *)addr)->sin_addr.s_addr == htonl(INADDR_LOOPBACK); |
|
| 647 |
- |
|
| 648 |
- case AF_INET6: |
|
| 649 |
- return IN6_IS_ADDR_LOOPBACK(&((const struct sockaddr_in6 *)addr)->sin6_addr); |
|
| 650 |
- |
|
| 651 |
- default: |
|
| 652 |
- return false; |
|
| 653 |
- } |
|
| 654 |
-} |
|
| 655 |
- |
|
| 656 |
- |
|
| 657 |
-static inline bool |
|
| 658 |
-addr_defined_ipi(const struct link_socket_actual *lsa) |
|
| 659 |
-{
|
|
| 660 |
-#if ENABLE_IP_PKTINFO |
|
| 661 |
- if (!lsa) |
|
| 662 |
- {
|
|
| 663 |
- return 0; |
|
| 664 |
- } |
|
| 665 |
- switch (lsa->dest.addr.sa.sa_family) |
|
| 666 |
- {
|
|
| 667 |
-#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) |
|
| 668 |
- case AF_INET: |
|
| 669 |
- return lsa->pi.in4.ipi_spec_dst.s_addr != 0; |
|
| 670 |
- |
|
| 671 |
-#elif defined(IP_RECVDSTADDR) |
|
| 672 |
- case AF_INET: |
|
| 673 |
- return lsa->pi.in4.s_addr != 0; |
|
| 674 |
- |
|
| 675 |
-#endif |
|
| 676 |
- case AF_INET6: |
|
| 677 |
- return !IN6_IS_ADDR_UNSPECIFIED(&lsa->pi.in6.ipi6_addr); |
|
| 678 |
- |
|
| 679 |
- default: |
|
| 680 |
- return 0; |
|
| 681 |
- } |
|
| 682 |
-#else /* if ENABLE_IP_PKTINFO */ |
|
| 683 |
- ASSERT(0); |
|
| 684 |
-#endif |
|
| 685 |
- return false; |
|
| 686 |
-} |
|
| 687 |
- |
|
| 688 |
-static inline bool |
|
| 689 |
-link_socket_actual_defined(const struct link_socket_actual *act) |
|
| 690 |
-{
|
|
| 691 |
- return act && addr_defined(&act->dest); |
|
| 692 |
-} |
|
| 693 |
- |
|
| 694 |
-static inline bool |
|
| 695 |
-addr_match(const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2) |
|
| 696 |
-{
|
|
| 697 |
- switch (a1->addr.sa.sa_family) |
|
| 698 |
- {
|
|
| 699 |
- case AF_INET: |
|
| 700 |
- return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr; |
|
| 701 |
- |
|
| 702 |
- case AF_INET6: |
|
| 703 |
- return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr); |
|
| 704 |
- } |
|
| 705 |
- ASSERT(0); |
|
| 706 |
- return false; |
|
| 707 |
-} |
|
| 708 |
- |
|
| 709 |
-static inline bool |
|
| 710 |
-addrlist_match(const struct openvpn_sockaddr *a1, const struct addrinfo *addrlist) |
|
| 711 |
-{
|
|
| 712 |
- const struct addrinfo *curele; |
|
| 713 |
- for (curele = addrlist; curele; curele = curele->ai_next) |
|
| 714 |
- {
|
|
| 715 |
- switch (a1->addr.sa.sa_family) |
|
| 716 |
- {
|
|
| 717 |
- case AF_INET: |
|
| 718 |
- if (a1->addr.in4.sin_addr.s_addr |
|
| 719 |
- == ((struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr) |
|
| 720 |
- {
|
|
| 721 |
- return true; |
|
| 722 |
- } |
|
| 723 |
- break; |
|
| 724 |
- |
|
| 725 |
- case AF_INET6: |
|
| 726 |
- if (IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, |
|
| 727 |
- &((struct sockaddr_in6 *)curele->ai_addr)->sin6_addr)) |
|
| 728 |
- {
|
|
| 729 |
- return true; |
|
| 730 |
- } |
|
| 731 |
- break; |
|
| 732 |
- |
|
| 733 |
- default: |
|
| 734 |
- ASSERT(0); |
|
| 735 |
- } |
|
| 736 |
- } |
|
| 737 |
- return false; |
|
| 738 |
-} |
|
| 739 |
- |
|
| 740 |
-static inline bool |
|
| 741 |
-addrlist_port_match(const struct openvpn_sockaddr *a1, const struct addrinfo *a2) |
|
| 742 |
-{
|
|
| 743 |
- const struct addrinfo *curele; |
|
| 744 |
- for (curele = a2; curele; curele = curele->ai_next) |
|
| 745 |
- {
|
|
| 746 |
- switch (a1->addr.sa.sa_family) |
|
| 747 |
- {
|
|
| 748 |
- case AF_INET: |
|
| 749 |
- if (curele->ai_family == AF_INET |
|
| 750 |
- && a1->addr.in4.sin_addr.s_addr |
|
| 751 |
- == ((struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr |
|
| 752 |
- && a1->addr.in4.sin_port == ((struct sockaddr_in *)curele->ai_addr)->sin_port) |
|
| 753 |
- {
|
|
| 754 |
- return true; |
|
| 755 |
- } |
|
| 756 |
- break; |
|
| 757 |
- |
|
| 758 |
- case AF_INET6: |
|
| 759 |
- if (curele->ai_family == AF_INET6 |
|
| 760 |
- && IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, |
|
| 761 |
- &((struct sockaddr_in6 *)curele->ai_addr)->sin6_addr) |
|
| 762 |
- && a1->addr.in6.sin6_port |
|
| 763 |
- == ((struct sockaddr_in6 *)curele->ai_addr)->sin6_port) |
|
| 764 |
- {
|
|
| 765 |
- return true; |
|
| 766 |
- } |
|
| 767 |
- break; |
|
| 768 |
- |
|
| 769 |
- default: |
|
| 770 |
- ASSERT(0); |
|
| 771 |
- } |
|
| 772 |
- } |
|
| 773 |
- return false; |
|
| 774 |
-} |
|
| 775 |
- |
|
| 776 |
- |
|
| 777 |
-static inline bool |
|
| 778 |
-addr_port_match(const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2) |
|
| 779 |
-{
|
|
| 780 |
- switch (a1->addr.sa.sa_family) |
|
| 781 |
- {
|
|
| 782 |
- case AF_INET: |
|
| 783 |
- return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr |
|
| 784 |
- && a1->addr.in4.sin_port == a2->addr.in4.sin_port; |
|
| 785 |
- |
|
| 786 |
- case AF_INET6: |
|
| 787 |
- return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr) |
|
| 788 |
- && a1->addr.in6.sin6_port == a2->addr.in6.sin6_port; |
|
| 789 |
- } |
|
| 790 |
- ASSERT(0); |
|
| 791 |
- return false; |
|
| 792 |
-} |
|
| 793 |
- |
|
| 794 |
-static inline bool |
|
| 795 |
-addr_match_proto(const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2, |
|
| 796 |
- const int proto) |
|
| 797 |
-{
|
|
| 798 |
- return link_socket_proto_connection_oriented(proto) ? addr_match(a1, a2) |
|
| 799 |
- : addr_port_match(a1, a2); |
|
| 800 |
-} |
|
| 801 |
- |
|
| 802 |
- |
|
| 803 |
-static inline bool |
|
| 804 |
-addrlist_match_proto(const struct openvpn_sockaddr *a1, struct addrinfo *addr_list, const int proto) |
|
| 805 |
-{
|
|
| 806 |
- return link_socket_proto_connection_oriented(proto) ? addrlist_match(a1, addr_list) |
|
| 807 |
- : addrlist_port_match(a1, addr_list); |
|
| 808 |
-} |
|
| 809 |
- |
|
| 810 |
-static inline void |
|
| 811 |
-addr_zero_host(struct openvpn_sockaddr *addr) |
|
| 812 |
-{
|
|
| 813 |
- switch (addr->addr.sa.sa_family) |
|
| 814 |
- {
|
|
| 815 |
- case AF_INET: |
|
| 816 |
- addr->addr.in4.sin_addr.s_addr = 0; |
|
| 817 |
- break; |
|
| 818 |
- |
|
| 819 |
- case AF_INET6: |
|
| 820 |
- memset(&addr->addr.in6.sin6_addr, 0, sizeof(struct in6_addr)); |
|
| 821 |
- break; |
|
| 822 |
- } |
|
| 823 |
-} |
|
| 824 |
- |
|
| 825 |
-static inline int |
|
| 826 |
-af_addr_size(sa_family_t af) |
|
| 827 |
-{
|
|
| 828 |
- switch (af) |
|
| 829 |
- {
|
|
| 830 |
- case AF_INET: |
|
| 831 |
- return sizeof(struct sockaddr_in); |
|
| 832 |
- |
|
| 833 |
- case AF_INET6: |
|
| 834 |
- return sizeof(struct sockaddr_in6); |
|
| 835 |
- |
|
| 836 |
- default: |
|
| 837 |
-#if 0 |
|
| 838 |
- /* could be called from socket_do_accept() with empty addr */ |
|
| 839 |
- msg(M_ERR, "Bad address family: %d\n", af); |
|
| 840 |
- ASSERT(0); |
|
| 841 |
-#endif |
|
| 842 |
- return 0; |
|
| 843 |
- } |
|
| 844 |
-} |
|
| 845 |
- |
|
| 846 |
-static inline bool |
|
| 847 |
-link_socket_actual_match(const struct link_socket_actual *a1, const struct link_socket_actual *a2) |
|
| 848 |
-{
|
|
| 849 |
- return addr_port_match(&a1->dest, &a2->dest); |
|
| 850 |
-} |
|
| 851 |
- |
|
| 852 | 616 |
#if PORT_SHARE |
| 853 | 617 |
|
| 854 | 618 |
static inline bool |
| 855 | 619 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,936 @@ |
| 0 |
+/* |
|
| 1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
| 2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
| 3 |
+ * session authentication and key exchange, |
|
| 4 |
+ * packet encryption, packet authentication, and |
|
| 5 |
+ * packet compression. |
|
| 6 |
+ * |
|
| 7 |
+ * Copyright (C) 2002-2025 OpenVPN Inc <sales@openvpn.net> |
|
| 8 |
+ * |
|
| 9 |
+ * This program is free software; you can redistribute it and/or modify |
|
| 10 |
+ * it under the terms of the GNU General Public License version 2 |
|
| 11 |
+ * as published by the Free Software Foundation. |
|
| 12 |
+ * |
|
| 13 |
+ * This program is distributed in the hope that it will be useful, |
|
| 14 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 15 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 16 |
+ * GNU General Public License for more details. |
|
| 17 |
+ * |
|
| 18 |
+ * You should have received a copy of the GNU General Public License along |
|
| 19 |
+ * with this program; if not, see <https://www.gnu.org/licenses/>. |
|
| 20 |
+ */ |
|
| 21 |
+ |
|
| 22 |
+#ifdef HAVE_CONFIG_H |
|
| 23 |
+#include "config.h" |
|
| 24 |
+#endif |
|
| 25 |
+ |
|
| 26 |
+#include "syshead.h" |
|
| 27 |
+ |
|
| 28 |
+#include "socket_util.h" |
|
| 29 |
+#include "crypto.h" |
|
| 30 |
+#include "manage.h" |
|
| 31 |
+ |
|
| 32 |
+/* |
|
| 33 |
+ * Format IP addresses in ascii |
|
| 34 |
+ */ |
|
| 35 |
+ |
|
| 36 |
+const char * |
|
| 37 |
+print_sockaddr_ex(const struct sockaddr *sa, const char *separator, const unsigned int flags, |
|
| 38 |
+ struct gc_arena *gc) |
|
| 39 |
+{
|
|
| 40 |
+ struct buffer out = alloc_buf_gc(128, gc); |
|
| 41 |
+ bool addr_is_defined = false; |
|
| 42 |
+ char hostaddr[NI_MAXHOST] = ""; |
|
| 43 |
+ char servname[NI_MAXSERV] = ""; |
|
| 44 |
+ int status; |
|
| 45 |
+ |
|
| 46 |
+ socklen_t salen = 0; |
|
| 47 |
+ switch (sa->sa_family) |
|
| 48 |
+ {
|
|
| 49 |
+ case AF_INET: |
|
| 50 |
+ if (!(flags & PS_DONT_SHOW_FAMILY)) |
|
| 51 |
+ {
|
|
| 52 |
+ buf_puts(&out, "[AF_INET]"); |
|
| 53 |
+ } |
|
| 54 |
+ salen = sizeof(struct sockaddr_in); |
|
| 55 |
+ addr_is_defined = ((struct sockaddr_in *)sa)->sin_addr.s_addr != 0; |
|
| 56 |
+ break; |
|
| 57 |
+ |
|
| 58 |
+ case AF_INET6: |
|
| 59 |
+ if (!(flags & PS_DONT_SHOW_FAMILY)) |
|
| 60 |
+ {
|
|
| 61 |
+ buf_puts(&out, "[AF_INET6]"); |
|
| 62 |
+ } |
|
| 63 |
+ salen = sizeof(struct sockaddr_in6); |
|
| 64 |
+ addr_is_defined = !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)sa)->sin6_addr); |
|
| 65 |
+ break; |
|
| 66 |
+ |
|
| 67 |
+ case AF_UNSPEC: |
|
| 68 |
+ if (!(flags & PS_DONT_SHOW_FAMILY)) |
|
| 69 |
+ {
|
|
| 70 |
+ return "[AF_UNSPEC]"; |
|
| 71 |
+ } |
|
| 72 |
+ else |
|
| 73 |
+ {
|
|
| 74 |
+ return ""; |
|
| 75 |
+ } |
|
| 76 |
+ |
|
| 77 |
+ default: |
|
| 78 |
+ ASSERT(0); |
|
| 79 |
+ } |
|
| 80 |
+ |
|
| 81 |
+ status = getnameinfo(sa, salen, hostaddr, sizeof(hostaddr), servname, sizeof(servname), |
|
| 82 |
+ NI_NUMERICHOST | NI_NUMERICSERV); |
|
| 83 |
+ |
|
| 84 |
+ if (status != 0) |
|
| 85 |
+ {
|
|
| 86 |
+ buf_printf(&out, "[nameinfo() err: %s]", gai_strerror(status)); |
|
| 87 |
+ return BSTR(&out); |
|
| 88 |
+ } |
|
| 89 |
+ |
|
| 90 |
+ if (!(flags & PS_DONT_SHOW_ADDR)) |
|
| 91 |
+ {
|
|
| 92 |
+ if (addr_is_defined) |
|
| 93 |
+ {
|
|
| 94 |
+ buf_puts(&out, hostaddr); |
|
| 95 |
+ } |
|
| 96 |
+ else |
|
| 97 |
+ {
|
|
| 98 |
+ buf_puts(&out, "[undef]"); |
|
| 99 |
+ } |
|
| 100 |
+ } |
|
| 101 |
+ |
|
| 102 |
+ if ((flags & PS_SHOW_PORT) || (flags & PS_SHOW_PORT_IF_DEFINED)) |
|
| 103 |
+ {
|
|
| 104 |
+ if (separator) |
|
| 105 |
+ {
|
|
| 106 |
+ buf_puts(&out, separator); |
|
| 107 |
+ } |
|
| 108 |
+ |
|
| 109 |
+ buf_puts(&out, servname); |
|
| 110 |
+ } |
|
| 111 |
+ |
|
| 112 |
+ return BSTR(&out); |
|
| 113 |
+} |
|
| 114 |
+ |
|
| 115 |
+const char * |
|
| 116 |
+print_link_socket_actual(const struct link_socket_actual *act, struct gc_arena *gc) |
|
| 117 |
+{
|
|
| 118 |
+ return print_link_socket_actual_ex(act, ":", PS_SHOW_PORT | PS_SHOW_PKTINFO, gc); |
|
| 119 |
+} |
|
| 120 |
+ |
|
| 121 |
+#ifndef IF_NAMESIZE |
|
| 122 |
+#define IF_NAMESIZE 16 |
|
| 123 |
+#endif |
|
| 124 |
+ |
|
| 125 |
+const char * |
|
| 126 |
+print_link_socket_actual_ex(const struct link_socket_actual *act, const char *separator, |
|
| 127 |
+ const unsigned int flags, struct gc_arena *gc) |
|
| 128 |
+{
|
|
| 129 |
+ if (act) |
|
| 130 |
+ {
|
|
| 131 |
+ struct buffer out = alloc_buf_gc(128, gc); |
|
| 132 |
+ buf_printf(&out, "%s", print_sockaddr_ex(&act->dest.addr.sa, separator, flags, gc)); |
|
| 133 |
+#if ENABLE_IP_PKTINFO |
|
| 134 |
+ char ifname[IF_NAMESIZE] = "[undef]"; |
|
| 135 |
+ |
|
| 136 |
+ if ((flags & PS_SHOW_PKTINFO) && addr_defined_ipi(act)) |
|
| 137 |
+ {
|
|
| 138 |
+ switch (act->dest.addr.sa.sa_family) |
|
| 139 |
+ {
|
|
| 140 |
+ case AF_INET: |
|
| 141 |
+ {
|
|
| 142 |
+ struct openvpn_sockaddr sa; |
|
| 143 |
+ CLEAR(sa); |
|
| 144 |
+ sa.addr.in4.sin_family = AF_INET; |
|
| 145 |
+#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) |
|
| 146 |
+ sa.addr.in4.sin_addr = act->pi.in4.ipi_spec_dst; |
|
| 147 |
+ if_indextoname(act->pi.in4.ipi_ifindex, ifname); |
|
| 148 |
+#elif defined(IP_RECVDSTADDR) |
|
| 149 |
+ sa.addr.in4.sin_addr = act->pi.in4; |
|
| 150 |
+ ifname[0] = 0; |
|
| 151 |
+#else /* if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) */ |
|
| 152 |
+#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h) |
|
| 153 |
+#endif |
|
| 154 |
+ buf_printf(&out, " (via %s%%%s)", |
|
| 155 |
+ print_sockaddr_ex(&sa.addr.sa, separator, 0, gc), ifname); |
|
| 156 |
+ } |
|
| 157 |
+ break; |
|
| 158 |
+ |
|
| 159 |
+ case AF_INET6: |
|
| 160 |
+ {
|
|
| 161 |
+ struct sockaddr_in6 sin6; |
|
| 162 |
+ char buf[INET6_ADDRSTRLEN] = "[undef]"; |
|
| 163 |
+ CLEAR(sin6); |
|
| 164 |
+ sin6.sin6_family = AF_INET6; |
|
| 165 |
+ sin6.sin6_addr = act->pi.in6.ipi6_addr; |
|
| 166 |
+ if_indextoname(act->pi.in6.ipi6_ifindex, ifname); |
|
| 167 |
+ if (getnameinfo((struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), buf, |
|
| 168 |
+ sizeof(buf), NULL, 0, NI_NUMERICHOST) |
|
| 169 |
+ == 0) |
|
| 170 |
+ {
|
|
| 171 |
+ buf_printf(&out, " (via %s%%%s)", buf, ifname); |
|
| 172 |
+ } |
|
| 173 |
+ else |
|
| 174 |
+ {
|
|
| 175 |
+ buf_printf(&out, " (via [getnameinfo() err]%%%s)", ifname); |
|
| 176 |
+ } |
|
| 177 |
+ } |
|
| 178 |
+ break; |
|
| 179 |
+ } |
|
| 180 |
+ } |
|
| 181 |
+#endif /* if ENABLE_IP_PKTINFO */ |
|
| 182 |
+ return BSTR(&out); |
|
| 183 |
+ } |
|
| 184 |
+ else |
|
| 185 |
+ {
|
|
| 186 |
+ return "[NULL]"; |
|
| 187 |
+ } |
|
| 188 |
+} |
|
| 189 |
+ |
|
| 190 |
+/* |
|
| 191 |
+ * Convert an in_addr_t in host byte order |
|
| 192 |
+ * to an ascii dotted quad. |
|
| 193 |
+ */ |
|
| 194 |
+const char * |
|
| 195 |
+print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc) |
|
| 196 |
+{
|
|
| 197 |
+ struct in_addr ia; |
|
| 198 |
+ char *out = gc_malloc(INET_ADDRSTRLEN, true, gc); |
|
| 199 |
+ |
|
| 200 |
+ if (addr || !(flags & IA_EMPTY_IF_UNDEF)) |
|
| 201 |
+ {
|
|
| 202 |
+ CLEAR(ia); |
|
| 203 |
+ ia.s_addr = (flags & IA_NET_ORDER) ? addr : htonl(addr); |
|
| 204 |
+ |
|
| 205 |
+ inet_ntop(AF_INET, &ia, out, INET_ADDRSTRLEN); |
|
| 206 |
+ } |
|
| 207 |
+ return out; |
|
| 208 |
+} |
|
| 209 |
+ |
|
| 210 |
+/* |
|
| 211 |
+ * Convert an in6_addr in host byte order |
|
| 212 |
+ * to an ascii representation of an IPv6 address |
|
| 213 |
+ */ |
|
| 214 |
+const char * |
|
| 215 |
+print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc) |
|
| 216 |
+{
|
|
| 217 |
+ char *out = gc_malloc(INET6_ADDRSTRLEN, true, gc); |
|
| 218 |
+ |
|
| 219 |
+ if (memcmp(&a6, &in6addr_any, sizeof(a6)) != 0 || !(flags & IA_EMPTY_IF_UNDEF)) |
|
| 220 |
+ {
|
|
| 221 |
+ inet_ntop(AF_INET6, &a6, out, INET6_ADDRSTRLEN); |
|
| 222 |
+ } |
|
| 223 |
+ return out; |
|
| 224 |
+} |
|
| 225 |
+ |
|
| 226 |
+/* |
|
| 227 |
+ * Convert an in_port_t in host byte order to a string |
|
| 228 |
+ */ |
|
| 229 |
+const char * |
|
| 230 |
+print_in_port_t(in_port_t port, struct gc_arena *gc) |
|
| 231 |
+{
|
|
| 232 |
+ struct buffer buffer = alloc_buf_gc(8, gc); |
|
| 233 |
+ buf_printf(&buffer, "%hu", port); |
|
| 234 |
+ return BSTR(&buffer); |
|
| 235 |
+} |
|
| 236 |
+ |
|
| 237 |
+/* add some offset to an ipv6 address |
|
| 238 |
+ * (add in steps of 8 bits, taking overflow into next round) |
|
| 239 |
+ */ |
|
| 240 |
+struct in6_addr |
|
| 241 |
+add_in6_addr(struct in6_addr base, uint32_t add) |
|
| 242 |
+{
|
|
| 243 |
+ int i; |
|
| 244 |
+ |
|
| 245 |
+ for (i = 15; i >= 0 && add > 0; i--) |
|
| 246 |
+ {
|
|
| 247 |
+ register int carry; |
|
| 248 |
+ register uint32_t h; |
|
| 249 |
+ |
|
| 250 |
+ h = (unsigned char)base.s6_addr[i]; |
|
| 251 |
+ base.s6_addr[i] = (h + add) & UINT8_MAX; |
|
| 252 |
+ |
|
| 253 |
+ /* using explicit carry for the 8-bit additions will catch |
|
| 254 |
+ * 8-bit and(!) 32-bit overruns nicely |
|
| 255 |
+ */ |
|
| 256 |
+ carry = ((h & 0xff) + (add & 0xff)) >> 8; |
|
| 257 |
+ add = (add >> 8) + carry; |
|
| 258 |
+ } |
|
| 259 |
+ return base; |
|
| 260 |
+} |
|
| 261 |
+ |
|
| 262 |
+/* set environmental variables for ip/port in *addr */ |
|
| 263 |
+void |
|
| 264 |
+setenv_sockaddr(struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr, |
|
| 265 |
+ const unsigned int flags) |
|
| 266 |
+{
|
|
| 267 |
+ char name_buf[256]; |
|
| 268 |
+ |
|
| 269 |
+ char buf[INET6_ADDRSTRLEN]; |
|
| 270 |
+ switch (addr->addr.sa.sa_family) |
|
| 271 |
+ {
|
|
| 272 |
+ case AF_INET: |
|
| 273 |
+ if (flags & SA_IP_PORT) |
|
| 274 |
+ {
|
|
| 275 |
+ snprintf(name_buf, sizeof(name_buf), "%s_ip", name_prefix); |
|
| 276 |
+ } |
|
| 277 |
+ else |
|
| 278 |
+ {
|
|
| 279 |
+ snprintf(name_buf, sizeof(name_buf), "%s", name_prefix); |
|
| 280 |
+ } |
|
| 281 |
+ |
|
| 282 |
+ inet_ntop(AF_INET, &addr->addr.in4.sin_addr, buf, sizeof(buf)); |
|
| 283 |
+ setenv_str(es, name_buf, buf); |
|
| 284 |
+ |
|
| 285 |
+ if ((flags & SA_IP_PORT) && addr->addr.in4.sin_port) |
|
| 286 |
+ {
|
|
| 287 |
+ snprintf(name_buf, sizeof(name_buf), "%s_port", name_prefix); |
|
| 288 |
+ setenv_int(es, name_buf, ntohs(addr->addr.in4.sin_port)); |
|
| 289 |
+ } |
|
| 290 |
+ break; |
|
| 291 |
+ |
|
| 292 |
+ case AF_INET6: |
|
| 293 |
+ if (IN6_IS_ADDR_V4MAPPED(&addr->addr.in6.sin6_addr)) |
|
| 294 |
+ {
|
|
| 295 |
+ struct in_addr ia; |
|
| 296 |
+ memcpy(&ia.s_addr, &addr->addr.in6.sin6_addr.s6_addr[12], sizeof(ia.s_addr)); |
|
| 297 |
+ snprintf(name_buf, sizeof(name_buf), "%s_ip", name_prefix); |
|
| 298 |
+ inet_ntop(AF_INET, &ia, buf, sizeof(buf)); |
|
| 299 |
+ } |
|
| 300 |
+ else |
|
| 301 |
+ {
|
|
| 302 |
+ snprintf(name_buf, sizeof(name_buf), "%s_ip6", name_prefix); |
|
| 303 |
+ inet_ntop(AF_INET6, &addr->addr.in6.sin6_addr, buf, sizeof(buf)); |
|
| 304 |
+ } |
|
| 305 |
+ setenv_str(es, name_buf, buf); |
|
| 306 |
+ |
|
| 307 |
+ if ((flags & SA_IP_PORT) && addr->addr.in6.sin6_port) |
|
| 308 |
+ {
|
|
| 309 |
+ snprintf(name_buf, sizeof(name_buf), "%s_port", name_prefix); |
|
| 310 |
+ setenv_int(es, name_buf, ntohs(addr->addr.in6.sin6_port)); |
|
| 311 |
+ } |
|
| 312 |
+ break; |
|
| 313 |
+ } |
|
| 314 |
+} |
|
| 315 |
+ |
|
| 316 |
+void |
|
| 317 |
+setenv_in_addr_t(struct env_set *es, const char *name_prefix, in_addr_t addr, |
|
| 318 |
+ const unsigned int flags) |
|
| 319 |
+{
|
|
| 320 |
+ if (addr || !(flags & SA_SET_IF_NONZERO)) |
|
| 321 |
+ {
|
|
| 322 |
+ struct openvpn_sockaddr si; |
|
| 323 |
+ CLEAR(si); |
|
| 324 |
+ si.addr.in4.sin_family = AF_INET; |
|
| 325 |
+ si.addr.in4.sin_addr.s_addr = htonl(addr); |
|
| 326 |
+ setenv_sockaddr(es, name_prefix, &si, flags); |
|
| 327 |
+ } |
|
| 328 |
+} |
|
| 329 |
+ |
|
| 330 |
+void |
|
| 331 |
+setenv_in6_addr(struct env_set *es, const char *name_prefix, const struct in6_addr *addr, |
|
| 332 |
+ const unsigned int flags) |
|
| 333 |
+{
|
|
| 334 |
+ if (!IN6_IS_ADDR_UNSPECIFIED(addr) || !(flags & SA_SET_IF_NONZERO)) |
|
| 335 |
+ {
|
|
| 336 |
+ struct openvpn_sockaddr si; |
|
| 337 |
+ CLEAR(si); |
|
| 338 |
+ si.addr.in6.sin6_family = AF_INET6; |
|
| 339 |
+ si.addr.in6.sin6_addr = *addr; |
|
| 340 |
+ setenv_sockaddr(es, name_prefix, &si, flags); |
|
| 341 |
+ } |
|
| 342 |
+} |
|
| 343 |
+ |
|
| 344 |
+void |
|
| 345 |
+setenv_link_socket_actual(struct env_set *es, const char *name_prefix, |
|
| 346 |
+ const struct link_socket_actual *act, const unsigned int flags) |
|
| 347 |
+{
|
|
| 348 |
+ setenv_sockaddr(es, name_prefix, &act->dest, flags); |
|
| 349 |
+} |
|
| 350 |
+ |
|
| 351 |
+/* |
|
| 352 |
+ * Convert protocol names between index and ascii form. |
|
| 353 |
+ */ |
|
| 354 |
+ |
|
| 355 |
+struct proto_names |
|
| 356 |
+{
|
|
| 357 |
+ const char *short_form; |
|
| 358 |
+ const char *display_form; |
|
| 359 |
+ sa_family_t proto_af; |
|
| 360 |
+ int proto; |
|
| 361 |
+}; |
|
| 362 |
+ |
|
| 363 |
+/* Indexed by PROTO_x */ |
|
| 364 |
+static const struct proto_names proto_names[] = {
|
|
| 365 |
+ { "proto-uninitialized", "proto-NONE", AF_UNSPEC, PROTO_NONE },
|
|
| 366 |
+ /* try IPv4 and IPv6 (client), bind dual-stack (server) */ |
|
| 367 |
+ { "udp", "UDP", AF_UNSPEC, PROTO_UDP },
|
|
| 368 |
+ { "tcp-server", "TCP_SERVER", AF_UNSPEC, PROTO_TCP_SERVER },
|
|
| 369 |
+ { "tcp-client", "TCP_CLIENT", AF_UNSPEC, PROTO_TCP_CLIENT },
|
|
| 370 |
+ { "tcp", "TCP", AF_UNSPEC, PROTO_TCP },
|
|
| 371 |
+ /* force IPv4 */ |
|
| 372 |
+ { "udp4", "UDPv4", AF_INET, PROTO_UDP },
|
|
| 373 |
+ { "tcp4-server", "TCPv4_SERVER", AF_INET, PROTO_TCP_SERVER },
|
|
| 374 |
+ { "tcp4-client", "TCPv4_CLIENT", AF_INET, PROTO_TCP_CLIENT },
|
|
| 375 |
+ { "tcp4", "TCPv4", AF_INET, PROTO_TCP },
|
|
| 376 |
+ /* force IPv6 */ |
|
| 377 |
+ { "udp6", "UDPv6", AF_INET6, PROTO_UDP },
|
|
| 378 |
+ { "tcp6-server", "TCPv6_SERVER", AF_INET6, PROTO_TCP_SERVER },
|
|
| 379 |
+ { "tcp6-client", "TCPv6_CLIENT", AF_INET6, PROTO_TCP_CLIENT },
|
|
| 380 |
+ { "tcp6", "TCPv6", AF_INET6, PROTO_TCP },
|
|
| 381 |
+}; |
|
| 382 |
+ |
|
| 383 |
+int |
|
| 384 |
+ascii2proto(const char *proto_name) |
|
| 385 |
+{
|
|
| 386 |
+ for (size_t i = 0; i < SIZE(proto_names); ++i) |
|
| 387 |
+ {
|
|
| 388 |
+ if (!strcmp(proto_name, proto_names[i].short_form)) |
|
| 389 |
+ {
|
|
| 390 |
+ return proto_names[i].proto; |
|
| 391 |
+ } |
|
| 392 |
+ } |
|
| 393 |
+ return -1; |
|
| 394 |
+} |
|
| 395 |
+ |
|
| 396 |
+sa_family_t |
|
| 397 |
+ascii2af(const char *proto_name) |
|
| 398 |
+{
|
|
| 399 |
+ for (size_t i = 0; i < SIZE(proto_names); ++i) |
|
| 400 |
+ {
|
|
| 401 |
+ if (!strcmp(proto_name, proto_names[i].short_form)) |
|
| 402 |
+ {
|
|
| 403 |
+ return proto_names[i].proto_af; |
|
| 404 |
+ } |
|
| 405 |
+ } |
|
| 406 |
+ return 0; |
|
| 407 |
+} |
|
| 408 |
+ |
|
| 409 |
+const char * |
|
| 410 |
+proto2ascii(int proto, sa_family_t af, bool display_form) |
|
| 411 |
+{
|
|
| 412 |
+ for (size_t i = 0; i < SIZE(proto_names); ++i) |
|
| 413 |
+ {
|
|
| 414 |
+ if (proto_names[i].proto_af == af && proto_names[i].proto == proto) |
|
| 415 |
+ {
|
|
| 416 |
+ if (display_form) |
|
| 417 |
+ {
|
|
| 418 |
+ return proto_names[i].display_form; |
|
| 419 |
+ } |
|
| 420 |
+ else |
|
| 421 |
+ {
|
|
| 422 |
+ return proto_names[i].short_form; |
|
| 423 |
+ } |
|
| 424 |
+ } |
|
| 425 |
+ } |
|
| 426 |
+ |
|
| 427 |
+ return "[unknown protocol]"; |
|
| 428 |
+} |
|
| 429 |
+ |
|
| 430 |
+const char * |
|
| 431 |
+proto2ascii_all(struct gc_arena *gc) |
|
| 432 |
+{
|
|
| 433 |
+ struct buffer out = alloc_buf_gc(256, gc); |
|
| 434 |
+ |
|
| 435 |
+ for (size_t i = 0; i < SIZE(proto_names); ++i) |
|
| 436 |
+ {
|
|
| 437 |
+ if (i) |
|
| 438 |
+ {
|
|
| 439 |
+ buf_printf(&out, " "); |
|
| 440 |
+ } |
|
| 441 |
+ buf_printf(&out, "[%s]", proto_names[i].short_form); |
|
| 442 |
+ } |
|
| 443 |
+ return BSTR(&out); |
|
| 444 |
+} |
|
| 445 |
+ |
|
| 446 |
+const char * |
|
| 447 |
+addr_family_name(int af) |
|
| 448 |
+{
|
|
| 449 |
+ switch (af) |
|
| 450 |
+ {
|
|
| 451 |
+ case AF_INET: |
|
| 452 |
+ return "AF_INET"; |
|
| 453 |
+ |
|
| 454 |
+ case AF_INET6: |
|
| 455 |
+ return "AF_INET6"; |
|
| 456 |
+ } |
|
| 457 |
+ return "AF_UNSPEC"; |
|
| 458 |
+} |
|
| 459 |
+ |
|
| 460 |
+/* |
|
| 461 |
+ * Given a local proto, return local proto |
|
| 462 |
+ * if !remote, or compatible remote proto |
|
| 463 |
+ * if remote. |
|
| 464 |
+ * |
|
| 465 |
+ * This is used for options compatibility |
|
| 466 |
+ * checking. |
|
| 467 |
+ * |
|
| 468 |
+ * IPv6 and IPv4 protocols are comptabile but OpenVPN |
|
| 469 |
+ * has always sent UDPv4, TCPv4 over the wire. Keep these |
|
| 470 |
+ * strings for backward compatibility |
|
| 471 |
+ */ |
|
| 472 |
+const char * |
|
| 473 |
+proto_remote(int proto, bool remote) |
|
| 474 |
+{
|
|
| 475 |
+ ASSERT(proto >= 0 && proto < PROTO_N); |
|
| 476 |
+ if (proto == PROTO_UDP) |
|
| 477 |
+ {
|
|
| 478 |
+ return "UDPv4"; |
|
| 479 |
+ } |
|
| 480 |
+ |
|
| 481 |
+ if ((remote && proto == PROTO_TCP_CLIENT) || (!remote && proto == PROTO_TCP_SERVER)) |
|
| 482 |
+ {
|
|
| 483 |
+ return "TCPv4_SERVER"; |
|
| 484 |
+ } |
|
| 485 |
+ if ((remote && proto == PROTO_TCP_SERVER) || (!remote && proto == PROTO_TCP_CLIENT)) |
|
| 486 |
+ {
|
|
| 487 |
+ return "TCPv4_CLIENT"; |
|
| 488 |
+ } |
|
| 489 |
+ |
|
| 490 |
+ ASSERT(0); |
|
| 491 |
+ return ""; /* Make the compiler happy */ |
|
| 492 |
+} |
|
| 493 |
+ |
|
| 494 |
+/** |
|
| 495 |
+ * Small helper function for openvpn_getaddrinfo to print the address |
|
| 496 |
+ * family when resolving fails |
|
| 497 |
+ */ |
|
| 498 |
+static const char * |
|
| 499 |
+getaddrinfo_addr_family_name(int af) |
|
| 500 |
+{
|
|
| 501 |
+ switch (af) |
|
| 502 |
+ {
|
|
| 503 |
+ case AF_INET: |
|
| 504 |
+ return "[AF_INET]"; |
|
| 505 |
+ |
|
| 506 |
+ case AF_INET6: |
|
| 507 |
+ return "[AF_INET6]"; |
|
| 508 |
+ } |
|
| 509 |
+ return ""; |
|
| 510 |
+} |
|
| 511 |
+ |
|
| 512 |
+/* |
|
| 513 |
+ * Prepend a random string to hostname to prevent DNS caching. |
|
| 514 |
+ * For example, foo.bar.gov would be modified to <random-chars>.foo.bar.gov. |
|
| 515 |
+ * Of course, this requires explicit support in the DNS server (wildcard). |
|
| 516 |
+ */ |
|
| 517 |
+static const char * |
|
| 518 |
+hostname_randomize(const char *hostname, struct gc_arena *gc) |
|
| 519 |
+{
|
|
| 520 |
+#define n_rnd_bytes 6 |
|
| 521 |
+ |
|
| 522 |
+ uint8_t rnd_bytes[n_rnd_bytes]; |
|
| 523 |
+ const char *rnd_str; |
|
| 524 |
+ struct buffer hname = alloc_buf_gc(strlen(hostname) + sizeof(rnd_bytes) * 2 + 4, gc); |
|
| 525 |
+ |
|
| 526 |
+ prng_bytes(rnd_bytes, sizeof(rnd_bytes)); |
|
| 527 |
+ rnd_str = format_hex_ex(rnd_bytes, sizeof(rnd_bytes), 40, 0, NULL, gc); |
|
| 528 |
+ buf_printf(&hname, "%s.%s", rnd_str, hostname); |
|
| 529 |
+ return BSTR(&hname); |
|
| 530 |
+#undef n_rnd_bytes |
|
| 531 |
+} |
|
| 532 |
+ |
|
| 533 |
+/* |
|
| 534 |
+ * Translate IPv4/IPv6 addr or hostname into struct addrinfo |
|
| 535 |
+ * If resolve error, try again for resolve_retry_seconds seconds. |
|
| 536 |
+ */ |
|
| 537 |
+int |
|
| 538 |
+openvpn_getaddrinfo(unsigned int flags, const char *hostname, const char *servname, |
|
| 539 |
+ int resolve_retry_seconds, struct signal_info *sig_info, int ai_family, |
|
| 540 |
+ struct addrinfo **res) |
|
| 541 |
+{
|
|
| 542 |
+ struct addrinfo hints; |
|
| 543 |
+ int status; |
|
| 544 |
+ struct signal_info sigrec = { 0 };
|
|
| 545 |
+ int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS; |
|
| 546 |
+ struct gc_arena gc = gc_new(); |
|
| 547 |
+ const char *print_hostname; |
|
| 548 |
+ const char *print_servname; |
|
| 549 |
+ |
|
| 550 |
+ ASSERT(res); |
|
| 551 |
+ |
|
| 552 |
+ ASSERT(hostname || servname); |
|
| 553 |
+ ASSERT(!(flags & GETADDR_HOST_ORDER)); |
|
| 554 |
+ |
|
| 555 |
+ if (servname) |
|
| 556 |
+ {
|
|
| 557 |
+ print_servname = servname; |
|
| 558 |
+ } |
|
| 559 |
+ else |
|
| 560 |
+ {
|
|
| 561 |
+ print_servname = ""; |
|
| 562 |
+ } |
|
| 563 |
+ |
|
| 564 |
+ if (flags & GETADDR_MSG_VIRT_OUT) |
|
| 565 |
+ {
|
|
| 566 |
+ msglevel |= M_MSG_VIRT_OUT; |
|
| 567 |
+ } |
|
| 568 |
+ |
|
| 569 |
+ if ((flags & (GETADDR_FATAL_ON_SIGNAL | GETADDR_WARN_ON_SIGNAL)) && !sig_info) |
|
| 570 |
+ {
|
|
| 571 |
+ sig_info = &sigrec; |
|
| 572 |
+ } |
|
| 573 |
+ |
|
| 574 |
+ /* try numeric ip addr first */ |
|
| 575 |
+ CLEAR(hints); |
|
| 576 |
+ hints.ai_flags = AI_NUMERICHOST; |
|
| 577 |
+ |
|
| 578 |
+ if (flags & GETADDR_PASSIVE) |
|
| 579 |
+ {
|
|
| 580 |
+ hints.ai_flags |= AI_PASSIVE; |
|
| 581 |
+ } |
|
| 582 |
+ |
|
| 583 |
+ if (flags & GETADDR_DATAGRAM) |
|
| 584 |
+ {
|
|
| 585 |
+ hints.ai_socktype = SOCK_DGRAM; |
|
| 586 |
+ } |
|
| 587 |
+ else |
|
| 588 |
+ {
|
|
| 589 |
+ hints.ai_socktype = SOCK_STREAM; |
|
| 590 |
+ } |
|
| 591 |
+ |
|
| 592 |
+ /* if hostname is not set, we want to bind to 'ANY', with |
|
| 593 |
+ * the correct address family - v4-only or v6/v6-dual-stack */ |
|
| 594 |
+ if (!hostname) |
|
| 595 |
+ {
|
|
| 596 |
+ hints.ai_family = ai_family; |
|
| 597 |
+ } |
|
| 598 |
+ |
|
| 599 |
+ status = getaddrinfo(hostname, servname, &hints, res); |
|
| 600 |
+ |
|
| 601 |
+ if (status != 0) /* parse as numeric address failed? */ |
|
| 602 |
+ {
|
|
| 603 |
+ const int fail_wait_interval = 5; /* seconds */ |
|
| 604 |
+ /* Add +4 to cause integer division rounding up (1 + 4) = 5, (0+4)/5=0 */ |
|
| 605 |
+ int resolve_retries = |
|
| 606 |
+ (flags & GETADDR_TRY_ONCE) ? 1 : ((resolve_retry_seconds + 4) / fail_wait_interval); |
|
| 607 |
+ const char *fmt; |
|
| 608 |
+ int level = 0; |
|
| 609 |
+ |
|
| 610 |
+ /* this is not a numeric IP, therefore force resolution using the |
|
| 611 |
+ * provided ai_family */ |
|
| 612 |
+ hints.ai_family = ai_family; |
|
| 613 |
+ |
|
| 614 |
+ if (hostname && (flags & GETADDR_RANDOMIZE)) |
|
| 615 |
+ {
|
|
| 616 |
+ hostname = hostname_randomize(hostname, &gc); |
|
| 617 |
+ } |
|
| 618 |
+ |
|
| 619 |
+ if (hostname) |
|
| 620 |
+ {
|
|
| 621 |
+ print_hostname = hostname; |
|
| 622 |
+ } |
|
| 623 |
+ else |
|
| 624 |
+ {
|
|
| 625 |
+ print_hostname = "undefined"; |
|
| 626 |
+ } |
|
| 627 |
+ |
|
| 628 |
+ fmt = "RESOLVE: Cannot resolve host address: %s:%s%s (%s)"; |
|
| 629 |
+ if ((flags & GETADDR_MENTION_RESOLVE_RETRY) && !resolve_retry_seconds) |
|
| 630 |
+ {
|
|
| 631 |
+ fmt = "RESOLVE: Cannot resolve host address: %s:%s%s (%s)" |
|
| 632 |
+ "(I would have retried this name query if you had " |
|
| 633 |
+ "specified the --resolv-retry option.)"; |
|
| 634 |
+ } |
|
| 635 |
+ |
|
| 636 |
+ if (!(flags & GETADDR_RESOLVE) || status == EAI_FAIL) |
|
| 637 |
+ {
|
|
| 638 |
+ msg(msglevel, "RESOLVE: Cannot parse IP address: %s:%s (%s)", print_hostname, |
|
| 639 |
+ print_servname, gai_strerror(status)); |
|
| 640 |
+ goto done; |
|
| 641 |
+ } |
|
| 642 |
+ |
|
| 643 |
+#ifdef ENABLE_MANAGEMENT |
|
| 644 |
+ if (flags & GETADDR_UPDATE_MANAGEMENT_STATE) |
|
| 645 |
+ {
|
|
| 646 |
+ if (management) |
|
| 647 |
+ {
|
|
| 648 |
+ management_set_state(management, OPENVPN_STATE_RESOLVE, NULL, NULL, NULL, NULL, |
|
| 649 |
+ NULL); |
|
| 650 |
+ } |
|
| 651 |
+ } |
|
| 652 |
+#endif |
|
| 653 |
+ |
|
| 654 |
+ /* |
|
| 655 |
+ * Resolve hostname |
|
| 656 |
+ */ |
|
| 657 |
+ while (true) |
|
| 658 |
+ {
|
|
| 659 |
+#ifndef _WIN32 |
|
| 660 |
+ /* force resolv.conf reload */ |
|
| 661 |
+ res_init(); |
|
| 662 |
+#endif |
|
| 663 |
+ /* try hostname lookup */ |
|
| 664 |
+ hints.ai_flags &= ~AI_NUMERICHOST; |
|
| 665 |
+ dmsg(D_SOCKET_DEBUG, "GETADDRINFO flags=0x%04x ai_family=%d ai_socktype=%d", flags, |
|
| 666 |
+ hints.ai_family, hints.ai_socktype); |
|
| 667 |
+ status = getaddrinfo(hostname, servname, &hints, res); |
|
| 668 |
+ |
|
| 669 |
+ if (sig_info) |
|
| 670 |
+ {
|
|
| 671 |
+ get_signal(&sig_info->signal_received); |
|
| 672 |
+ if (sig_info->signal_received) /* were we interrupted by a signal? */ |
|
| 673 |
+ {
|
|
| 674 |
+ /* why are we overwriting SIGUSR1 ? */ |
|
| 675 |
+ if (signal_reset(sig_info, SIGUSR1) == SIGUSR1) /* ignore SIGUSR1 */ |
|
| 676 |
+ {
|
|
| 677 |
+ msg(level, "RESOLVE: Ignored SIGUSR1 signal received during " |
|
| 678 |
+ "DNS resolution attempt"); |
|
| 679 |
+ } |
|
| 680 |
+ else |
|
| 681 |
+ {
|
|
| 682 |
+ /* turn success into failure (interrupted syscall) */ |
|
| 683 |
+ if (0 == status) |
|
| 684 |
+ {
|
|
| 685 |
+ ASSERT(res); |
|
| 686 |
+ freeaddrinfo(*res); |
|
| 687 |
+ *res = NULL; |
|
| 688 |
+ status = EAI_AGAIN; /* = temporary failure */ |
|
| 689 |
+ errno = EINTR; |
|
| 690 |
+ } |
|
| 691 |
+ goto done; |
|
| 692 |
+ } |
|
| 693 |
+ } |
|
| 694 |
+ } |
|
| 695 |
+ |
|
| 696 |
+ /* success? */ |
|
| 697 |
+ if (0 == status) |
|
| 698 |
+ {
|
|
| 699 |
+ break; |
|
| 700 |
+ } |
|
| 701 |
+ |
|
| 702 |
+ /* resolve lookup failed, should we |
|
| 703 |
+ * continue or fail? */ |
|
| 704 |
+ level = msglevel; |
|
| 705 |
+ if (resolve_retries > 0) |
|
| 706 |
+ {
|
|
| 707 |
+ level = D_RESOLVE_ERRORS; |
|
| 708 |
+ } |
|
| 709 |
+ |
|
| 710 |
+ msg(level, fmt, print_hostname, print_servname, getaddrinfo_addr_family_name(ai_family), |
|
| 711 |
+ gai_strerror(status)); |
|
| 712 |
+ |
|
| 713 |
+ if (--resolve_retries <= 0) |
|
| 714 |
+ {
|
|
| 715 |
+ goto done; |
|
| 716 |
+ } |
|
| 717 |
+ |
|
| 718 |
+ management_sleep(fail_wait_interval); |
|
| 719 |
+ } |
|
| 720 |
+ |
|
| 721 |
+ ASSERT(res); |
|
| 722 |
+ |
|
| 723 |
+ /* hostname resolve succeeded */ |
|
| 724 |
+ |
|
| 725 |
+ /* |
|
| 726 |
+ * Do not choose an IP Addresse by random or change the order * |
|
| 727 |
+ * of IP addresses, doing so will break RFC 3484 address selection * |
|
| 728 |
+ */ |
|
| 729 |
+ } |
|
| 730 |
+ else |
|
| 731 |
+ {
|
|
| 732 |
+ /* IP address parse succeeded */ |
|
| 733 |
+ if (flags & GETADDR_RANDOMIZE) |
|
| 734 |
+ {
|
|
| 735 |
+ msg(M_WARN, "WARNING: ignoring --remote-random-hostname because the " |
|
| 736 |
+ "hostname is an IP address"); |
|
| 737 |
+ } |
|
| 738 |
+ } |
|
| 739 |
+ |
|
| 740 |
+done: |
|
| 741 |
+ if (sig_info && sig_info->signal_received) |
|
| 742 |
+ {
|
|
| 743 |
+ int level = 0; |
|
| 744 |
+ if (flags & GETADDR_FATAL_ON_SIGNAL) |
|
| 745 |
+ {
|
|
| 746 |
+ level = M_FATAL; |
|
| 747 |
+ } |
|
| 748 |
+ else if (flags & GETADDR_WARN_ON_SIGNAL) |
|
| 749 |
+ {
|
|
| 750 |
+ level = M_WARN; |
|
| 751 |
+ } |
|
| 752 |
+ msg(level, "RESOLVE: signal received during DNS resolution attempt"); |
|
| 753 |
+ } |
|
| 754 |
+ |
|
| 755 |
+ gc_free(&gc); |
|
| 756 |
+ return status; |
|
| 757 |
+} |
|
| 758 |
+ |
|
| 759 |
+/* |
|
| 760 |
+ * We do our own inet_aton because the glibc function |
|
| 761 |
+ * isn't very good about error checking. |
|
| 762 |
+ */ |
|
| 763 |
+int |
|
| 764 |
+openvpn_inet_aton(const char *dotted_quad, struct in_addr *addr) |
|
| 765 |
+{
|
|
| 766 |
+ unsigned int a, b, c, d; |
|
| 767 |
+ |
|
| 768 |
+ CLEAR(*addr); |
|
| 769 |
+ if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) == 4) |
|
| 770 |
+ {
|
|
| 771 |
+ if (a < 256 && b < 256 && c < 256 && d < 256) |
|
| 772 |
+ {
|
|
| 773 |
+ addr->s_addr = htonl(a << 24 | b << 16 | c << 8 | d); |
|
| 774 |
+ return OIA_IP; /* good dotted quad */ |
|
| 775 |
+ } |
|
| 776 |
+ } |
|
| 777 |
+ if (string_class(dotted_quad, CC_DIGIT | CC_DOT, 0)) |
|
| 778 |
+ {
|
|
| 779 |
+ return OIA_ERROR; /* probably a badly formatted dotted quad */ |
|
| 780 |
+ } |
|
| 781 |
+ else |
|
| 782 |
+ {
|
|
| 783 |
+ return OIA_HOSTNAME; /* probably a hostname */ |
|
| 784 |
+ } |
|
| 785 |
+} |
|
| 786 |
+ |
|
| 787 |
+bool |
|
| 788 |
+ip_addr_dotted_quad_safe(const char *dotted_quad) |
|
| 789 |
+{
|
|
| 790 |
+ /* verify non-NULL */ |
|
| 791 |
+ if (!dotted_quad) |
|
| 792 |
+ {
|
|
| 793 |
+ return false; |
|
| 794 |
+ } |
|
| 795 |
+ |
|
| 796 |
+ /* verify length is within limits */ |
|
| 797 |
+ if (strlen(dotted_quad) > 15) |
|
| 798 |
+ {
|
|
| 799 |
+ return false; |
|
| 800 |
+ } |
|
| 801 |
+ |
|
| 802 |
+ /* verify that all chars are either numeric or '.' and that no numeric |
|
| 803 |
+ * substring is greater than 3 chars */ |
|
| 804 |
+ {
|
|
| 805 |
+ int nnum = 0; |
|
| 806 |
+ const char *p = dotted_quad; |
|
| 807 |
+ int c; |
|
| 808 |
+ |
|
| 809 |
+ while ((c = *p++)) |
|
| 810 |
+ {
|
|
| 811 |
+ if (c >= '0' && c <= '9') |
|
| 812 |
+ {
|
|
| 813 |
+ ++nnum; |
|
| 814 |
+ if (nnum > 3) |
|
| 815 |
+ {
|
|
| 816 |
+ return false; |
|
| 817 |
+ } |
|
| 818 |
+ } |
|
| 819 |
+ else if (c == '.') |
|
| 820 |
+ {
|
|
| 821 |
+ nnum = 0; |
|
| 822 |
+ } |
|
| 823 |
+ else |
|
| 824 |
+ {
|
|
| 825 |
+ return false; |
|
| 826 |
+ } |
|
| 827 |
+ } |
|
| 828 |
+ } |
|
| 829 |
+ |
|
| 830 |
+ /* verify that string will convert to IP address */ |
|
| 831 |
+ {
|
|
| 832 |
+ struct in_addr a; |
|
| 833 |
+ return openvpn_inet_aton(dotted_quad, &a) == OIA_IP; |
|
| 834 |
+ } |
|
| 835 |
+} |
|
| 836 |
+ |
|
| 837 |
+bool |
|
| 838 |
+ipv6_addr_safe(const char *ipv6_text_addr) |
|
| 839 |
+{
|
|
| 840 |
+ /* verify non-NULL */ |
|
| 841 |
+ if (!ipv6_text_addr) |
|
| 842 |
+ {
|
|
| 843 |
+ return false; |
|
| 844 |
+ } |
|
| 845 |
+ |
|
| 846 |
+ /* verify length is within limits */ |
|
| 847 |
+ if (strlen(ipv6_text_addr) > INET6_ADDRSTRLEN) |
|
| 848 |
+ {
|
|
| 849 |
+ return false; |
|
| 850 |
+ } |
|
| 851 |
+ |
|
| 852 |
+ /* verify that string will convert to IPv6 address */ |
|
| 853 |
+ {
|
|
| 854 |
+ struct in6_addr a6; |
|
| 855 |
+ return inet_pton(AF_INET6, ipv6_text_addr, &a6) == 1; |
|
| 856 |
+ } |
|
| 857 |
+} |
|
| 858 |
+ |
|
| 859 |
+static bool |
|
| 860 |
+dns_addr_safe(const char *addr) |
|
| 861 |
+{
|
|
| 862 |
+ if (addr) |
|
| 863 |
+ {
|
|
| 864 |
+ const size_t len = strlen(addr); |
|
| 865 |
+ return len > 0 && len <= 255 && string_class(addr, CC_ALNUM | CC_DASH | CC_DOT, 0); |
|
| 866 |
+ } |
|
| 867 |
+ else |
|
| 868 |
+ {
|
|
| 869 |
+ return false; |
|
| 870 |
+ } |
|
| 871 |
+} |
|
| 872 |
+ |
|
| 873 |
+bool |
|
| 874 |
+ip_or_dns_addr_safe(const char *addr, const bool allow_fqdn) |
|
| 875 |
+{
|
|
| 876 |
+ if (ip_addr_dotted_quad_safe(addr)) |
|
| 877 |
+ {
|
|
| 878 |
+ return true; |
|
| 879 |
+ } |
|
| 880 |
+ else if (allow_fqdn) |
|
| 881 |
+ {
|
|
| 882 |
+ return dns_addr_safe(addr); |
|
| 883 |
+ } |
|
| 884 |
+ else |
|
| 885 |
+ {
|
|
| 886 |
+ return false; |
|
| 887 |
+ } |
|
| 888 |
+} |
|
| 889 |
+ |
|
| 890 |
+bool |
|
| 891 |
+mac_addr_safe(const char *mac_addr) |
|
| 892 |
+{
|
|
| 893 |
+ /* verify non-NULL */ |
|
| 894 |
+ if (!mac_addr) |
|
| 895 |
+ {
|
|
| 896 |
+ return false; |
|
| 897 |
+ } |
|
| 898 |
+ |
|
| 899 |
+ /* verify length is within limits */ |
|
| 900 |
+ if (strlen(mac_addr) > 17) |
|
| 901 |
+ {
|
|
| 902 |
+ return false; |
|
| 903 |
+ } |
|
| 904 |
+ |
|
| 905 |
+ /* verify that all chars are either alphanumeric or ':' and that no |
|
| 906 |
+ * alphanumeric substring is greater than 2 chars */ |
|
| 907 |
+ {
|
|
| 908 |
+ int nnum = 0; |
|
| 909 |
+ const char *p = mac_addr; |
|
| 910 |
+ int c; |
|
| 911 |
+ |
|
| 912 |
+ while ((c = *p++)) |
|
| 913 |
+ {
|
|
| 914 |
+ if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) |
|
| 915 |
+ {
|
|
| 916 |
+ ++nnum; |
|
| 917 |
+ if (nnum > 2) |
|
| 918 |
+ {
|
|
| 919 |
+ return false; |
|
| 920 |
+ } |
|
| 921 |
+ } |
|
| 922 |
+ else if (c == ':') |
|
| 923 |
+ {
|
|
| 924 |
+ nnum = 0; |
|
| 925 |
+ } |
|
| 926 |
+ else |
|
| 927 |
+ {
|
|
| 928 |
+ return false; |
|
| 929 |
+ } |
|
| 930 |
+ } |
|
| 931 |
+ } |
|
| 932 |
+ |
|
| 933 |
+ /* error-checking is left to script invoked in lladdr.c */ |
|
| 934 |
+ return true; |
|
| 935 |
+} |
| 0 | 936 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,491 @@ |
| 0 |
+/* |
|
| 1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
| 2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
| 3 |
+ * session authentication and key exchange, |
|
| 4 |
+ * packet encryption, packet authentication, and |
|
| 5 |
+ * packet compression. |
|
| 6 |
+ * |
|
| 7 |
+ * Copyright (C) 2002-2025 OpenVPN Inc <sales@openvpn.net> |
|
| 8 |
+ * |
|
| 9 |
+ * This program is free software; you can redistribute it and/or modify |
|
| 10 |
+ * it under the terms of the GNU General Public License version 2 |
|
| 11 |
+ * as published by the Free Software Foundation. |
|
| 12 |
+ * |
|
| 13 |
+ * This program is distributed in the hope that it will be useful, |
|
| 14 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 15 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 16 |
+ * GNU General Public License for more details. |
|
| 17 |
+ * |
|
| 18 |
+ * You should have received a copy of the GNU General Public License along |
|
| 19 |
+ * with this program; if not, see <https://www.gnu.org/licenses/>. |
|
| 20 |
+ */ |
|
| 21 |
+ |
|
| 22 |
+#ifndef SOCKET_UTIL_H |
|
| 23 |
+#define SOCKET_UTIL_H |
|
| 24 |
+ |
|
| 25 |
+#include "buffer.h" |
|
| 26 |
+#include "env_set.h" |
|
| 27 |
+#include "sig.h" |
|
| 28 |
+ |
|
| 29 |
+#define PS_SHOW_PORT_IF_DEFINED (1 << 0) |
|
| 30 |
+#define PS_SHOW_PORT (1 << 1) |
|
| 31 |
+#define PS_SHOW_PKTINFO (1 << 2) |
|
| 32 |
+#define PS_DONT_SHOW_ADDR (1 << 3) |
|
| 33 |
+#define PS_DONT_SHOW_FAMILY (1 << 4) |
|
| 34 |
+ |
|
| 35 |
+/* OpenVPN sockaddr struct */ |
|
| 36 |
+struct openvpn_sockaddr |
|
| 37 |
+{
|
|
| 38 |
+ /*int dummy;*/ /* add offset to force a bug if sa not explicitly dereferenced */ |
|
| 39 |
+ union |
|
| 40 |
+ {
|
|
| 41 |
+ struct sockaddr sa; |
|
| 42 |
+ struct sockaddr_in in4; |
|
| 43 |
+ struct sockaddr_in6 in6; |
|
| 44 |
+ } addr; |
|
| 45 |
+}; |
|
| 46 |
+ |
|
| 47 |
+/* actual address of remote, based on source address of received packets */ |
|
| 48 |
+struct link_socket_actual |
|
| 49 |
+{
|
|
| 50 |
+ /*int dummy;*/ /* add offset to force a bug if dest not explicitly dereferenced */ |
|
| 51 |
+ |
|
| 52 |
+ struct openvpn_sockaddr dest; |
|
| 53 |
+#if ENABLE_IP_PKTINFO |
|
| 54 |
+ union |
|
| 55 |
+ {
|
|
| 56 |
+#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) |
|
| 57 |
+ struct in_pktinfo in4; |
|
| 58 |
+#elif defined(IP_RECVDSTADDR) |
|
| 59 |
+ struct in_addr in4; |
|
| 60 |
+#endif |
|
| 61 |
+ struct in6_pktinfo in6; |
|
| 62 |
+ } pi; |
|
| 63 |
+#endif |
|
| 64 |
+}; |
|
| 65 |
+ |
|
| 66 |
+const char *print_sockaddr_ex(const struct sockaddr *addr, const char *separator, |
|
| 67 |
+ const unsigned int flags, struct gc_arena *gc); |
|
| 68 |
+ |
|
| 69 |
+static inline const char * |
|
| 70 |
+print_openvpn_sockaddr(const struct openvpn_sockaddr *addr, struct gc_arena *gc) |
|
| 71 |
+{
|
|
| 72 |
+ return print_sockaddr_ex(&addr->addr.sa, ":", PS_SHOW_PORT, gc); |
|
| 73 |
+} |
|
| 74 |
+ |
|
| 75 |
+static inline const char * |
|
| 76 |
+print_sockaddr(const struct sockaddr *addr, struct gc_arena *gc) |
|
| 77 |
+{
|
|
| 78 |
+ return print_sockaddr_ex(addr, ":", PS_SHOW_PORT, gc); |
|
| 79 |
+} |
|
| 80 |
+ |
|
| 81 |
+ |
|
| 82 |
+const char *print_link_socket_actual_ex(const struct link_socket_actual *act, const char *separator, |
|
| 83 |
+ const unsigned int flags, struct gc_arena *gc); |
|
| 84 |
+ |
|
| 85 |
+const char *print_link_socket_actual(const struct link_socket_actual *act, struct gc_arena *gc); |
|
| 86 |
+ |
|
| 87 |
+ |
|
| 88 |
+#define IA_EMPTY_IF_UNDEF (1 << 0) |
|
| 89 |
+#define IA_NET_ORDER (1 << 1) |
|
| 90 |
+const char *print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc); |
|
| 91 |
+ |
|
| 92 |
+const char *print_in6_addr(struct in6_addr addr6, unsigned int flags, struct gc_arena *gc); |
|
| 93 |
+ |
|
| 94 |
+const char *print_in_port_t(in_port_t port, struct gc_arena *gc); |
|
| 95 |
+ |
|
| 96 |
+struct in6_addr add_in6_addr(struct in6_addr base, uint32_t add); |
|
| 97 |
+ |
|
| 98 |
+#define SA_IP_PORT (1 << 0) |
|
| 99 |
+#define SA_SET_IF_NONZERO (1 << 1) |
|
| 100 |
+void setenv_sockaddr(struct env_set *es, const char *name_prefix, |
|
| 101 |
+ const struct openvpn_sockaddr *addr, const unsigned int flags); |
|
| 102 |
+ |
|
| 103 |
+void setenv_in_addr_t(struct env_set *es, const char *name_prefix, in_addr_t addr, |
|
| 104 |
+ const unsigned int flags); |
|
| 105 |
+ |
|
| 106 |
+void setenv_in6_addr(struct env_set *es, const char *name_prefix, const struct in6_addr *addr, |
|
| 107 |
+ const unsigned int flags); |
|
| 108 |
+ |
|
| 109 |
+void setenv_link_socket_actual(struct env_set *es, const char *name_prefix, |
|
| 110 |
+ const struct link_socket_actual *act, const unsigned int flags); |
|
| 111 |
+ |
|
| 112 |
+/* |
|
| 113 |
+ * DNS resolution |
|
| 114 |
+ */ |
|
| 115 |
+ |
|
| 116 |
+#define GETADDR_RESOLVE (1 << 0) |
|
| 117 |
+#define GETADDR_FATAL (1 << 1) |
|
| 118 |
+#define GETADDR_HOST_ORDER (1 << 2) |
|
| 119 |
+#define GETADDR_MENTION_RESOLVE_RETRY (1 << 3) |
|
| 120 |
+#define GETADDR_FATAL_ON_SIGNAL (1 << 4) |
|
| 121 |
+#define GETADDR_WARN_ON_SIGNAL (1 << 5) |
|
| 122 |
+#define GETADDR_MSG_VIRT_OUT (1 << 6) |
|
| 123 |
+#define GETADDR_TRY_ONCE (1 << 7) |
|
| 124 |
+#define GETADDR_UPDATE_MANAGEMENT_STATE (1 << 8) |
|
| 125 |
+#define GETADDR_RANDOMIZE (1 << 9) |
|
| 126 |
+#define GETADDR_PASSIVE (1 << 10) |
|
| 127 |
+#define GETADDR_DATAGRAM (1 << 11) |
|
| 128 |
+ |
|
| 129 |
+#define GETADDR_CACHE_MASK (GETADDR_DATAGRAM | GETADDR_PASSIVE) |
|
| 130 |
+ |
|
| 131 |
+/** |
|
| 132 |
+ * Translate an IPv4 addr or hostname from string form to in_addr_t |
|
| 133 |
+ * |
|
| 134 |
+ * In case of resolve error, it will try again for |
|
| 135 |
+ * resolve_retry_seconds seconds. |
|
| 136 |
+ */ |
|
| 137 |
+in_addr_t getaddr(unsigned int flags, const char *hostname, int resolve_retry_seconds, |
|
| 138 |
+ bool *succeeded, struct signal_info *sig_info); |
|
| 139 |
+ |
|
| 140 |
+/** |
|
| 141 |
+ * Translate an IPv6 addr or hostname from string form to in6_addr |
|
| 142 |
+ */ |
|
| 143 |
+bool get_ipv6_addr(const char *hostname, struct in6_addr *network, unsigned int *netbits, |
|
| 144 |
+ int msglevel); |
|
| 145 |
+ |
|
| 146 |
+int openvpn_getaddrinfo(unsigned int flags, const char *hostname, const char *servname, |
|
| 147 |
+ int resolve_retry_seconds, struct signal_info *sig_info, int ai_family, |
|
| 148 |
+ struct addrinfo **res); |
|
| 149 |
+ |
|
| 150 |
+/* return values of openvpn_inet_aton */ |
|
| 151 |
+#define OIA_HOSTNAME 0 |
|
| 152 |
+#define OIA_IP 1 |
|
| 153 |
+#define OIA_ERROR -1 |
|
| 154 |
+int openvpn_inet_aton(const char *dotted_quad, struct in_addr *addr); |
|
| 155 |
+ |
|
| 156 |
+/* integrity validation on pulled options */ |
|
| 157 |
+bool ip_addr_dotted_quad_safe(const char *dotted_quad); |
|
| 158 |
+ |
|
| 159 |
+bool ip_or_dns_addr_safe(const char *addr, const bool allow_fqdn); |
|
| 160 |
+ |
|
| 161 |
+bool mac_addr_safe(const char *mac_addr); |
|
| 162 |
+ |
|
| 163 |
+bool ipv6_addr_safe(const char *ipv6_text_addr); |
|
| 164 |
+ |
|
| 165 |
+/* |
|
| 166 |
+ * Transport protocol naming and other details. |
|
| 167 |
+ */ |
|
| 168 |
+ |
|
| 169 |
+/* |
|
| 170 |
+ * Use enum's instead of #define to allow for easier |
|
| 171 |
+ * optional proto support |
|
| 172 |
+ */ |
|
| 173 |
+enum proto_num |
|
| 174 |
+{
|
|
| 175 |
+ PROTO_NONE, /* catch for uninitialized */ |
|
| 176 |
+ PROTO_UDP, |
|
| 177 |
+ PROTO_TCP, |
|
| 178 |
+ PROTO_TCP_SERVER, |
|
| 179 |
+ PROTO_TCP_CLIENT, |
|
| 180 |
+ PROTO_N |
|
| 181 |
+}; |
|
| 182 |
+ |
|
| 183 |
+static inline bool |
|
| 184 |
+proto_is_net(int proto) |
|
| 185 |
+{
|
|
| 186 |
+ ASSERT(proto >= 0 && proto < PROTO_N); |
|
| 187 |
+ return proto != PROTO_NONE; |
|
| 188 |
+} |
|
| 189 |
+ |
|
| 190 |
+/** |
|
| 191 |
+ * @brief Returns if the protocol being used is UDP |
|
| 192 |
+ */ |
|
| 193 |
+static inline bool |
|
| 194 |
+proto_is_udp(int proto) |
|
| 195 |
+{
|
|
| 196 |
+ ASSERT(proto >= 0 && proto < PROTO_N); |
|
| 197 |
+ return proto == PROTO_UDP; |
|
| 198 |
+} |
|
| 199 |
+ |
|
| 200 |
+/** |
|
| 201 |
+ * @brief Return if the protocol is datagram (UDP) |
|
| 202 |
+ * |
|
| 203 |
+ */ |
|
| 204 |
+static inline bool |
|
| 205 |
+proto_is_dgram(int proto) |
|
| 206 |
+{
|
|
| 207 |
+ return proto_is_udp(proto); |
|
| 208 |
+} |
|
| 209 |
+ |
|
| 210 |
+/** |
|
| 211 |
+ * @brief returns if the proto is a TCP variant (tcp-server, tcp-client or tcp) |
|
| 212 |
+ */ |
|
| 213 |
+static inline bool |
|
| 214 |
+proto_is_tcp(int proto) |
|
| 215 |
+{
|
|
| 216 |
+ ASSERT(proto >= 0 && proto < PROTO_N); |
|
| 217 |
+ return proto == PROTO_TCP_CLIENT || proto == PROTO_TCP_SERVER; |
|
| 218 |
+} |
|
| 219 |
+ |
|
| 220 |
+int ascii2proto(const char *proto_name); |
|
| 221 |
+ |
|
| 222 |
+sa_family_t ascii2af(const char *proto_name); |
|
| 223 |
+ |
|
| 224 |
+const char *proto2ascii(int proto, sa_family_t af, bool display_form); |
|
| 225 |
+ |
|
| 226 |
+const char *proto2ascii_all(struct gc_arena *gc); |
|
| 227 |
+ |
|
| 228 |
+const char *proto_remote(int proto, bool remote); |
|
| 229 |
+ |
|
| 230 |
+const char *addr_family_name(int af); |
|
| 231 |
+ |
|
| 232 |
+static inline bool |
|
| 233 |
+addr_defined(const struct openvpn_sockaddr *addr) |
|
| 234 |
+{
|
|
| 235 |
+ if (!addr) |
|
| 236 |
+ {
|
|
| 237 |
+ return 0; |
|
| 238 |
+ } |
|
| 239 |
+ switch (addr->addr.sa.sa_family) |
|
| 240 |
+ {
|
|
| 241 |
+ case AF_INET: |
|
| 242 |
+ return addr->addr.in4.sin_addr.s_addr != 0; |
|
| 243 |
+ |
|
| 244 |
+ case AF_INET6: |
|
| 245 |
+ return !IN6_IS_ADDR_UNSPECIFIED(&addr->addr.in6.sin6_addr); |
|
| 246 |
+ |
|
| 247 |
+ default: |
|
| 248 |
+ return 0; |
|
| 249 |
+ } |
|
| 250 |
+} |
|
| 251 |
+ |
|
| 252 |
+static inline bool |
|
| 253 |
+addr_local(const struct sockaddr *addr) |
|
| 254 |
+{
|
|
| 255 |
+ if (!addr) |
|
| 256 |
+ {
|
|
| 257 |
+ return false; |
|
| 258 |
+ } |
|
| 259 |
+ switch (addr->sa_family) |
|
| 260 |
+ {
|
|
| 261 |
+ case AF_INET: |
|
| 262 |
+ return ((const struct sockaddr_in *)addr)->sin_addr.s_addr == htonl(INADDR_LOOPBACK); |
|
| 263 |
+ |
|
| 264 |
+ case AF_INET6: |
|
| 265 |
+ return IN6_IS_ADDR_LOOPBACK(&((const struct sockaddr_in6 *)addr)->sin6_addr); |
|
| 266 |
+ |
|
| 267 |
+ default: |
|
| 268 |
+ return false; |
|
| 269 |
+ } |
|
| 270 |
+} |
|
| 271 |
+ |
|
| 272 |
+ |
|
| 273 |
+static inline bool |
|
| 274 |
+addr_defined_ipi(const struct link_socket_actual *lsa) |
|
| 275 |
+{
|
|
| 276 |
+#if ENABLE_IP_PKTINFO |
|
| 277 |
+ if (!lsa) |
|
| 278 |
+ {
|
|
| 279 |
+ return 0; |
|
| 280 |
+ } |
|
| 281 |
+ switch (lsa->dest.addr.sa.sa_family) |
|
| 282 |
+ {
|
|
| 283 |
+#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) |
|
| 284 |
+ case AF_INET: |
|
| 285 |
+ return lsa->pi.in4.ipi_spec_dst.s_addr != 0; |
|
| 286 |
+ |
|
| 287 |
+#elif defined(IP_RECVDSTADDR) |
|
| 288 |
+ case AF_INET: |
|
| 289 |
+ return lsa->pi.in4.s_addr != 0; |
|
| 290 |
+ |
|
| 291 |
+#endif |
|
| 292 |
+ case AF_INET6: |
|
| 293 |
+ return !IN6_IS_ADDR_UNSPECIFIED(&lsa->pi.in6.ipi6_addr); |
|
| 294 |
+ |
|
| 295 |
+ default: |
|
| 296 |
+ return 0; |
|
| 297 |
+ } |
|
| 298 |
+#else /* if ENABLE_IP_PKTINFO */ |
|
| 299 |
+ ASSERT(0); |
|
| 300 |
+#endif |
|
| 301 |
+ return false; |
|
| 302 |
+} |
|
| 303 |
+ |
|
| 304 |
+/* |
|
| 305 |
+ * Overhead added to packets by various protocols. |
|
| 306 |
+ */ |
|
| 307 |
+static inline int |
|
| 308 |
+datagram_overhead(sa_family_t af, int proto) |
|
| 309 |
+{
|
|
| 310 |
+ int overhead = 0; |
|
| 311 |
+ overhead += (proto == PROTO_UDP) ? 8 : 20; |
|
| 312 |
+ overhead += (af == AF_INET) ? 20 : 40; |
|
| 313 |
+ return overhead; |
|
| 314 |
+} |
|
| 315 |
+ |
|
| 316 |
+/* |
|
| 317 |
+ * Misc inline functions |
|
| 318 |
+ */ |
|
| 319 |
+ |
|
| 320 |
+static inline bool |
|
| 321 |
+link_socket_proto_connection_oriented(int proto) |
|
| 322 |
+{
|
|
| 323 |
+ return !proto_is_dgram(proto); |
|
| 324 |
+} |
|
| 325 |
+ |
|
| 326 |
+static inline bool |
|
| 327 |
+link_socket_actual_defined(const struct link_socket_actual *act) |
|
| 328 |
+{
|
|
| 329 |
+ return act && addr_defined(&act->dest); |
|
| 330 |
+} |
|
| 331 |
+ |
|
| 332 |
+static inline bool |
|
| 333 |
+addr_match(const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2) |
|
| 334 |
+{
|
|
| 335 |
+ switch (a1->addr.sa.sa_family) |
|
| 336 |
+ {
|
|
| 337 |
+ case AF_INET: |
|
| 338 |
+ return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr; |
|
| 339 |
+ |
|
| 340 |
+ case AF_INET6: |
|
| 341 |
+ return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr); |
|
| 342 |
+ } |
|
| 343 |
+ ASSERT(0); |
|
| 344 |
+ return false; |
|
| 345 |
+} |
|
| 346 |
+ |
|
| 347 |
+static inline bool |
|
| 348 |
+addrlist_match(const struct openvpn_sockaddr *a1, const struct addrinfo *addrlist) |
|
| 349 |
+{
|
|
| 350 |
+ const struct addrinfo *curele; |
|
| 351 |
+ for (curele = addrlist; curele; curele = curele->ai_next) |
|
| 352 |
+ {
|
|
| 353 |
+ switch (a1->addr.sa.sa_family) |
|
| 354 |
+ {
|
|
| 355 |
+ case AF_INET: |
|
| 356 |
+ if (a1->addr.in4.sin_addr.s_addr |
|
| 357 |
+ == ((struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr) |
|
| 358 |
+ {
|
|
| 359 |
+ return true; |
|
| 360 |
+ } |
|
| 361 |
+ break; |
|
| 362 |
+ |
|
| 363 |
+ case AF_INET6: |
|
| 364 |
+ if (IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, |
|
| 365 |
+ &((struct sockaddr_in6 *)curele->ai_addr)->sin6_addr)) |
|
| 366 |
+ {
|
|
| 367 |
+ return true; |
|
| 368 |
+ } |
|
| 369 |
+ break; |
|
| 370 |
+ |
|
| 371 |
+ default: |
|
| 372 |
+ ASSERT(0); |
|
| 373 |
+ } |
|
| 374 |
+ } |
|
| 375 |
+ return false; |
|
| 376 |
+} |
|
| 377 |
+ |
|
| 378 |
+static inline bool |
|
| 379 |
+addrlist_port_match(const struct openvpn_sockaddr *a1, const struct addrinfo *a2) |
|
| 380 |
+{
|
|
| 381 |
+ const struct addrinfo *curele; |
|
| 382 |
+ for (curele = a2; curele; curele = curele->ai_next) |
|
| 383 |
+ {
|
|
| 384 |
+ switch (a1->addr.sa.sa_family) |
|
| 385 |
+ {
|
|
| 386 |
+ case AF_INET: |
|
| 387 |
+ if (curele->ai_family == AF_INET |
|
| 388 |
+ && a1->addr.in4.sin_addr.s_addr |
|
| 389 |
+ == ((struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr |
|
| 390 |
+ && a1->addr.in4.sin_port == ((struct sockaddr_in *)curele->ai_addr)->sin_port) |
|
| 391 |
+ {
|
|
| 392 |
+ return true; |
|
| 393 |
+ } |
|
| 394 |
+ break; |
|
| 395 |
+ |
|
| 396 |
+ case AF_INET6: |
|
| 397 |
+ if (curele->ai_family == AF_INET6 |
|
| 398 |
+ && IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, |
|
| 399 |
+ &((struct sockaddr_in6 *)curele->ai_addr)->sin6_addr) |
|
| 400 |
+ && a1->addr.in6.sin6_port |
|
| 401 |
+ == ((struct sockaddr_in6 *)curele->ai_addr)->sin6_port) |
|
| 402 |
+ {
|
|
| 403 |
+ return true; |
|
| 404 |
+ } |
|
| 405 |
+ break; |
|
| 406 |
+ |
|
| 407 |
+ default: |
|
| 408 |
+ ASSERT(0); |
|
| 409 |
+ } |
|
| 410 |
+ } |
|
| 411 |
+ return false; |
|
| 412 |
+} |
|
| 413 |
+ |
|
| 414 |
+ |
|
| 415 |
+static inline bool |
|
| 416 |
+addr_port_match(const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2) |
|
| 417 |
+{
|
|
| 418 |
+ switch (a1->addr.sa.sa_family) |
|
| 419 |
+ {
|
|
| 420 |
+ case AF_INET: |
|
| 421 |
+ return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr |
|
| 422 |
+ && a1->addr.in4.sin_port == a2->addr.in4.sin_port; |
|
| 423 |
+ |
|
| 424 |
+ case AF_INET6: |
|
| 425 |
+ return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr) |
|
| 426 |
+ && a1->addr.in6.sin6_port == a2->addr.in6.sin6_port; |
|
| 427 |
+ } |
|
| 428 |
+ ASSERT(0); |
|
| 429 |
+ return false; |
|
| 430 |
+} |
|
| 431 |
+ |
|
| 432 |
+static inline bool |
|
| 433 |
+addr_match_proto(const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2, |
|
| 434 |
+ const int proto) |
|
| 435 |
+{
|
|
| 436 |
+ return link_socket_proto_connection_oriented(proto) ? addr_match(a1, a2) |
|
| 437 |
+ : addr_port_match(a1, a2); |
|
| 438 |
+} |
|
| 439 |
+ |
|
| 440 |
+ |
|
| 441 |
+static inline bool |
|
| 442 |
+addrlist_match_proto(const struct openvpn_sockaddr *a1, struct addrinfo *addr_list, const int proto) |
|
| 443 |
+{
|
|
| 444 |
+ return link_socket_proto_connection_oriented(proto) ? addrlist_match(a1, addr_list) |
|
| 445 |
+ : addrlist_port_match(a1, addr_list); |
|
| 446 |
+} |
|
| 447 |
+ |
|
| 448 |
+static inline void |
|
| 449 |
+addr_zero_host(struct openvpn_sockaddr *addr) |
|
| 450 |
+{
|
|
| 451 |
+ switch (addr->addr.sa.sa_family) |
|
| 452 |
+ {
|
|
| 453 |
+ case AF_INET: |
|
| 454 |
+ addr->addr.in4.sin_addr.s_addr = 0; |
|
| 455 |
+ break; |
|
| 456 |
+ |
|
| 457 |
+ case AF_INET6: |
|
| 458 |
+ memset(&addr->addr.in6.sin6_addr, 0, sizeof(struct in6_addr)); |
|
| 459 |
+ break; |
|
| 460 |
+ } |
|
| 461 |
+} |
|
| 462 |
+ |
|
| 463 |
+static inline int |
|
| 464 |
+af_addr_size(sa_family_t af) |
|
| 465 |
+{
|
|
| 466 |
+ switch (af) |
|
| 467 |
+ {
|
|
| 468 |
+ case AF_INET: |
|
| 469 |
+ return sizeof(struct sockaddr_in); |
|
| 470 |
+ |
|
| 471 |
+ case AF_INET6: |
|
| 472 |
+ return sizeof(struct sockaddr_in6); |
|
| 473 |
+ |
|
| 474 |
+ default: |
|
| 475 |
+#if 0 |
|
| 476 |
+ /* could be called from socket_do_accept() with empty addr */ |
|
| 477 |
+ msg(M_ERR, "Bad address family: %d\n", af); |
|
| 478 |
+ ASSERT(0); |
|
| 479 |
+#endif |
|
| 480 |
+ return 0; |
|
| 481 |
+ } |
|
| 482 |
+} |
|
| 483 |
+ |
|
| 484 |
+static inline bool |
|
| 485 |
+link_socket_actual_match(const struct link_socket_actual *a1, const struct link_socket_actual *a2) |
|
| 486 |
+{
|
|
| 487 |
+ return addr_port_match(&a1->dest, &a2->dest); |
|
| 488 |
+} |
|
| 489 |
+ |
|
| 490 |
+#endif |