OpenVPN
dns.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single 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) 2022-2026 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 "dns.h"
30#include "socket_util.h"
31#include "options.h"
32#include "run_command.h"
33#include "domain_helper.h"
34
35#ifdef _WIN32
36#include "win32.h"
37#include "openvpn-msg.h"
38#endif
39
47static bool
48dns_server_port_parse(in_port_t *port, const char *port_str)
49{
50 char *endptr;
51 errno = 0;
52 unsigned long tmp = strtoul(port_str, &endptr, 10);
53 if (errno || *endptr != '\0' || tmp == 0 || tmp > UINT16_MAX)
54 {
55 return false;
56 }
57 *port = (in_port_t)tmp;
58 return true;
59}
60
61bool
62dns_server_addr_parse(struct dns_server *server, const char *addr)
63{
64 if (!addr)
65 {
66 return false;
67 }
68
69 char addrcopy[INET6_ADDRSTRLEN] = { 0 };
70 size_t copylen = 0;
71 in_port_t port = 0;
72 sa_family_t af;
73
74 const char *first_colon = strchr(addr, ':');
75 const char *last_colon = strrchr(addr, ':');
76
77 if (!first_colon || first_colon == last_colon)
78 {
79 /* IPv4 address with optional port, e.g. 1.2.3.4 or 1.2.3.4:853 */
80 if (last_colon)
81 {
82 if (last_colon == addr || !dns_server_port_parse(&port, last_colon + 1))
83 {
84 return false;
85 }
86 copylen = first_colon - addr;
87 }
88 af = AF_INET;
89 }
90 else
91 {
92 /* IPv6 address with optional port, e.g. ab::cd or [ab::cd]:853 */
93 if (addr[0] == '[')
94 {
95 addr += 1;
96 const char *bracket = last_colon - 1;
97 if (*bracket != ']' || bracket == addr || !dns_server_port_parse(&port, last_colon + 1))
98 {
99 return false;
100 }
101 copylen = bracket - addr;
102 }
103 af = AF_INET6;
104 }
105
106 /* Copy the address part into a temporary buffer and use that */
107 if (copylen)
108 {
109 if (copylen >= sizeof(addrcopy))
110 {
111 return false;
112 }
113 strncpy(addrcopy, addr, copylen);
114 addr = addrcopy;
115 }
116
117 struct addrinfo *ai = NULL;
118 if (openvpn_getaddrinfo(0, addr, NULL, 0, NULL, af, &ai) != 0)
119 {
120 return false;
121 }
122
123 if (server->addr_count >= SIZE(server->addr))
124 {
125 return false;
126 }
127
128 if (ai->ai_family == AF_INET)
129 {
130 struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
131 server->addr[server->addr_count].in.a4.s_addr = sin->sin_addr.s_addr;
132 }
133 else
134 {
135 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
136 server->addr[server->addr_count].in.a6 = sin6->sin6_addr;
137 }
138
139 server->addr[server->addr_count].family = af;
140 server->addr[server->addr_count].port = port;
141 server->addr_count += 1;
142
143 freeaddrinfo(ai);
144 return true;
145}
146
147bool
148dns_domain_list_append(struct dns_domain **entry, char **domains, struct gc_arena *gc)
149{
150 /* Fast forward to the end of the list */
151 while (*entry)
152 {
153 entry = &((*entry)->next);
154 }
155
156 /* Append all domains to the end of the list */
157 while (*domains)
158 {
159 char *domain = *domains++;
160 if (!validate_domain(domain))
161 {
162 return false;
163 }
164
165 ALLOC_OBJ_CLEAR_GC(*entry, struct dns_domain, gc);
166 struct dns_domain *new = *entry;
167 new->name = domain;
168 entry = &new->next;
169 }
170
171 return true;
172}
173
174bool
175dns_server_priority_parse(long *priority, const char *str, bool pulled)
176{
177 char *endptr;
178 const long min = pulled ? 0 : INT8_MIN;
179 const long max = INT8_MAX;
180 long prio = strtol(str, &endptr, 10);
181 if (*endptr != '\0' || prio < min || prio > max)
182 {
183 return false;
184 }
185 *priority = prio;
186 return true;
187}
188
189struct dns_server *
190dns_server_get(struct dns_server **entry, long priority, struct gc_arena *gc)
191{
192 struct dns_server *obj = *entry;
193 while (true)
194 {
195 if (!obj || obj->priority > priority)
196 {
197 ALLOC_OBJ_CLEAR_GC(*entry, struct dns_server, gc);
198 (*entry)->next = obj;
199 (*entry)->priority = priority;
200 return *entry;
201 }
202 else if (obj->priority == priority)
203 {
204 return obj;
205 }
206 entry = &obj->next;
207 obj = *entry;
208 }
209}
210
211bool
212dns_options_verify(msglvl_t msglevel, const struct dns_options *o)
213{
214 const struct dns_server *server = o->servers ? o->servers : o->servers_prepull;
215 while (server)
216 {
217 if (server->addr_count == 0)
218 {
219 msg(msglevel, "ERROR: dns server %ld does not have an address assigned",
220 server->priority);
221 return false;
222 }
223 server = server->next;
224 }
225 return true;
226}
227
228static struct dns_domain *
229clone_dns_domains(const struct dns_domain *domain, struct gc_arena *gc)
230{
231 struct dns_domain *new_list = NULL;
232 struct dns_domain **new_entry = &new_list;
233
234 while (domain)
235 {
236 ALLOC_OBJ_CLEAR_GC(*new_entry, struct dns_domain, gc);
237 struct dns_domain *new_domain = *new_entry;
238 *new_domain = *domain;
239 new_entry = &new_domain->next;
240 domain = domain->next;
241 }
242
243 return new_list;
244}
245
246static struct dns_server *
247clone_dns_servers(const struct dns_server *server, struct gc_arena *gc)
248{
249 struct dns_server *new_list = NULL;
250 struct dns_server **new_entry = &new_list;
251
252 while (server)
253 {
254 ALLOC_OBJ_CLEAR_GC(*new_entry, struct dns_server, gc);
255 struct dns_server *new_server = *new_entry;
256 *new_server = *server;
257 new_server->domains = clone_dns_domains(server->domains, gc);
258 new_entry = &new_server->next;
259 server = server->next;
260 }
261
262 return new_list;
263}
264
265struct dns_options
266clone_dns_options(const struct dns_options *o, struct gc_arena *gc)
267{
268 struct dns_options clone;
269
270 memset(&clone, 0, sizeof(clone));
272 clone.servers = clone_dns_servers(o->servers, gc);
274 clone.updown = o->updown;
275 clone.updown_flags = o->updown_flags;
276 clone.from_dhcp = o->from_dhcp;
277
278 return clone;
279}
280
281void
283{
284 o->servers_prepull = o->servers;
285 o->servers = NULL;
286}
287
288void
290{
291 struct dns_server **entry = &o->servers;
292 struct dns_server *server = *entry;
293 struct dns_server *server_pp = o->servers_prepull;
294
295 while (server && server_pp)
296 {
297 if (server->priority > server_pp->priority)
298 {
299 /* Merge static server in front of pulled one */
300 struct dns_server *next_pp = server_pp->next;
301 server_pp->next = server;
302 *entry = server_pp;
303 server = *entry;
304 server_pp = next_pp;
305 }
306 else if (server->priority == server_pp->priority)
307 {
308 /* Pulled server overrides static one */
309 server_pp = server_pp->next;
310 }
311 entry = &server->next;
312 server = *entry;
313 }
314
315 /* Append remaining local servers */
316 if (server_pp)
317 {
318 *entry = server_pp;
319 }
320
321 o->servers_prepull = NULL;
322}
323
324static const char *
326{
327 switch (dnssec)
328 {
329 case DNS_SECURITY_YES:
330 return "yes";
331
333 return "optional";
334
335 case DNS_SECURITY_NO:
336 return "no";
337
338 default:
339 return "unset";
340 }
341}
342
343static const char *
345{
346 switch (transport)
347 {
349 return "DoH";
350
352 return "DoT";
353
355 return "plain";
356
357 default:
358 return "unset";
359 }
360}
361
362#ifdef _WIN32
363
364static void
365make_domain_list(const char *what, const struct dns_domain *src, bool nrpt_domains, char *dst,
366 size_t dst_size)
367{
368 /* NRPT domains need two \0 at the end for REG_MULTI_SZ
369 * and a leading '.' added in front of the domain name */
370 size_t term_size = nrpt_domains ? 2 : 1;
371 size_t leading_dot = nrpt_domains ? 1 : 0;
372 size_t offset = 0;
373
374 memset(dst, 0, dst_size);
375
376 while (src)
377 {
378 size_t len = strlen(src->name);
379 if (offset + leading_dot + len + term_size > dst_size)
380 {
381 msg(M_WARN, "WARNING: %s truncated", what);
382 if (offset)
383 {
384 /* Remove trailing comma */
385 *(dst + offset - 1) = '\0';
386 }
387 break;
388 }
389
390 if (leading_dot)
391 {
392 *(dst + offset++) = '.';
393 }
394 strncpy(dst + offset, src->name, len);
395 offset += len;
396
397 src = src->next;
398 if (src)
399 {
400 *(dst + offset++) = ',';
401 }
402 }
403}
404
405static void
406run_up_down_service(bool add, const struct options *o, const struct tuntap *tt)
407{
408 const struct dns_server *server = o->dns_options.servers;
409 const struct dns_domain *search_domains = o->dns_options.search_domains;
410
411 while (true)
412 {
413 if (!server)
414 {
415 if (add)
416 {
417 msg(M_WARN, "WARNING: setting DNS failed, no compatible server profile");
418 }
419 return;
420 }
421
422 bool only_standard_server_ports = true;
423 for (size_t i = 0; i < NRPT_ADDR_NUM; ++i)
424 {
425 if (server->addr[i].port && server->addr[i].port != 53)
426 {
427 only_standard_server_ports = false;
428 break;
429 }
430 }
431 if ((server->transport == DNS_TRANSPORT_UNSET || server->transport == DNS_TRANSPORT_PLAIN)
432 && only_standard_server_ports)
433 {
434 break; /* found compatible server */
435 }
436
437 server = server->next;
438 }
439
440 ack_message_t ack;
443 0 },
444 .iface = { .index = tt->adapter_index, .name = "" },
445 .flags = server->dnssec == DNS_SECURITY_NO ? 0 : nrpt_dnssec,
446 };
447 strncpynt(nrpt.iface.name, tt->actual_name, sizeof(nrpt.iface.name));
448
449 for (size_t i = 0; i < NRPT_ADDR_NUM; ++i)
450 {
451 if (server->addr[i].family == AF_UNSPEC)
452 {
453 /* No more addresses */
454 break;
455 }
456
457 if (inet_ntop(server->addr[i].family, &server->addr[i].in, nrpt.addresses[i],
459 == NULL)
460 {
461 msg(M_WARN, "WARNING: could not convert dns server address");
462 }
463 }
464
465 make_domain_list("dns server resolve domains", server->domains, true, nrpt.resolve_domains,
466 sizeof(nrpt.resolve_domains));
467
468 make_domain_list("dns search domains", search_domains, false, nrpt.search_domains,
469 sizeof(nrpt.search_domains));
470
471 msg(D_LOW, "%s NRPT DNS%s%s on '%s' (if_index = %lu) using service",
472 (add ? "Setting" : "Deleting"), nrpt.resolve_domains[0] != 0 ? ", resolve domains" : "",
473 nrpt.search_domains[0] != 0 ? ", search domains" : "",
474 nrpt.iface.name, nrpt.iface.index);
475
476 send_msg_iservice(o->msg_channel, &nrpt, sizeof(nrpt), &ack, "DNS");
477}
478
479#else /* ifdef _WIN32 */
480
481#if defined(__GNUC__) || defined(__clang__)
482#pragma GCC diagnostic push
483#pragma GCC diagnostic ignored "-Wsign-compare"
484#endif
485
486static void
487setenv_dns_option(struct env_set *es, const char *format, int i, int j, const char *value)
488{
489 char name[64];
490 bool name_ok = false;
491
492 if (j < 0)
493 {
494 name_ok = checked_snprintf(name, sizeof(name), format, i);
495 }
496 else
497 {
498 name_ok = checked_snprintf(name, sizeof(name), format, i, j);
499 }
500
501 if (!name_ok)
502 {
503 msg(M_WARN, "WARNING: dns option setenv name buffer overflow");
504 }
505
506 setenv_str(es, name, value);
507}
508
509static void
510setenv_dns_options(const struct dns_options *o, struct env_set *es)
511{
512 struct gc_arena gc = gc_new();
513 const struct dns_server *s;
514 const struct dns_domain *d;
515 int i, j;
516
517 for (i = 1, d = o->search_domains; d != NULL; i++, d = d->next)
518 {
519 setenv_dns_option(es, "dns_search_domain_%d", i, -1, d->name);
520 }
521
522 for (i = 1, s = o->servers; s != NULL; i++, s = s->next)
523 {
524 for (j = 0; j < s->addr_count; ++j)
525 {
526 if (s->addr[j].family == AF_INET)
527 {
528 setenv_dns_option(es, "dns_server_%d_address_%d", i, j + 1,
529 print_in_addr_t(s->addr[j].in.a4.s_addr, IA_NET_ORDER, &gc));
530 }
531 else
532 {
533 setenv_dns_option(es, "dns_server_%d_address_%d", i, j + 1,
534 print_in6_addr(s->addr[j].in.a6, 0, &gc));
535 }
536 if (s->addr[j].port)
537 {
538 setenv_dns_option(es, "dns_server_%d_port_%d", i, j + 1,
539 print_in_port_t(s->addr[j].port, &gc));
540 }
541 }
542
543 if (s->domains)
544 {
545 for (j = 1, d = s->domains; d != NULL; j++, d = d->next)
546 {
547 setenv_dns_option(es, "dns_server_%d_resolve_domain_%d", i, j, d->name);
548 }
549 }
550
551 if (s->dnssec)
552 {
553 setenv_dns_option(es, "dns_server_%d_dnssec", i, -1, dnssec_value(s->dnssec));
554 }
555
556 if (s->transport)
557 {
558 setenv_dns_option(es, "dns_server_%d_transport", i, -1, transport_value(s->transport));
559 }
560 if (s->sni)
561 {
562 setenv_dns_option(es, "dns_server_%d_sni", i, -1, s->sni);
563 }
564 }
565
566 gc_free(&gc);
567}
568
569#if defined(__GNUC__) || defined(__clang__)
570#pragma GCC diagnostic pop
571#endif
572
573static void
574updown_env_set(bool up, const struct dns_options *o, const struct tuntap *tt, struct env_set *es)
575{
576 setenv_str(es, "dev", tt->actual_name);
577 setenv_str(es, "script_type", up ? "dns-up" : "dns-down");
578 setenv_dns_options(o, es);
579}
580
581static int
582do_run_up_down_command(bool up, const char *vars_file, const struct dns_options *o,
583 const struct tuntap *tt)
584{
585 struct gc_arena gc = gc_new();
586 struct argv argv = argv_new();
587 struct env_set *es = env_set_create(&gc);
588
589 if (vars_file)
590 {
591 setenv_str(es, "dns_vars_file", vars_file);
592 }
593 else
594 {
595 updown_env_set(up, o, tt, es);
596 }
597
598 argv_printf(&argv, "%s", o->updown);
600 int res;
601 if (dns_updown_user_set(o))
602 {
603 res = openvpn_run_script(&argv, es, S_EXITCODE, "dns updown");
604 }
605 else
606 {
607 res = openvpn_execve_check(&argv, es, S_EXITCODE, "WARNING: Failed running dns updown");
608 }
609 argv_free(&argv);
610 gc_free(&gc);
611 return res;
612}
613
614static bool
615run_updown_runner(bool up, struct options *o, const struct tuntap *tt,
616 struct dns_updown_runner_info *updown_runner)
617{
618 int dns_pipe_fd[2];
619 int ack_pipe_fd[2];
620 if (pipe(dns_pipe_fd) != 0 || pipe(ack_pipe_fd) != 0)
621 {
622 msg(M_WARN | M_ERRNO, "run_dns_up_down: unable to create pipes");
623 return false;
624 }
625 updown_runner->pid = fork();
626 if (updown_runner->pid == -1)
627 {
628 msg(M_WARN | M_ERRNO, "run_dns_up_down: unable to fork");
629 close(dns_pipe_fd[0]);
630 close(dns_pipe_fd[1]);
631 close(ack_pipe_fd[0]);
632 close(ack_pipe_fd[1]);
633 return false;
634 }
635 else if (updown_runner->pid > 0)
636 {
637 /* Parent process */
638 close(dns_pipe_fd[0]);
639 close(ack_pipe_fd[1]);
640 updown_runner->fds[0] = ack_pipe_fd[0];
641 updown_runner->fds[1] = dns_pipe_fd[1];
642 }
643 else
644 {
645 /* Script runner process, close unused FDs */
646 for (int fd = 3; fd < 100; ++fd)
647 {
648 if (fd != dns_pipe_fd[0] && fd != ack_pipe_fd[1])
649 {
650 close(fd);
651 }
652 }
653
654 /* Ignore signals */
655 signal(SIGINT, SIG_IGN);
656 signal(SIGHUP, SIG_IGN);
657 signal(SIGTERM, SIG_IGN);
658 signal(SIGUSR1, SIG_IGN);
659 signal(SIGUSR2, SIG_IGN);
660 signal(SIGPIPE, SIG_IGN);
661
662 while (1)
663 {
664 char path[PATH_MAX];
665
666 /* Block here until parent sends a path */
667 ssize_t rlen = read(dns_pipe_fd[0], &path, sizeof(path));
668 if (rlen < 1)
669 {
670 if (rlen == -1 && errno == EINTR)
671 {
672 continue;
673 }
674 close(dns_pipe_fd[0]);
675 close(ack_pipe_fd[1]);
676 exit(0);
677 }
678
679 path[sizeof(path) - 1] = '\0';
680 int res = do_run_up_down_command(up, path, &o->dns_options, tt);
681 platform_unlink(path);
682
683 /* Unblock parent process */
684 while (1)
685 {
686 ssize_t wlen = write(ack_pipe_fd[1], &res, sizeof(res));
687 if ((wlen == -1 && errno != EINTR) || wlen < (ssize_t)sizeof(res))
688 {
689 /* Not much we can do about errors but exit */
690 close(dns_pipe_fd[0]);
691 close(ack_pipe_fd[1]);
692 exit(0);
693 }
694 else if (wlen == sizeof(res))
695 {
696 break;
697 }
698 }
699
700 up = !up; /* do the opposite next time */
701 }
702 }
703
704 return true;
705}
706
707static void
708run_up_down_command(bool up, struct options *o, const struct tuntap *tt,
709 struct dns_updown_runner_info *updown_runner)
710{
711 struct dns_options *dns = &o->dns_options;
712 if (!dns->updown || (o->up_script && !dns_updown_user_set(dns) && !dns_updown_forced(dns)))
713 {
714 return;
715 }
716
717 int status = -1;
718
719 if (!updown_runner->required)
720 {
721 /* Run dns updown directly */
722 status = do_run_up_down_command(up, NULL, dns, tt);
723 }
724 else
725 {
726 if (updown_runner->pid < 1)
727 {
728 /* Need to set up privilege preserving child first */
729 if (!run_updown_runner(up, o, tt, updown_runner))
730 {
731 return;
732 }
733 }
734
735 struct gc_arena gc = gc_new();
736 const char *dvf = platform_create_temp_file(o->tmp_dir, "dvf", &gc);
737 if (!dvf)
738 {
739 msg(M_ERR, "could not create dns vars file");
740 goto out_free;
741 }
742
743 struct env_set *es = env_set_create(&gc);
744 updown_env_set(up, &o->dns_options, tt, es);
746
747 int wfd = updown_runner->fds[1];
748 ssize_t dvf_size = strlen(dvf) + 1;
749 while (1)
750 {
751 ssize_t len = write(wfd, dvf, dvf_size);
752 if (len < dvf_size)
753 {
754 if (len == -1 && errno == EINTR)
755 {
756 continue;
757 }
758 msg(M_WARN | M_ERRNO, "could not send dns vars filename");
759 }
760 break;
761 }
762
763 int rfd = updown_runner->fds[0];
764 while (1)
765 {
766 ssize_t len = read(rfd, &status, sizeof(status));
767 if (len < (ssize_t)sizeof(status))
768 {
769 if (len == -1 && errno == EINTR)
770 {
771 continue;
772 }
773 msg(M_WARN | M_ERRNO, "could not receive dns updown status");
774 }
775 break;
776 }
777
778out_free:
779 gc_free(&gc);
780 }
781
782 msg(M_INFO, "dns %s command exited with status %d", up ? "up" : "down", status);
783}
784
785#endif /* _WIN32 */
786
787void
789{
790 struct gc_arena gc = gc_new();
791
792 int i = 1;
793 struct dns_server *server = o->servers_prepull ? o->servers_prepull : o->servers;
794 while (server)
795 {
796 msg(D_SHOW_PARMS, " DNS server #%d:", i++);
797
798 for (size_t j = 0; j < server->addr_count; ++j)
799 {
800 const char *addr;
801 const char *fmt_port;
802 if (server->addr[j].family == AF_INET)
803 {
804 addr = print_in_addr_t(server->addr[j].in.a4.s_addr, IA_NET_ORDER, &gc);
805 fmt_port = " address = %s:%s";
806 }
807 else
808 {
809 addr = print_in6_addr(server->addr[j].in.a6, 0, &gc);
810 fmt_port = " address = [%s]:%s";
811 }
812
813 if (server->addr[j].port)
814 {
815 const char *port = print_in_port_t(server->addr[j].port, &gc);
816 msg(D_SHOW_PARMS, fmt_port, addr, port);
817 }
818 else
819 {
820 msg(D_SHOW_PARMS, " address = %s", addr);
821 }
822 }
823
824 if (server->dnssec)
825 {
826 msg(D_SHOW_PARMS, " dnssec = %s", dnssec_value(server->dnssec));
827 }
828
829 if (server->transport)
830 {
831 msg(D_SHOW_PARMS, " transport = %s", transport_value(server->transport));
832 }
833 if (server->sni)
834 {
835 msg(D_SHOW_PARMS, " sni = %s", server->sni);
836 }
837
838 struct dns_domain *domain = server->domains;
839 if (domain)
840 {
841 msg(D_SHOW_PARMS, " resolve domains:");
842 while (domain)
843 {
844 msg(D_SHOW_PARMS, " %s", domain->name);
845 domain = domain->next;
846 }
847 }
848
849 server = server->next;
850 }
851
852 struct dns_domain *search_domain = o->search_domains;
853 if (search_domain)
854 {
855 msg(D_SHOW_PARMS, " DNS search domains:");
856 while (search_domain)
857 {
858 msg(D_SHOW_PARMS, " %s", search_domain->name);
859 search_domain = search_domain->next;
860 }
861 }
862
863 gc_free(&gc);
864}
865
866void
867run_dns_up_down(bool up, struct options *o, const struct tuntap *tt,
868 struct dns_updown_runner_info *duri)
869{
870 if (!o->dns_options.servers)
871 {
872 return;
873 }
874#ifdef _WIN32
875 /* Don't use iservice in DHCP mode */
876 struct tuntap_options *tto = &o->tuntap_options;
878 {
879 return;
880 }
881#endif
882
883 /* Warn about adding servers of unsupported AF */
884 const struct dns_server *s = o->dns_options.servers;
885 while (up && s)
886 {
887 size_t bad_count = 0;
888 for (size_t i = 0; i < s->addr_count; ++i)
889 {
890 if ((s->addr[i].family == AF_INET6 && !tt->did_ifconfig_ipv6_setup)
891 || (s->addr[i].family == AF_INET && !tt->did_ifconfig_setup))
892 {
893 ++bad_count;
894 }
895 }
896 if (bad_count == s->addr_count)
897 {
898 msg(M_WARN,
899 "DNS server %ld only has address(es) from a family "
900 "the tunnel is not configured for - it will not be reachable",
901 s->priority);
902 }
903 else if (bad_count)
904 {
905 msg(M_WARN,
906 "DNS server %ld has address(es) from a family "
907 "the tunnel is not configured for",
908 s->priority);
909 }
910 s = s->next;
911 }
912
913#ifdef _WIN32
914 run_up_down_service(up, o, tt);
915#else
916 run_up_down_command(up, o, tt, duri);
917#endif /* ifdef _WIN32 */
918}
void argv_msg(const msglvl_t msglevel, const struct argv *a)
Write the arguments stored in a struct argv via the msg() command.
Definition argv.c:242
void argv_free(struct argv *a)
Frees all memory allocations allocated by the struct argv related functions.
Definition argv.c:101
bool argv_printf(struct argv *argres, const char *format,...)
printf() variant which populates a struct argv.
Definition argv.c:438
struct argv argv_new(void)
Allocates a new struct argv and ensures it is initialised.
Definition argv.c:87
bool checked_snprintf(char *str, size_t size, const char *format,...)
Like snprintf() but returns an boolean.
Definition buffer.c:1143
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Definition buffer.h:1125
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition buffer.h:362
static void gc_free(struct gc_arena *a)
Definition buffer.h:1049
static struct gc_arena gc_new(void)
Definition buffer.h:1041
bool dns_options_verify(msglvl_t msglevel, const struct dns_options *o)
Checks validity of DNS options.
Definition dns.c:212
static const char * dnssec_value(const enum dns_security dnssec)
Definition dns.c:325
void run_dns_up_down(bool up, struct options *o, const struct tuntap *tt, struct dns_updown_runner_info *duri)
Invokes the action associated with bringing DNS up or down.
Definition dns.c:867
void dns_options_postprocess_pull(struct dns_options *o)
Merges pulled DNS servers with static ones into an ordered list.
Definition dns.c:289
bool dns_server_addr_parse(struct dns_server *server, const char *addr)
Parses a string IPv4 or IPv6 address and optional colon separated port, into a in_addr or in6_addr re...
Definition dns.c:62
bool dns_domain_list_append(struct dns_domain **entry, char **domains, struct gc_arena *gc)
Appends safe DNS domain parameters to a linked list.
Definition dns.c:148
struct dns_server * dns_server_get(struct dns_server **entry, long priority, struct gc_arena *gc)
Find or create DNS server with priority in a linked list.
Definition dns.c:190
static void run_up_down_service(bool add, const struct options *o, const struct tuntap *tt)
Definition dns.c:406
static void make_domain_list(const char *what, const struct dns_domain *src, bool nrpt_domains, char *dst, size_t dst_size)
Definition dns.c:365
static bool dns_server_port_parse(in_port_t *port, const char *port_str)
Parses a string as port and stores it.
Definition dns.c:48
static struct dns_server * clone_dns_servers(const struct dns_server *server, struct gc_arena *gc)
Definition dns.c:247
static struct dns_domain * clone_dns_domains(const struct dns_domain *domain, struct gc_arena *gc)
Definition dns.c:229
static const char * transport_value(const enum dns_server_transport transport)
Definition dns.c:344
bool dns_server_priority_parse(long *priority, const char *str, bool pulled)
Parses a string DNS server priority and validates it.
Definition dns.c:175
struct dns_options clone_dns_options(const struct dns_options *o, struct gc_arena *gc)
Makes a deep copy of the passed DNS options.
Definition dns.c:266
void show_dns_options(const struct dns_options *o)
Prints configured DNS options.
Definition dns.c:788
void dns_options_preprocess_pull(struct dns_options *o)
Saves and resets the server options, so that pulled ones don't mix in.
Definition dns.c:282
static bool dns_updown_user_set(const struct dns_options *o)
Returns whether dns-updown is user defined.
Definition dns.h:218
dns_security
Definition dns.h:31
@ DNS_SECURITY_NO
Definition dns.h:33
@ DNS_SECURITY_YES
Definition dns.h:34
@ DNS_SECURITY_OPTIONAL
Definition dns.h:35
static bool dns_updown_forced(const struct dns_options *o)
Returns whether dns-updown is forced to run.
Definition dns.h:229
dns_server_transport
Definition dns.h:39
@ DNS_TRANSPORT_PLAIN
Definition dns.h:41
@ DNS_TRANSPORT_UNSET
Definition dns.h:40
@ DNS_TRANSPORT_TLS
Definition dns.h:43
@ DNS_TRANSPORT_HTTPS
Definition dns.h:42
static bool validate_domain(const char *domain)
void env_set_write_file(const char *path, const struct env_set *es)
Write a struct env_set to a file.
Definition env_set.c:238
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition env_set.c:307
struct env_set * env_set_create(struct gc_arena *gc)
Definition env_set.c:156
#define D_SHOW_PARMS
Definition errlevel.h:95
#define D_LOW
Definition errlevel.h:96
#define M_INFO
Definition errlevel.h:54
static SERVICE_STATUS status
Definition interactive.c:51
@ write
@ read
@ nrpt_dnssec
@ msg_add_nrpt_cfg
Definition openvpn-msg.h:38
@ msg_del_nrpt_cfg
Definition openvpn-msg.h:39
#define NRPT_ADDR_SIZE
#define NRPT_ADDR_NUM
#define SIZE(x)
Definition basic.h:29
#define M_ERR
Definition error.h:106
#define msg(flags,...)
Definition error.h:152
unsigned int msglvl_t
Definition error.h:77
#define M_WARN
Definition error.h:92
#define M_ERRNO
Definition error.h:95
const char * platform_create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)
Create a temporary file in directory, returns the filename of the created file.
Definition platform.c:540
bool platform_unlink(const char *filename)
Definition platform.c:487
int openvpn_execve_check(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message)
#define S_EXITCODE
Instead of returning 1/0 for success/fail, return exit code when between 0 and 255 and -1 otherwise.
Definition run_command.h:53
static int openvpn_run_script(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *hook)
Will run a script and return the exit code of the script if between 0 and 255, -1 otherwise.
Definition run_command.h:89
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)
const char * print_in_port_t(in_port_t port, struct gc_arena *gc)
const char * print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
#define IA_NET_ORDER
Definition socket_util.h:90
Definition argv.h:35
struct dns_domain * next
Definition dns.h:55
const char * name
Definition dns.h:56
struct dns_server * servers
Definition dns.h:117
const char * updown
Definition dns.h:119
struct dhcp_options from_dhcp
Definition dns.h:114
struct dns_server * servers_prepull
Definition dns.h:116
enum dns_updown_flags updown_flags
Definition dns.h:120
struct dns_domain * search_domains
Definition dns.h:115
struct in_addr a4
Definition dns.h:63
union dns_server_addr::@0 in
sa_family_t family
Definition dns.h:66
struct in6_addr a6
Definition dns.h:64
in_port_t port
Definition dns.h:67
struct dns_server_addr addr[8]
Definition dns.h:75
enum dns_security dnssec
Definition dns.h:77
struct dns_server * next
Definition dns.h:72
long priority
Definition dns.h:73
size_t addr_count
Definition dns.h:74
struct dns_domain * domains
Definition dns.h:76
enum dns_server_transport transport
Definition dns.h:78
const char * sni
Definition dns.h:79
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
char name[256]
Definition openvpn-msg.h:71
message_header_t header
nrpt_address_t addresses[NRPT_ADDR_NUM]
const char * tmp_dir
Definition options.h:464
const char * up_script
Definition options.h:383
HANDLE msg_channel
Definition options.h:688
struct tuntap_options tuntap_options
Definition options.h:369
struct dns_options dns_options
Definition options.h:316
int ip_win32_type
Definition tun.h:83
Definition tun.h:181
DWORD adapter_index
Definition tun.h:232
bool did_ifconfig_ipv6_setup
if the internal variables related to ifconfig-ipv6 of this struct have been set up.
Definition tun.h:199
bool did_ifconfig_setup
if the internal variables related to ifconfig of this struct have been set up.
Definition tun.h:195
char * actual_name
Definition tun.h:205
#define SIGHUP
Definition syshead.h:55
unsigned short sa_family_t
Definition syshead.h:409
#define SIGINT
Definition syshead.h:56
#define SIGTERM
Definition syshead.h:59
#define SIGUSR1
Definition syshead.h:57
uint16_t in_port_t
Definition syshead.h:53
#define SIGUSR2
Definition syshead.h:58
struct env_set * es
struct gc_arena gc
Definition test_ssl.c:131
#define IPW32_SET_ADAPTIVE
Definition tun.h:81
#define IPW32_SET_DHCP_MASQ
Definition tun.h:80
bool send_msg_iservice(HANDLE pipe, const void *data, DWORD size, ack_message_t *ack, const char *context)
Send the size bytes in buffer data to the interactive service pipe and read the result in ack.
Definition win32.c:1422