OpenVPN
socket_util.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2025 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#include "socket_util.h"
30#include "crypto.h"
31#include "manage.h"
32
33/*
34 * Format IP addresses in ascii
35 */
36
37const char *
38print_sockaddr_ex(const struct sockaddr *sa, const char *separator, const unsigned int flags,
39 struct gc_arena *gc)
40{
41 struct buffer out = alloc_buf_gc(128, gc);
42 bool addr_is_defined = false;
43 char hostaddr[NI_MAXHOST] = "";
44 char servname[NI_MAXSERV] = "";
45 int status;
46
47 socklen_t salen = 0;
48 switch (sa->sa_family)
49 {
50 case AF_INET:
51 if (!(flags & PS_DONT_SHOW_FAMILY))
52 {
53 buf_puts(&out, "[AF_INET]");
54 }
55 salen = sizeof(struct sockaddr_in);
56 addr_is_defined = ((struct sockaddr_in *)sa)->sin_addr.s_addr != 0;
57 break;
58
59 case AF_INET6:
60 if (!(flags & PS_DONT_SHOW_FAMILY))
61 {
62 buf_puts(&out, "[AF_INET6]");
63 }
64 salen = sizeof(struct sockaddr_in6);
65 addr_is_defined = !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)sa)->sin6_addr);
66 break;
67
68 case AF_UNSPEC:
69 if (!(flags & PS_DONT_SHOW_FAMILY))
70 {
71 return "[AF_UNSPEC]";
72 }
73 else
74 {
75 return "";
76 }
77
78 default:
79 ASSERT(0);
80 }
81
82 status = getnameinfo(sa, salen, hostaddr, sizeof(hostaddr), servname, sizeof(servname),
83 NI_NUMERICHOST | NI_NUMERICSERV);
84
85 if (status != 0)
86 {
87 buf_printf(&out, "[nameinfo() err: %s]", gai_strerror(status));
88 return BSTR(&out);
89 }
90
91 if (!(flags & PS_DONT_SHOW_ADDR))
92 {
93 if (addr_is_defined)
94 {
95 buf_puts(&out, hostaddr);
96 }
97 else
98 {
99 buf_puts(&out, "[undef]");
100 }
101 }
102
103 if ((flags & PS_SHOW_PORT) || (flags & PS_SHOW_PORT_IF_DEFINED))
104 {
105 if (separator)
106 {
107 buf_puts(&out, separator);
108 }
109
110 buf_puts(&out, servname);
111 }
112
113 return BSTR(&out);
114}
115
116const char *
121
122#ifndef IF_NAMESIZE
123#define IF_NAMESIZE 16
124#endif
125
126const char *
127print_link_socket_actual_ex(const struct link_socket_actual *act, const char *separator,
128 const unsigned int flags, struct gc_arena *gc)
129{
130 if (act)
131 {
132 struct buffer out = alloc_buf_gc(128, gc);
133 buf_printf(&out, "%s", print_sockaddr_ex(&act->dest.addr.sa, separator, flags, gc));
134#if ENABLE_IP_PKTINFO
135 char ifname[IF_NAMESIZE] = "[undef]";
136
137 if ((flags & PS_SHOW_PKTINFO) && addr_defined_ipi(act))
138 {
139 switch (act->dest.addr.sa.sa_family)
140 {
141 case AF_INET:
142 {
143 struct openvpn_sockaddr sa;
144 CLEAR(sa);
145 sa.addr.in4.sin_family = AF_INET;
146#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST)
147 sa.addr.in4.sin_addr = act->pi.in4.ipi_spec_dst;
148 if_indextoname(act->pi.in4.ipi_ifindex, ifname);
149#elif defined(IP_RECVDSTADDR)
150 sa.addr.in4.sin_addr = act->pi.in4;
151 ifname[0] = 0;
152#else /* if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) */
153#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h)
154#endif
155 buf_printf(&out, " (via %s%%%s)",
156 print_sockaddr_ex(&sa.addr.sa, separator, 0, gc), ifname);
157 }
158 break;
159
160 case AF_INET6:
161 {
162 struct sockaddr_in6 sin6;
163 char buf[INET6_ADDRSTRLEN] = "[undef]";
164 CLEAR(sin6);
165 sin6.sin6_family = AF_INET6;
166 sin6.sin6_addr = act->pi.in6.ipi6_addr;
167 if_indextoname(act->pi.in6.ipi6_ifindex, ifname);
168 if (getnameinfo((struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), buf,
169 sizeof(buf), NULL, 0, NI_NUMERICHOST)
170 == 0)
171 {
172 buf_printf(&out, " (via %s%%%s)", buf, ifname);
173 }
174 else
175 {
176 buf_printf(&out, " (via [getnameinfo() err]%%%s)", ifname);
177 }
178 }
179 break;
180 }
181 }
182#endif /* if ENABLE_IP_PKTINFO */
183 return BSTR(&out);
184 }
185 else
186 {
187 return "[NULL]";
188 }
189}
190
191/*
192 * Convert an in_addr_t in host byte order
193 * to an ascii dotted quad.
194 */
195const char *
196print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
197{
198 struct in_addr ia;
199 char *out = gc_malloc(INET_ADDRSTRLEN, true, gc);
200
201 if (addr || !(flags & IA_EMPTY_IF_UNDEF))
202 {
203 CLEAR(ia);
204 ia.s_addr = (flags & IA_NET_ORDER) ? addr : htonl(addr);
205
206 inet_ntop(AF_INET, &ia, out, INET_ADDRSTRLEN);
207 }
208 return out;
209}
210
211/*
212 * Convert an in6_addr in host byte order
213 * to an ascii representation of an IPv6 address
214 */
215const char *
216print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
217{
218 char *out = gc_malloc(INET6_ADDRSTRLEN, true, gc);
219
220 if (memcmp(&a6, &in6addr_any, sizeof(a6)) != 0 || !(flags & IA_EMPTY_IF_UNDEF))
221 {
222 inet_ntop(AF_INET6, &a6, out, INET6_ADDRSTRLEN);
223 }
224 return out;
225}
226
227/*
228 * Convert an in_port_t in host byte order to a string
229 */
230const char *
231print_in_port_t(in_port_t port, struct gc_arena *gc)
232{
233 struct buffer buffer = alloc_buf_gc(8, gc);
234 buf_printf(&buffer, "%hu", port);
235 return BSTR(&buffer);
236}
237
238/* add some offset to an ipv6 address
239 * (add in steps of 8 bits, taking overflow into next round)
240 */
241struct in6_addr
242add_in6_addr(struct in6_addr base, uint32_t add)
243{
244 for (int i = 15; i >= 0 && add > 0; i--)
245 {
246 register uint32_t carry;
247 register uint32_t h;
248
249 h = base.s6_addr[i];
250 base.s6_addr[i] = (h + add) & UINT8_MAX;
251
252 /* using explicit carry for the 8-bit additions will catch
253 * 8-bit and(!) 32-bit overruns nicely
254 */
255 carry = ((h & 0xff) + (add & 0xff)) >> 8;
256 add = (add >> 8) + carry;
257 }
258 return base;
259}
260
261/* set environmental variables for ip/port in *addr */
262void
263setenv_sockaddr(struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr,
264 const unsigned int flags)
265{
266 char name_buf[256];
267
268 char buf[INET6_ADDRSTRLEN];
269 switch (addr->addr.sa.sa_family)
270 {
271 case AF_INET:
272 if (flags & SA_IP_PORT)
273 {
274 snprintf(name_buf, sizeof(name_buf), "%s_ip", name_prefix);
275 }
276 else
277 {
278 snprintf(name_buf, sizeof(name_buf), "%s", name_prefix);
279 }
280
281 inet_ntop(AF_INET, &addr->addr.in4.sin_addr, buf, sizeof(buf));
282 setenv_str(es, name_buf, buf);
283
284 if ((flags & SA_IP_PORT) && addr->addr.in4.sin_port)
285 {
286 snprintf(name_buf, sizeof(name_buf), "%s_port", name_prefix);
287 setenv_int(es, name_buf, ntohs(addr->addr.in4.sin_port));
288 }
289 break;
290
291 case AF_INET6:
292 if (IN6_IS_ADDR_V4MAPPED(&addr->addr.in6.sin6_addr))
293 {
294 struct in_addr ia;
295 memcpy(&ia.s_addr, &addr->addr.in6.sin6_addr.s6_addr[12], sizeof(ia.s_addr));
296 snprintf(name_buf, sizeof(name_buf), "%s_ip", name_prefix);
297 inet_ntop(AF_INET, &ia, buf, sizeof(buf));
298 }
299 else
300 {
301 snprintf(name_buf, sizeof(name_buf), "%s_ip6", name_prefix);
302 inet_ntop(AF_INET6, &addr->addr.in6.sin6_addr, buf, sizeof(buf));
303 }
304 setenv_str(es, name_buf, buf);
305
306 if ((flags & SA_IP_PORT) && addr->addr.in6.sin6_port)
307 {
308 snprintf(name_buf, sizeof(name_buf), "%s_port", name_prefix);
309 setenv_int(es, name_buf, ntohs(addr->addr.in6.sin6_port));
310 }
311 break;
312 }
313}
314
315void
316setenv_in_addr_t(struct env_set *es, const char *name_prefix, in_addr_t addr,
317 const unsigned int flags)
318{
319 if (addr || !(flags & SA_SET_IF_NONZERO))
320 {
321 struct openvpn_sockaddr si;
322 CLEAR(si);
323 si.addr.in4.sin_family = AF_INET;
324 si.addr.in4.sin_addr.s_addr = htonl(addr);
325 setenv_sockaddr(es, name_prefix, &si, flags);
326 }
327}
328
329void
330setenv_in6_addr(struct env_set *es, const char *name_prefix, const struct in6_addr *addr,
331 const unsigned int flags)
332{
333 if (!IN6_IS_ADDR_UNSPECIFIED(addr) || !(flags & SA_SET_IF_NONZERO))
334 {
335 struct openvpn_sockaddr si;
336 CLEAR(si);
337 si.addr.in6.sin6_family = AF_INET6;
338 si.addr.in6.sin6_addr = *addr;
339 setenv_sockaddr(es, name_prefix, &si, flags);
340 }
341}
342
343void
344setenv_link_socket_actual(struct env_set *es, const char *name_prefix,
345 const struct link_socket_actual *act, const unsigned int flags)
346{
347 setenv_sockaddr(es, name_prefix, &act->dest, flags);
348}
349
350/*
351 * Convert protocol names between index and ascii form.
352 */
353
355{
356 const char *short_form;
357 const char *display_form;
359 int proto;
360};
361
362/* Indexed by PROTO_x */
363static const struct proto_names proto_names[] = {
364 { "proto-uninitialized", "proto-NONE", AF_UNSPEC, PROTO_NONE },
365 /* try IPv4 and IPv6 (client), bind dual-stack (server) */
366 { "udp", "UDP", AF_UNSPEC, PROTO_UDP },
367 { "tcp-server", "TCP_SERVER", AF_UNSPEC, PROTO_TCP_SERVER },
368 { "tcp-client", "TCP_CLIENT", AF_UNSPEC, PROTO_TCP_CLIENT },
369 { "tcp", "TCP", AF_UNSPEC, PROTO_TCP },
370 /* force IPv4 */
371 { "udp4", "UDPv4", AF_INET, PROTO_UDP },
372 { "tcp4-server", "TCPv4_SERVER", AF_INET, PROTO_TCP_SERVER },
373 { "tcp4-client", "TCPv4_CLIENT", AF_INET, PROTO_TCP_CLIENT },
374 { "tcp4", "TCPv4", AF_INET, PROTO_TCP },
375 /* force IPv6 */
376 { "udp6", "UDPv6", AF_INET6, PROTO_UDP },
377 { "tcp6-server", "TCPv6_SERVER", AF_INET6, PROTO_TCP_SERVER },
378 { "tcp6-client", "TCPv6_CLIENT", AF_INET6, PROTO_TCP_CLIENT },
379 { "tcp6", "TCPv6", AF_INET6, PROTO_TCP },
380};
381
382int
383ascii2proto(const char *proto_name)
384{
385 for (size_t i = 0; i < SIZE(proto_names); ++i)
386 {
387 if (!strcmp(proto_name, proto_names[i].short_form))
388 {
389 return proto_names[i].proto;
390 }
391 }
392 return -1;
393}
394
396ascii2af(const char *proto_name)
397{
398 for (size_t i = 0; i < SIZE(proto_names); ++i)
399 {
400 if (!strcmp(proto_name, proto_names[i].short_form))
401 {
402 return proto_names[i].proto_af;
403 }
404 }
405 return 0;
406}
407
408const char *
410{
411 for (size_t i = 0; i < SIZE(proto_names); ++i)
412 {
413 if (proto_names[i].proto_af == af && proto_names[i].proto == proto)
414 {
415 if (display_form)
416 {
417 return proto_names[i].display_form;
418 }
419 else
420 {
421 return proto_names[i].short_form;
422 }
423 }
424 }
425
426 return "[unknown protocol]";
427}
428
429const char *
431{
432 struct buffer out = alloc_buf_gc(256, gc);
433
434 for (size_t i = 0; i < SIZE(proto_names); ++i)
435 {
436 if (i)
437 {
438 buf_printf(&out, " ");
439 }
440 buf_printf(&out, "[%s]", proto_names[i].short_form);
441 }
442 return BSTR(&out);
443}
444
445const char *
447{
448 switch (af)
449 {
450 case AF_INET:
451 return "AF_INET";
452
453 case AF_INET6:
454 return "AF_INET6";
455 }
456 return "AF_UNSPEC";
457}
458
459/*
460 * Given a local proto, return local proto
461 * if !remote, or compatible remote proto
462 * if remote.
463 *
464 * This is used for options compatibility
465 * checking.
466 *
467 * IPv6 and IPv4 protocols are comptabile but OpenVPN
468 * has always sent UDPv4, TCPv4 over the wire. Keep these
469 * strings for backward compatibility
470 */
471const char *
472proto_remote(int proto, bool remote)
473{
474 ASSERT(proto >= 0 && proto < PROTO_N);
475 if (proto == PROTO_UDP)
476 {
477 return "UDPv4";
478 }
479
480 if ((remote && proto == PROTO_TCP_CLIENT) || (!remote && proto == PROTO_TCP_SERVER))
481 {
482 return "TCPv4_SERVER";
483 }
484 if ((remote && proto == PROTO_TCP_SERVER) || (!remote && proto == PROTO_TCP_CLIENT))
485 {
486 return "TCPv4_CLIENT";
487 }
488
489 ASSERT(0);
490 return ""; /* Make the compiler happy */
491}
492
497static const char *
499{
500 switch (af)
501 {
502 case AF_INET:
503 return "[AF_INET]";
504
505 case AF_INET6:
506 return "[AF_INET6]";
507 }
508 return "";
509}
510
511/*
512 * Prepend a random string to hostname to prevent DNS caching.
513 * For example, foo.bar.gov would be modified to <random-chars>.foo.bar.gov.
514 * Of course, this requires explicit support in the DNS server (wildcard).
515 */
516static const char *
517hostname_randomize(const char *hostname, struct gc_arena *gc)
518{
519#define n_rnd_bytes 6
520
522 const char *rnd_str;
523 struct buffer hname = alloc_buf_gc(strlen(hostname) + sizeof(rnd_bytes) * 2 + 4, gc);
524
526 rnd_str = format_hex_ex(rnd_bytes, sizeof(rnd_bytes), 40, 0, NULL, gc);
527 buf_printf(&hname, "%s.%s", rnd_str, hostname);
528 return BSTR(&hname);
529#undef n_rnd_bytes
530}
531
532/*
533 * Translate IPv4/IPv6 addr or hostname into struct addrinfo
534 * If resolve error, try again for resolve_retry_seconds seconds.
535 */
536int
537openvpn_getaddrinfo(unsigned int flags, const char *hostname, const char *servname,
538 int resolve_retry_seconds, struct signal_info *sig_info, int ai_family,
539 struct addrinfo **res)
540{
541 struct addrinfo hints;
542 int status;
543 struct signal_info sigrec = { 0 };
544 int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS;
545 struct gc_arena gc = gc_new();
546 const char *print_hostname;
547 const char *print_servname;
548
549 ASSERT(res);
550
551 ASSERT(hostname || servname);
552 ASSERT(!(flags & GETADDR_HOST_ORDER));
553
554 if (servname)
555 {
556 print_servname = servname;
557 }
558 else
559 {
560 print_servname = "";
561 }
562
563 if (flags & GETADDR_MSG_VIRT_OUT)
564 {
565 msglevel |= M_MSG_VIRT_OUT;
566 }
567
568 if ((flags & (GETADDR_FATAL_ON_SIGNAL | GETADDR_WARN_ON_SIGNAL)) && !sig_info)
569 {
570 sig_info = &sigrec;
571 }
572
573 /* try numeric ip addr first */
574 CLEAR(hints);
575 hints.ai_flags = AI_NUMERICHOST;
576
577 if (flags & GETADDR_PASSIVE)
578 {
579 hints.ai_flags |= AI_PASSIVE;
580 }
581
582 if (flags & GETADDR_DATAGRAM)
583 {
584 hints.ai_socktype = SOCK_DGRAM;
585 }
586 else
587 {
588 hints.ai_socktype = SOCK_STREAM;
589 }
590
591 /* if hostname is not set, we want to bind to 'ANY', with
592 * the correct address family - v4-only or v6/v6-dual-stack */
593 if (!hostname)
594 {
595 hints.ai_family = ai_family;
596 }
597
598 status = getaddrinfo(hostname, servname, &hints, res);
599
600 if (status != 0) /* parse as numeric address failed? */
601 {
602 const int fail_wait_interval = 5; /* seconds */
603 /* Add +4 to cause integer division rounding up (1 + 4) = 5, (0+4)/5=0 */
604 int resolve_retries =
605 (flags & GETADDR_TRY_ONCE) ? 1 : ((resolve_retry_seconds + 4) / fail_wait_interval);
606 const char *fmt;
607 int level = 0;
608
609 /* this is not a numeric IP, therefore force resolution using the
610 * provided ai_family */
611 hints.ai_family = ai_family;
612
613 if (hostname && (flags & GETADDR_RANDOMIZE))
614 {
615 hostname = hostname_randomize(hostname, &gc);
616 }
617
618 if (hostname)
619 {
620 print_hostname = hostname;
621 }
622 else
623 {
624 print_hostname = "undefined";
625 }
626
627 fmt = "RESOLVE: Cannot resolve host address: %s:%s%s (%s)";
628 if ((flags & GETADDR_MENTION_RESOLVE_RETRY) && !resolve_retry_seconds)
629 {
630 fmt = "RESOLVE: Cannot resolve host address: %s:%s%s (%s)"
631 "(I would have retried this name query if you had "
632 "specified the --resolv-retry option.)";
633 }
634
635 if (!(flags & GETADDR_RESOLVE) || status == EAI_FAIL)
636 {
637 msg(msglevel, "RESOLVE: Cannot parse IP address: %s:%s (%s)", print_hostname,
638 print_servname, gai_strerror(status));
639 goto done;
640 }
641
642#ifdef ENABLE_MANAGEMENT
644 {
645 if (management)
646 {
648 NULL);
649 }
650 }
651#endif
652
653 /*
654 * Resolve hostname
655 */
656 while (true)
657 {
658#ifndef _WIN32
659 /* force resolv.conf reload */
660 res_init();
661#endif
662 /* try hostname lookup */
663 hints.ai_flags &= ~AI_NUMERICHOST;
664 dmsg(D_SOCKET_DEBUG, "GETADDRINFO flags=0x%04x ai_family=%d ai_socktype=%d", flags,
665 hints.ai_family, hints.ai_socktype);
666 status = getaddrinfo(hostname, servname, &hints, res);
667
668 if (sig_info)
669 {
670 get_signal(&sig_info->signal_received);
671 if (sig_info->signal_received) /* were we interrupted by a signal? */
672 {
673 /* why are we overwriting SIGUSR1 ? */
674 if (signal_reset(sig_info, SIGUSR1) == SIGUSR1) /* ignore SIGUSR1 */
675 {
676 msg(level, "RESOLVE: Ignored SIGUSR1 signal received during "
677 "DNS resolution attempt");
678 }
679 else
680 {
681 /* turn success into failure (interrupted syscall) */
682 if (0 == status)
683 {
684 ASSERT(res);
685 freeaddrinfo(*res);
686 *res = NULL;
687 status = EAI_AGAIN; /* = temporary failure */
688 errno = EINTR;
689 }
690 goto done;
691 }
692 }
693 }
694
695 /* success? */
696 if (0 == status)
697 {
698 break;
699 }
700
701 /* resolve lookup failed, should we
702 * continue or fail? */
703 level = msglevel;
704 if (resolve_retries > 0)
705 {
706 level = D_RESOLVE_ERRORS;
707 }
708
709 msg(level, fmt, print_hostname, print_servname, getaddrinfo_addr_family_name(ai_family),
710 gai_strerror(status));
711
712 if (--resolve_retries <= 0)
713 {
714 goto done;
715 }
716
717 management_sleep(fail_wait_interval);
718 }
719
720 ASSERT(res);
721
722 /* hostname resolve succeeded */
723
724 /*
725 * Do not choose an IP Addresse by random or change the order *
726 * of IP addresses, doing so will break RFC 3484 address selection *
727 */
728 }
729 else
730 {
731 /* IP address parse succeeded */
732 if (flags & GETADDR_RANDOMIZE)
733 {
734 msg(M_WARN, "WARNING: ignoring --remote-random-hostname because the "
735 "hostname is an IP address");
736 }
737 }
738
739done:
740 if (sig_info && sig_info->signal_received)
741 {
742 int level = 0;
743 if (flags & GETADDR_FATAL_ON_SIGNAL)
744 {
745 level = M_FATAL;
746 }
747 else if (flags & GETADDR_WARN_ON_SIGNAL)
748 {
749 level = M_WARN;
750 }
751 msg(level, "RESOLVE: signal received during DNS resolution attempt");
752 }
753
754 gc_free(&gc);
755 return status;
756}
757
758/*
759 * We do our own inet_aton because the glibc function
760 * isn't very good about error checking.
761 */
762int
763openvpn_inet_aton(const char *dotted_quad, struct in_addr *addr)
764{
765 unsigned int a, b, c, d;
766
767 CLEAR(*addr);
768 if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) == 4)
769 {
770 if (a < 256 && b < 256 && c < 256 && d < 256)
771 {
772 addr->s_addr = htonl(a << 24 | b << 16 | c << 8 | d);
773 return OIA_IP; /* good dotted quad */
774 }
775 }
776 if (string_class(dotted_quad, CC_DIGIT | CC_DOT, 0))
777 {
778 return OIA_ERROR; /* probably a badly formatted dotted quad */
779 }
780 else
781 {
782 return OIA_HOSTNAME; /* probably a hostname */
783 }
784}
785
786bool
787ip_addr_dotted_quad_safe(const char *dotted_quad)
788{
789 /* verify non-NULL */
790 if (!dotted_quad)
791 {
792 return false;
793 }
794
795 /* verify length is within limits */
796 if (strlen(dotted_quad) > 15)
797 {
798 return false;
799 }
800
801 /* verify that all chars are either numeric or '.' and that no numeric
802 * substring is greater than 3 chars */
803 {
804 int nnum = 0;
805 const char *p = dotted_quad;
806 int c;
807
808 while ((c = *p++))
809 {
810 if (c >= '0' && c <= '9')
811 {
812 ++nnum;
813 if (nnum > 3)
814 {
815 return false;
816 }
817 }
818 else if (c == '.')
819 {
820 nnum = 0;
821 }
822 else
823 {
824 return false;
825 }
826 }
827 }
828
829 /* verify that string will convert to IP address */
830 {
831 struct in_addr a;
832 return openvpn_inet_aton(dotted_quad, &a) == OIA_IP;
833 }
834}
835
836bool
837ipv6_addr_safe(const char *ipv6_text_addr)
838{
839 /* verify non-NULL */
840 if (!ipv6_text_addr)
841 {
842 return false;
843 }
844
845 /* verify length is within limits */
846 if (strlen(ipv6_text_addr) > INET6_ADDRSTRLEN)
847 {
848 return false;
849 }
850
851 /* verify that string will convert to IPv6 address */
852 {
853 struct in6_addr a6;
854 return inet_pton(AF_INET6, ipv6_text_addr, &a6) == 1;
855 }
856}
857
858static bool
859dns_addr_safe(const char *addr)
860{
861 if (addr)
862 {
863 const size_t len = strlen(addr);
864 return len > 0 && len <= 255 && string_class(addr, CC_ALNUM | CC_DASH | CC_DOT, 0);
865 }
866 else
867 {
868 return false;
869 }
870}
871
872bool
873ip_or_dns_addr_safe(const char *addr, const bool allow_fqdn)
874{
875 if (ip_addr_dotted_quad_safe(addr))
876 {
877 return true;
878 }
879 else if (allow_fqdn)
880 {
881 return dns_addr_safe(addr);
882 }
883 else
884 {
885 return false;
886 }
887}
888
889bool
890mac_addr_safe(const char *mac_addr)
891{
892 /* verify non-NULL */
893 if (!mac_addr)
894 {
895 return false;
896 }
897
898 /* verify length is within limits */
899 if (strlen(mac_addr) > 17)
900 {
901 return false;
902 }
903
904 /* verify that all chars are either alphanumeric or ':' and that no
905 * alphanumeric substring is greater than 2 chars */
906 {
907 int nnum = 0;
908 const char *p = mac_addr;
909 int c;
910
911 while ((c = *p++))
912 {
913 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
914 {
915 ++nnum;
916 if (nnum > 2)
917 {
918 return false;
919 }
920 }
921 else if (c == ':')
922 {
923 nnum = 0;
924 }
925 else
926 {
927 return false;
928 }
929 }
930 }
931
932 /* error-checking is left to script invoked in lladdr.c */
933 return true;
934}
bool buf_printf(struct buffer *buf, const char *format,...)
Definition buffer.c:241
bool buf_puts(struct buffer *buf, const char *str)
Definition buffer.c:268
bool string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
Definition buffer.c:1022
char * format_hex_ex(const uint8_t *data, int size, int maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Definition buffer.c:483
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition buffer.c:336
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition buffer.c:89
#define CC_DASH
dash
Definition buffer.h:886
#define BSTR(buf)
Definition buffer.h:128
#define CC_DIGIT
digit isdigit()
Definition buffer.h:874
#define CC_DOT
dot
Definition buffer.h:887
static void gc_free(struct gc_arena *a)
Definition buffer.h:1015
#define CC_ALNUM
alphanumeric isalnum()
Definition buffer.h:870
static struct gc_arena gc_new(void)
Definition buffer.h:1007
void prng_bytes(uint8_t *output, int len)
Definition crypto.c:1709
Data Channel Cryptography Module.
void setenv_int(struct env_set *es, const char *name, int value)
Definition env_set.c:291
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition env_set.c:307
#define D_SOCKET_DEBUG
Definition errlevel.h:139
#define D_RESOLVE_ERRORS
Definition errlevel.h:59
static SERVICE_STATUS status
Definition interactive.c:51
void management_set_state(struct management *man, const int state, const char *detail, const in_addr_t *tun_local_ip, const struct in6_addr *tun_local_ip6, const struct openvpn_sockaddr *local, const struct openvpn_sockaddr *remote)
Definition manage.c:2778
void management_sleep(const int n)
A sleep function that services the management layer for n seconds rather than doing nothing.
Definition manage.c:4131
#define OPENVPN_STATE_RESOLVE
Definition manage.h:460
#define CLEAR(x)
Definition basic.h:32
#define SIZE(x)
Definition basic.h:29
#define M_FATAL
Definition error.h:88
#define dmsg(flags,...)
Definition error.h:170
#define msg(flags,...)
Definition error.h:150
#define ASSERT(x)
Definition error.h:217
#define M_WARN
Definition error.h:90
#define M_MSG_VIRT_OUT
Definition error.h:98
int signal_reset(struct signal_info *si, int signum)
Clear the signal if its current value equals signum.
Definition sig.c:262
static void get_signal(volatile int *sig)
Copy the global signal_received (if non-zero) to the passed-in argument sig.
Definition sig.h:109
static bool dns_addr_safe(const char *addr)
const char * proto2ascii(int proto, sa_family_t af, bool display_form)
int openvpn_getaddrinfo(unsigned int flags, const char *hostname, const char *servname, int resolve_retry_seconds, struct signal_info *sig_info, int ai_family, struct addrinfo **res)
#define n_rnd_bytes
bool mac_addr_safe(const char *mac_addr)
void setenv_in_addr_t(struct env_set *es, const char *name_prefix, in_addr_t addr, const unsigned int flags)
const char * print_sockaddr_ex(const struct sockaddr *sa, const char *separator, const unsigned int flags, struct gc_arena *gc)
Definition socket_util.c:38
const char * print_in_port_t(in_port_t port, struct gc_arena *gc)
static const char * hostname_randomize(const char *hostname, struct gc_arena *gc)
const char * proto2ascii_all(struct gc_arena *gc)
void setenv_link_socket_actual(struct env_set *es, const char *name_prefix, const struct link_socket_actual *act, const unsigned int flags)
void setenv_in6_addr(struct env_set *es, const char *name_prefix, const struct in6_addr *addr, const unsigned int flags)
const char * print_link_socket_actual(const struct link_socket_actual *act, struct gc_arena *gc)
void setenv_sockaddr(struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr, const unsigned int flags)
const char * print_link_socket_actual_ex(const struct link_socket_actual *act, const char *separator, const unsigned int flags, struct gc_arena *gc)
struct in6_addr add_in6_addr(struct in6_addr base, uint32_t add)
sa_family_t ascii2af(const char *proto_name)
int openvpn_inet_aton(const char *dotted_quad, struct in_addr *addr)
const char * proto_remote(int proto, bool remote)
bool ipv6_addr_safe(const char *ipv6_text_addr)
const char * print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
bool ip_or_dns_addr_safe(const char *addr, const bool allow_fqdn)
int ascii2proto(const char *proto_name)
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
static const char * getaddrinfo_addr_family_name(int af)
Small helper function for openvpn_getaddrinfo to print the address family when resolving fails.
#define IF_NAMESIZE
const char * addr_family_name(int af)
bool ip_addr_dotted_quad_safe(const char *dotted_quad)
#define IA_EMPTY_IF_UNDEF
Definition socket_util.h:89
#define OIA_HOSTNAME
#define GETADDR_MSG_VIRT_OUT
#define GETADDR_TRY_ONCE
#define SA_IP_PORT
Definition socket_util.h:99
#define GETADDR_PASSIVE
#define GETADDR_FATAL
#define GETADDR_UPDATE_MANAGEMENT_STATE
#define PS_SHOW_PORT
Definition socket_util.h:31
@ PROTO_NONE
@ PROTO_UDP
@ PROTO_TCP
@ PROTO_TCP_CLIENT
@ PROTO_N
@ PROTO_TCP_SERVER
#define PS_DONT_SHOW_ADDR
Definition socket_util.h:33
#define GETADDR_HOST_ORDER
#define OIA_ERROR
#define PS_SHOW_PORT_IF_DEFINED
Definition socket_util.h:30
#define GETADDR_RANDOMIZE
#define GETADDR_DATAGRAM
#define GETADDR_FATAL_ON_SIGNAL
static bool addr_defined_ipi(const struct link_socket_actual *lsa)
#define OIA_IP
#define GETADDR_RESOLVE
#define PS_DONT_SHOW_FAMILY
Definition socket_util.h:34
#define IA_NET_ORDER
Definition socket_util.h:90
#define SA_SET_IF_NONZERO
#define GETADDR_MENTION_RESOLVE_RETRY
#define GETADDR_WARN_ON_SIGNAL
#define PS_SHOW_PKTINFO
Definition socket_util.h:32
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:65
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
union openvpn_sockaddr::@27 addr
struct sockaddr sa
Definition socket_util.h:42
struct sockaddr_in in4
Definition socket_util.h:43
struct sockaddr_in6 in6
Definition socket_util.h:44
const char * short_form
const char * display_form
sa_family_t proto_af
volatile int signal_received
Definition sig.h:42
unsigned short sa_family_t
Definition syshead.h:396
struct env_set * es
char ** res
struct gc_arena gc
Definition test_ssl.c:154