Browse code

socket: Create socket_util with non-socket functions

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>

Frank Lichtenheld authored on 2025/09/01 00:59:32
Showing 20 changed files
... ...
@@ -555,6 +555,8 @@ set(SOURCE_FILES
555 555
     src/openvpn/sig.h
556 556
     src/openvpn/socket.c
557 557
     src/openvpn/socket.h
558
+    src/openvpn/socket_util.c
559
+    src/openvpn/socket_util.h
558 560
     src/openvpn/socks.c
559 561
     src/openvpn/socks.h
560 562
     src/openvpn/ssl.c
... ...
@@ -128,6 +128,7 @@ openvpn_SOURCES = \
128 128
 	shaper.c shaper.h \
129 129
 	sig.c sig.h \
130 130
 	socket.c socket.h \
131
+	socket_util.c socket_util.h \
131 132
 	socks.c socks.h \
132 133
 	ssl.c ssl.h  ssl_backend.h \
133 134
 	ssl_openssl.c ssl_openssl.h \
... ...
@@ -28,7 +28,7 @@
28 28
 
29 29
 #include "clinat.h"
30 30
 #include "proto.h"
31
-#include "socket.h"
31
+#include "socket_util.h"
32 32
 #include "memdbg.h"
33 33
 
34 34
 static bool
... ...
@@ -27,7 +27,7 @@
27 27
 #include "syshead.h"
28 28
 
29 29
 #include "dhcp.h"
30
-#include "socket.h"
30
+#include "socket_util.h"
31 31
 #include "error.h"
32 32
 
33 33
 #include "memdbg.h"
... ...
@@ -27,7 +27,7 @@
27 27
 #include "syshead.h"
28 28
 
29 29
 #include "dns.h"
30
-#include "socket.h"
30
+#include "socket_util.h"
31 31
 #include "options.h"
32 32
 #include "run_command.h"
33 33
 
... ...
@@ -48,7 +48,7 @@
48 48
 
49 49
 #include "misc.h"
50 50
 #include "event.h"
51
-#include "socket.h"
51
+#include "socket_util.h"
52 52
 #include "mroute.h"
53 53
 
54 54
 #define MANAGEMENT_VERSION                  5
... ...
@@ -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
  */
... ...
@@ -30,7 +30,7 @@
30 30
 #include "mroute.h"
31 31
 #include "proto.h"
32 32
 #include "error.h"
33
-#include "socket.h"
33
+#include "socket_util.h"
34 34
 
35 35
 #include "memdbg.h"
36 36
 
... ...
@@ -26,6 +26,7 @@
26 26
 #include "proto.h"
27 27
 #include "error.h"
28 28
 #include "mtu.h"
29
+#include "socket.h"
29 30
 #include "ssl_common.h"
30 31
 
31 32
 void mss_fixup_ipv4(struct buffer *buf, uint16_t maxmss);
... ...
@@ -30,7 +30,7 @@
30 30
 #include "misc.h"
31 31
 #include "openvpn.h"
32 32
 #include "run_command.h"
33
-#include "socket.h"
33
+#include "socket_util.h"
34 34
 
35 35
 #include <stdbool.h>
36 36
 #include <netinet/in.h>
... ...
@@ -45,7 +45,7 @@
45 45
 #include "ssl_ncp.h"
46 46
 #include "options.h"
47 47
 #include "misc.h"
48
-#include "socket.h"
48
+#include "socket_util.h"
49 49
 #include "packet_id.h"
50 50
 #include "pkcs11.h"
51 51
 #include "win32.h"
... ...
@@ -33,7 +33,7 @@
33 33
 #include "mtu.h"
34 34
 #include "route.h"
35 35
 #include "tun.h"
36
-#include "socket.h"
36
+#include "socket_util.h"
37 37
 #include "plugin.h"
38 38
 #include "manage.h"
39 39
 #include "proxy.h"
... ...
@@ -29,7 +29,7 @@
29 29
 #include "pool.h"
30 30
 #include "buffer.h"
31 31
 #include "error.h"
32
-#include "socket.h"
32
+#include "socket_util.h"
33 33
 #include "otime.h"
34 34
 
35 35
 #include "memdbg.h"
... ...
@@ -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
... ...
@@ -30,7 +30,7 @@
30 30
 #define SSL_COMMON_H_
31 31
 
32 32
 #include "session_id.h"
33
-#include "socket.h"
33
+#include "socket_util.h"
34 34
 #include "packet_id.h"
35 35
 #include "crypto.h"
36 36
 #include "options.h"
... ...
@@ -39,7 +39,7 @@
39 39
 #include "fdmisc.h"
40 40
 #include "common.h"
41 41
 #include "run_command.h"
42
-#include "socket.h"
42
+#include "socket_util.h"
43 43
 #include "manage.h"
44 44
 #include "route.h"
45 45
 #include "win32.h"