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-2024 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, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include "syshead.h"
29
30#include "dns.h"
31#include "socket.h"
32#include "options.h"
33#include "run_command.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, 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 char *first_colon = strchr(addr, ':');
75 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 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
147void
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 ALLOC_OBJ_CLEAR_GC(*entry, struct dns_domain, gc);
160 struct dns_domain *new = *entry;
161 new->name = *domains++;
162 entry = &new->next;
163 }
164}
165
166bool
167dns_server_priority_parse(long *priority, const char *str, bool pulled)
168{
169 char *endptr;
170 const long min = pulled ? 0 : INT8_MIN;
171 const long max = INT8_MAX;
172 long prio = strtol(str, &endptr, 10);
173 if (*endptr != '\0' || prio < min || prio > max)
174 {
175 return false;
176 }
177 *priority = prio;
178 return true;
179}
180
181struct dns_server *
182dns_server_get(struct dns_server **entry, long priority, struct gc_arena *gc)
183{
184 struct dns_server *obj = *entry;
185 while (true)
186 {
187 if (!obj || obj->priority > priority)
188 {
189 ALLOC_OBJ_CLEAR_GC(*entry, struct dns_server, gc);
190 (*entry)->next = obj;
191 (*entry)->priority = priority;
192 return *entry;
193 }
194 else if (obj->priority == priority)
195 {
196 return obj;
197 }
198 entry = &obj->next;
199 obj = *entry;
200 }
201}
202
203bool
204dns_options_verify(int msglevel, const struct dns_options *o)
205{
206 const struct dns_server *server =
207 o->servers ? o->servers : o->servers_prepull;
208 while (server)
209 {
210 if (server->addr_count == 0)
211 {
212 msg(msglevel, "ERROR: dns server %ld does not have an address assigned", server->priority);
213 return false;
214 }
215 server = server->next;
216 }
217 return true;
218}
219
220static struct dns_domain *
221clone_dns_domains(const struct dns_domain *domain, struct gc_arena *gc)
222{
223 struct dns_domain *new_list = NULL;
224 struct dns_domain **new_entry = &new_list;
225
226 while (domain)
227 {
228 ALLOC_OBJ_CLEAR_GC(*new_entry, struct dns_domain, gc);
229 struct dns_domain *new_domain = *new_entry;
230 *new_domain = *domain;
231 new_entry = &new_domain->next;
232 domain = domain->next;
233 }
234
235 return new_list;
236}
237
238static struct dns_server *
239clone_dns_servers(const struct dns_server *server, struct gc_arena *gc)
240{
241 struct dns_server *new_list = NULL;
242 struct dns_server **new_entry = &new_list;
243
244 while (server)
245 {
246 ALLOC_OBJ_CLEAR_GC(*new_entry, struct dns_server, gc);
247 struct dns_server *new_server = *new_entry;
248 *new_server = *server;
249 new_server->domains = clone_dns_domains(server->domains, gc);
250 new_entry = &new_server->next;
251 server = server->next;
252 }
253
254 return new_list;
255}
256
257struct dns_options
258clone_dns_options(const struct dns_options *o, struct gc_arena *gc)
259{
260 struct dns_options clone;
261
262 memset(&clone, 0, sizeof(clone));
264 clone.servers = clone_dns_servers(o->servers, gc);
266 clone.updown = o->updown;
268
269 return clone;
270}
271
272void
274{
275 o->servers_prepull = o->servers;
276 o->servers = NULL;
277}
278
279void
281{
282 struct dns_server **entry = &o->servers;
283 struct dns_server *server = *entry;
284 struct dns_server *server_pp = o->servers_prepull;
285
286 while (server && server_pp)
287 {
288 if (server->priority > server_pp->priority)
289 {
290 /* Merge static server in front of pulled one */
291 struct dns_server *next_pp = server_pp->next;
292 server_pp->next = server;
293 *entry = server_pp;
294 server = *entry;
295 server_pp = next_pp;
296 }
297 else if (server->priority == server_pp->priority)
298 {
299 /* Pulled server overrides static one */
300 server_pp = server_pp->next;
301 }
302 entry = &server->next;
303 server = *entry;
304 }
305
306 /* Append remaining local servers */
307 if (server_pp)
308 {
309 *entry = server_pp;
310 }
311
312 o->servers_prepull = NULL;
313}
314
315static const char *
317{
318 switch (dnssec)
319 {
320 case DNS_SECURITY_YES:
321 return "yes";
322
324 return "optional";
325
326 case DNS_SECURITY_NO:
327 return "no";
328
329 default:
330 return "unset";
331 }
332}
333
334static const char *
336{
337 switch (transport)
338 {
340 return "DoH";
341
343 return "DoT";
344
346 return "plain";
347
348 default:
349 return "unset";
350 }
351}
352
353#ifdef _WIN32
354
355static void
356make_domain_list(const char *what, const struct dns_domain *src,
357 bool nrpt_domains, char *dst, size_t dst_size)
358{
359 /* NRPT domains need two \0 at the end for REG_MULTI_SZ
360 * and a leading '.' added in front of the domain name */
361 size_t term_size = nrpt_domains ? 2 : 1;
362 size_t leading_dot = nrpt_domains ? 1 : 0;
363 size_t offset = 0;
364
365 memset(dst, 0, dst_size);
366
367 while (src)
368 {
369 size_t len = strlen(src->name);
370 if (offset + leading_dot + len + term_size > dst_size)
371 {
372 msg(M_WARN, "WARNING: %s truncated", what);
373 if (offset)
374 {
375 /* Remove trailing comma */
376 *(dst + offset - 1) = '\0';
377 }
378 break;
379 }
380
381 if (leading_dot)
382 {
383 *(dst + offset++) = '.';
384 }
385 strncpy(dst + offset, src->name, len);
386 offset += len;
387
388 src = src->next;
389 if (src)
390 {
391 *(dst + offset++) = ',';
392 }
393 }
394}
395
396static void
397run_up_down_service(bool add, const struct options *o, const struct tuntap *tt)
398{
399 const struct dns_server *server = o->dns_options.servers;
400 const struct dns_domain *search_domains = o->dns_options.search_domains;
401
402 while (true)
403 {
404 if (!server)
405 {
406 if (add)
407 {
408 msg(M_WARN, "WARNING: setting DNS failed, no compatible server profile");
409 }
410 return;
411 }
412
413 bool only_standard_server_ports = true;
414 for (size_t i = 0; i < NRPT_ADDR_NUM; ++i)
415 {
416 if (server->addr[i].port && server->addr[i].port != 53)
417 {
418 only_standard_server_ports = false;
419 break;
420 }
421 }
422 if ((server->transport == DNS_TRANSPORT_UNSET || server->transport == DNS_TRANSPORT_PLAIN)
423 && only_standard_server_ports)
424 {
425 break; /* found compatible server */
426 }
427
428 server = server->next;
429 }
430
431 ack_message_t ack;
433 .header = {
436 0
437 },
438 .iface = { .index = tt->adapter_index, .name = "" },
439 .flags = server->dnssec == DNS_SECURITY_NO ? 0 : nrpt_dnssec,
440 };
441 strncpynt(nrpt.iface.name, tt->actual_name, sizeof(nrpt.iface.name));
442
443 for (size_t i = 0; i < NRPT_ADDR_NUM; ++i)
444 {
445 if (server->addr[i].family == AF_UNSPEC)
446 {
447 /* No more addresses */
448 break;
449 }
450
451 if (inet_ntop(server->addr[i].family, &server->addr[i].in,
452 nrpt.addresses[i], NRPT_ADDR_SIZE) == NULL)
453 {
454 msg(M_WARN, "WARNING: could not convert dns server address");
455 }
456 }
457
458 make_domain_list("dns server resolve domains", server->domains, true,
459 nrpt.resolve_domains, sizeof(nrpt.resolve_domains));
460
461 make_domain_list("dns search domains", search_domains, false,
462 nrpt.search_domains, sizeof(nrpt.search_domains));
463
464 send_msg_iservice(o->msg_channel, &nrpt, sizeof(nrpt), &ack, "DNS");
465}
466
467#else /* ifdef _WIN32 */
468
469static void
470setenv_dns_option(struct env_set *es,
471 const char *format, int i, int j,
472 const char *value)
473{
474 char name[64];
475 bool name_ok = false;
476
477 if (j < 0)
478 {
479 name_ok = snprintf(name, sizeof(name), format, i);
480 }
481 else
482 {
483 name_ok = snprintf(name, sizeof(name), format, i, j);
484 }
485
486 if (!name_ok)
487 {
488 msg(M_WARN, "WARNING: dns option setenv name buffer overflow");
489 }
490
491 setenv_str(es, name, value);
492}
493
494static void
495setenv_dns_options(const struct dns_options *o, struct env_set *es)
496{
497 struct gc_arena gc = gc_new();
498 const struct dns_server *s;
499 const struct dns_domain *d;
500 int i, j;
501
502 for (i = 1, d = o->search_domains; d != NULL; i++, d = d->next)
503 {
504 setenv_dns_option(es, "dns_search_domain_%d", i, -1, d->name);
505 }
506
507 for (i = 1, s = o->servers; s != NULL; i++, s = s->next)
508 {
509 for (j = 0; j < s->addr_count; ++j)
510 {
511 if (s->addr[j].family == AF_INET)
512 {
513 setenv_dns_option(es, "dns_server_%d_address_%d", i, j + 1,
514 print_in_addr_t(s->addr[j].in.a4.s_addr, IA_NET_ORDER, &gc));
515 }
516 else
517 {
518 setenv_dns_option(es, "dns_server_%d_address_%d", i, j + 1,
519 print_in6_addr(s->addr[j].in.a6, 0, &gc));
520 }
521 if (s->addr[j].port)
522 {
523 setenv_dns_option(es, "dns_server_%d_port_%d", i, j + 1,
524 print_in_port_t(s->addr[j].port, &gc));
525 }
526 }
527
528 if (s->domains)
529 {
530 for (j = 1, d = s->domains; d != NULL; j++, d = d->next)
531 {
532 setenv_dns_option(es, "dns_server_%d_resolve_domain_%d", i, j, d->name);
533 }
534 }
535
536 if (s->dnssec)
537 {
538 setenv_dns_option(es, "dns_server_%d_dnssec", i, -1,
539 dnssec_value(s->dnssec));
540 }
541
542 if (s->transport)
543 {
544 setenv_dns_option(es, "dns_server_%d_transport", i, -1,
546 }
547 if (s->sni)
548 {
549 setenv_dns_option(es, "dns_server_%d_sni", i, -1, s->sni);
550 }
551 }
552
553 gc_free(&gc);
554}
555
556static void
557updown_env_set(bool up, const struct dns_options *o, const struct tuntap *tt, struct env_set *es)
558{
559 setenv_str(es, "dev", tt->actual_name);
560 setenv_str(es, "script_type", up ? "dns-up" : "dns-down");
561 setenv_dns_options(o, es);
562}
563
564static int
565do_run_up_down_command(bool up, const char *vars_file, const struct dns_options *o, const struct tuntap *tt)
566{
567 struct gc_arena gc = gc_new();
568 struct argv argv = argv_new();
569 struct env_set *es = env_set_create(&gc);
570
571 if (vars_file)
572 {
573 setenv_str(es, "dns_vars_file", vars_file);
574 }
575 else
576 {
577 updown_env_set(up, o, tt, es);
578 }
579
580 argv_printf(&argv, "%s", o->updown);
582 int res;
583 if (o->user_set_updown)
584 {
585 res = openvpn_run_script(&argv, es, S_EXITCODE, "dns updown");
586 }
587 else
588 {
589 res = openvpn_execve_check(&argv, es, S_EXITCODE, "WARNING: Failed running dns updown");
590 }
591 argv_free(&argv);
592 gc_free(&gc);
593 return res;
594}
595
596static bool
597run_updown_runner(bool up, struct options *o, const struct tuntap *tt, struct dns_updown_runner_info *updown_runner)
598{
599 int dns_pipe_fd[2];
600 int ack_pipe_fd[2];
601 if (pipe(dns_pipe_fd) != 0
602 || pipe(ack_pipe_fd) != 0)
603 {
604 msg(M_ERR | M_ERRNO, "run_dns_up_down: unable to create pipes");
605 return false;
606 }
607 updown_runner->pid = fork();
608 if (updown_runner->pid == -1)
609 {
610 msg(M_ERR | M_ERRNO, "run_dns_up_down: unable to fork");
611 close(dns_pipe_fd[0]);
612 close(dns_pipe_fd[1]);
613 close(ack_pipe_fd[0]);
614 close(ack_pipe_fd[1]);
615 return false;
616 }
617 else if (updown_runner->pid > 0)
618 {
619 /* Parent process */
620 close(dns_pipe_fd[0]);
621 close(ack_pipe_fd[1]);
622 updown_runner->fds[0] = ack_pipe_fd[0];
623 updown_runner->fds[1] = dns_pipe_fd[1];
624 }
625 else
626 {
627 /* Script runner process, close unused FDs */
628 for (int fd = 3; fd < 100; ++fd)
629 {
630 if (fd != dns_pipe_fd[0]
631 && fd != ack_pipe_fd[1])
632 {
633 close(fd);
634 }
635 }
636
637 /* Ignore signals */
638 signal(SIGINT, SIG_IGN);
639 signal(SIGHUP, SIG_IGN);
640 signal(SIGTERM, SIG_IGN);
641 signal(SIGUSR1, SIG_IGN);
642 signal(SIGUSR2, SIG_IGN);
643 signal(SIGPIPE, SIG_IGN);
644
645 while (1)
646 {
647 ssize_t rlen, wlen;
648 char path[PATH_MAX];
649
650 /* Block here until parent sends a path */
651 rlen = read(dns_pipe_fd[0], &path, sizeof(path));
652 if (rlen < 1)
653 {
654 if (rlen == -1 && errno == EINTR)
655 {
656 continue;
657 }
658 close(dns_pipe_fd[0]);
659 close(ack_pipe_fd[1]);
660 exit(0);
661 }
662
663 path[sizeof(path) - 1] = '\0';
664 int res = do_run_up_down_command(up, path, &o->dns_options, tt);
665 platform_unlink(path);
666
667 /* Unblock parent process */
668 while (1)
669 {
670 wlen = write(ack_pipe_fd[1], &res, sizeof(res));
671 if ((wlen == -1 && errno != EINTR) || wlen < sizeof(res))
672 {
673 /* Not much we can do about errors but exit */
674 close(dns_pipe_fd[0]);
675 close(ack_pipe_fd[1]);
676 exit(0);
677 }
678 else if (wlen == sizeof(res))
679 {
680 break;
681 }
682 }
683
684 up = !up; /* do the opposite next time */
685 }
686 }
687
688 return true;
689}
690
691static void
692run_up_down_command(bool up, struct options *o, const struct tuntap *tt, struct dns_updown_runner_info *updown_runner)
693{
694 if (!o->dns_options.updown)
695 {
696 return;
697 }
698
699 int status = -1;
700
701 if (!updown_runner->required)
702 {
703 /* Run dns updown directly */
704 status = do_run_up_down_command(up, NULL, &o->dns_options, tt);
705 }
706 else
707 {
708 if (updown_runner->pid < 1)
709 {
710 /* Need to set up privilege preserving child first */
711 if (!run_updown_runner(up, o, tt, updown_runner))
712 {
713 return;
714 }
715 }
716
717 struct gc_arena gc = gc_new();
718 const char *dvf = platform_create_temp_file(o->tmp_dir, "dvf", &gc);
719 if (!dvf)
720 {
721 msg(M_ERR, "could not create dns vars file");
722 goto out_free;
723 }
724
725 struct env_set *es = env_set_create(&gc);
726 updown_env_set(up, &o->dns_options, tt, es);
728
729 int wfd = updown_runner->fds[1];
730 size_t dvf_size = strlen(dvf) + 1;
731 while (1)
732 {
733 ssize_t len = write(wfd, dvf, dvf_size);
734 if (len < dvf_size)
735 {
736 if (len == -1 && errno == EINTR)
737 {
738 continue;
739 }
740 msg(M_ERR | M_ERRNO, "could not send dns vars filename");
741 }
742 break;
743 }
744
745 int rfd = updown_runner->fds[0];
746 while (1)
747 {
748 ssize_t len = read(rfd, &status, sizeof(status));
749 if (len < sizeof(status))
750 {
751 if (len == -1 && errno == EINTR)
752 {
753 continue;
754 }
755 msg(M_ERR | M_ERRNO, "could not receive dns updown status");
756 }
757 break;
758 }
759
760out_free:
761 gc_free(&gc);
762 }
763
764 msg(M_INFO, "dns %s command exited with status %d", up ? "up" : "down", status);
765}
766
767#endif /* _WIN32 */
768
769void
771{
772 struct gc_arena gc = gc_new();
773
774 int i = 1;
775 struct dns_server *server = o->servers_prepull ? o->servers_prepull : o->servers;
776 while (server)
777 {
778 msg(D_SHOW_PARMS, " DNS server #%d:", i++);
779
780 for (int j = 0; j < server->addr_count; ++j)
781 {
782 const char *addr;
783 const char *fmt_port;
784 if (server->addr[j].family == AF_INET)
785 {
786 addr = print_in_addr_t(server->addr[j].in.a4.s_addr, IA_NET_ORDER, &gc);
787 fmt_port = " address = %s:%s";
788 }
789 else
790 {
791 addr = print_in6_addr(server->addr[j].in.a6, 0, &gc);
792 fmt_port = " address = [%s]:%s";
793 }
794
795 if (server->addr[j].port)
796 {
797 const char *port = print_in_port_t(server->addr[j].port, &gc);
798 msg(D_SHOW_PARMS, fmt_port, addr, port);
799 }
800 else
801 {
802 msg(D_SHOW_PARMS, " address = %s", addr);
803 }
804 }
805
806 if (server->dnssec)
807 {
808 msg(D_SHOW_PARMS, " dnssec = %s", dnssec_value(server->dnssec));
809 }
810
811 if (server->transport)
812 {
813 msg(D_SHOW_PARMS, " transport = %s", transport_value(server->transport));
814 }
815 if (server->sni)
816 {
817 msg(D_SHOW_PARMS, " sni = %s", server->sni);
818 }
819
820 struct dns_domain *domain = server->domains;
821 if (domain)
822 {
823 msg(D_SHOW_PARMS, " resolve domains:");
824 while (domain)
825 {
826 msg(D_SHOW_PARMS, " %s", domain->name);
827 domain = domain->next;
828 }
829 }
830
831 server = server->next;
832 }
833
834 struct dns_domain *search_domain = o->search_domains;
835 if (search_domain)
836 {
837 msg(D_SHOW_PARMS, " DNS search domains:");
838 while (search_domain)
839 {
840 msg(D_SHOW_PARMS, " %s", search_domain->name);
841 search_domain = search_domain->next;
842 }
843 }
844
845 gc_free(&gc);
846}
847
848void
849run_dns_up_down(bool up, struct options *o, const struct tuntap *tt, struct dns_updown_runner_info *duri)
850{
851 if (!o->dns_options.servers)
852 {
853 return;
854 }
855
856 /* Warn about adding servers of unsupported AF */
857 const struct dns_server *s = o->dns_options.servers;
858 while (up && s)
859 {
860 size_t bad_count = 0;
861 for (size_t i = 0; i < s->addr_count; ++i)
862 {
863 if ((s->addr[i].family == AF_INET6 && !tt->did_ifconfig_ipv6_setup)
864 || (s->addr[i].family == AF_INET && !tt->did_ifconfig_setup))
865 {
866 ++bad_count;
867 }
868 }
869 if (bad_count == s->addr_count)
870 {
871 msg(M_WARN, "DNS server %ld only has address(es) from a family "
872 "the tunnel is not configured for - it will not be reachable",
873 s->priority);
874 }
875 else if (bad_count)
876 {
877 msg(M_WARN, "DNS server %ld has address(es) from a family "
878 "the tunnel is not configured for", s->priority);
879 }
880 s = s->next;
881 }
882
883#ifdef _WIN32
884 run_up_down_service(up, o, tt);
885#else
886 run_up_down_command(up, o, tt, duri);
887#endif /* ifdef _WIN32 */
888}
void argv_msg(const int msglev, const struct argv *a)
Write the arguments stored in a struct argv via the msg() command.
Definition argv.c:243
void argv_free(struct argv *a)
Frees all memory allocations allocated by the struct argv related functions.
Definition argv.c:102
bool argv_printf(struct argv *argres, const char *format,...)
printf() variant which populates a struct argv.
Definition argv.c:440
struct argv argv_new(void)
Allocates a new struct argv and ensures it is initialised.
Definition argv.c:88
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Definition buffer.h:1097
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition buffer.h:361
static void gc_free(struct gc_arena *a)
Definition buffer.h:1033
static struct gc_arena gc_new(void)
Definition buffer.h:1025
bool dns_options_verify(int msglevel, const struct dns_options *o)
Checks validity of DNS options.
Definition dns.c:204
void dns_domain_list_append(struct dns_domain **entry, char **domains, struct gc_arena *gc)
Appends DNS domain parameters to a linked list.
Definition dns.c:148
static const char * dnssec_value(const enum dns_security dnssec)
Definition dns.c:316
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:849
void dns_options_postprocess_pull(struct dns_options *o)
Merges pulled DNS servers with static ones into an ordered list.
Definition dns.c:280
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
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:182
static void run_up_down_service(bool add, const struct options *o, const struct tuntap *tt)
Definition dns.c:397
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:356
static struct dns_server * clone_dns_servers(const struct dns_server *server, struct gc_arena *gc)
Definition dns.c:239
static struct dns_domain * clone_dns_domains(const struct dns_domain *domain, struct gc_arena *gc)
Definition dns.c:221
static const char * transport_value(const enum dns_server_transport transport)
Definition dns.c:335
bool dns_server_priority_parse(long *priority, const char *str, bool pulled)
Parses a string DNS server priority and validates it.
Definition dns.c:167
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:258
void show_dns_options(const struct dns_options *o)
Prints configured DNS options.
Definition dns.c:770
static bool dns_server_port_parse(in_port_t *port, char *port_str)
Parses a string as port and stores it.
Definition dns.c:48
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:273
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
dns_server_transport
Definition dns.h:38
@ DNS_TRANSPORT_PLAIN
Definition dns.h:40
@ DNS_TRANSPORT_UNSET
Definition dns.h:39
@ DNS_TRANSPORT_TLS
Definition dns.h:42
@ DNS_TRANSPORT_HTTPS
Definition dns.h:41
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:239
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition env_set.c:308
struct env_set * env_set_create(struct gc_arena *gc)
Definition env_set.c:157
#define D_SHOW_PARMS
Definition errlevel.h:96
#define M_INFO
Definition errlevel.h:55
static SERVICE_STATUS status
Definition interactive.c:52
@ 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:30
#define M_ERR
Definition error.h:105
#define msg(flags,...)
Definition error.h:144
#define M_WARN
Definition error.h:91
#define M_ERRNO
Definition error.h:94
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:541
bool platform_unlink(const char *filename)
Definition platform.c:488
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:49
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:87
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)
Definition socket.c:469
const char * print_in_port_t(in_port_t port, struct gc_arena *gc)
Definition socket.c:3043
const char * print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
Definition socket.c:3027
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
Definition socket.c:3007
#define IA_NET_ORDER
Definition socket.h:402
Definition argv.h:35
struct dns_domain * next
Definition dns.h:46
const char * name
Definition dns.h:47
struct dns_server * servers
Definition dns.h:82
const char * updown
Definition dns.h:84
struct dns_server * servers_prepull
Definition dns.h:81
bool user_set_updown
Definition dns.h:85
struct dns_domain * search_domains
Definition dns.h:80
struct in_addr a4
Definition dns.h:53
union dns_server_addr::@0 in
sa_family_t family
Definition dns.h:56
struct in6_addr a6
Definition dns.h:54
in_port_t port
Definition dns.h:57
struct dns_server_addr addr[8]
Definition dns.h:64
enum dns_security dnssec
Definition dns.h:66
struct dns_server * next
Definition dns.h:61
long priority
Definition dns.h:62
size_t addr_count
Definition dns.h:63
struct dns_domain * domains
Definition dns.h:65
enum dns_server_transport transport
Definition dns.h:67
const char * sni
Definition dns.h:68
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:117
char name[256]
Definition openvpn-msg.h:67
message_header_t header
nrpt_address_t addresses[NRPT_ADDR_NUM]
const char * tmp_dir
Definition options.h:466
HANDLE msg_channel
Definition options.h:692
struct dns_options dns_options
Definition options.h:312
Definition tun.h:178
DWORD adapter_index
Definition tun.h:228
bool did_ifconfig_ipv6_setup
if the internal variables related to ifconfig-ipv6 of this struct have been set up.
Definition tun.h:196
bool did_ifconfig_setup
if the internal variables related to ifconfig of this struct have been set up.
Definition tun.h:192
char * actual_name
Definition tun.h:202
unsigned short sa_family_t
Definition syshead.h:395
struct env_set * es
struct gc_arena gc
Definition test_ssl.c:155
bool send_msg_iservice(HANDLE pipe, const void *data, size_t size, ack_message_t *ack, const char *context)
Definition win32.c:1432