52 unsigned long tmp = strtoul(port_str, &endptr, 10);
53 if (errno || *endptr !=
'\0' || tmp == 0 || tmp > UINT16_MAX)
69 char addrcopy[INET6_ADDRSTRLEN] = { 0 };
74 char *first_colon = strchr(addr,
':');
75 char *last_colon = strrchr(addr,
':');
77 if (!first_colon || first_colon == last_colon)
86 copylen = first_colon - addr;
96 char *bracket = last_colon - 1;
101 copylen = bracket - addr;
109 if (copylen >=
sizeof(addrcopy))
113 strncpy(addrcopy, addr, copylen);
117 struct addrinfo *ai = NULL;
128 if (ai->ai_family == AF_INET)
130 struct sockaddr_in *sin = (
struct sockaddr_in *)ai->ai_addr;
135 struct sockaddr_in6 *sin6 = (
struct sockaddr_in6 *)ai->ai_addr;
153 entry = &((*entry)->next);
159 char *domain = *domains++;
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)
198 (*entry)->next = obj;
219 msg(msglevel,
"ERROR: dns server %ld does not have an address assigned",
223 server = server->
next;
238 *new_domain = *domain;
239 new_entry = &new_domain->
next;
240 domain = domain->
next;
256 *new_server = *server;
258 new_entry = &new_server->
next;
259 server = server->
next;
270 memset(&clone, 0,
sizeof(clone));
295 while (server && server_pp)
301 server_pp->
next = server;
309 server_pp = server_pp->
next;
311 entry = &server->
next;
370 size_t term_size = nrpt_domains ? 2 : 1;
371 size_t leading_dot = nrpt_domains ? 1 : 0;
374 memset(dst, 0, dst_size);
378 size_t len = strlen(src->
name);
379 if (offset + leading_dot + len + term_size > dst_size)
381 msg(
M_WARN,
"WARNING: %s truncated", what);
385 *(dst + offset - 1) =
'\0';
392 *(dst + offset++) =
'.';
394 strncpy(dst + offset, src->
name, len);
400 *(dst + offset++) =
',';
417 msg(
M_WARN,
"WARNING: setting DNS failed, no compatible server profile");
422 bool only_standard_server_ports =
true;
427 only_standard_server_ports =
false;
432 && only_standard_server_ports)
437 server = server->
next;
461 msg(
M_WARN,
"WARNING: could not convert dns server address");
471 msg(
D_LOW,
"%s NRPT DNS%s%s on '%s' (if_index = %d) using service",
472 (add ?
"Setting" :
"Deleting"), nrpt.
resolve_domains[0] != 0 ?
", resolve domains" :
"",
481setenv_dns_option(
struct env_set *
es,
const char *format,
int i,
int j,
const char *value)
484 bool name_ok =
false;
488 const int ret = snprintf(
name,
sizeof(
name), format, i);
489 name_ok = (ret > 0 && ret <
sizeof(
name));
493 const int ret = snprintf(
name,
sizeof(
name), format, i, j);
494 name_ok = (ret > 0 && ret <
sizeof(
name));
499 msg(
M_WARN,
"WARNING: dns option setenv name buffer overflow");
515 setenv_dns_option(
es,
"dns_search_domain_%d", i, -1, d->
name);
518 for (i = 1, s = o->
servers; s != NULL; i++, s = s->
next)
524 setenv_dns_option(
es,
"dns_server_%d_address_%d", i, j + 1,
529 setenv_dns_option(
es,
"dns_server_%d_address_%d", i, j + 1,
534 setenv_dns_option(
es,
"dns_server_%d_port_%d", i, j + 1,
541 for (j = 1, d = s->
domains; d != NULL; j++, d = d->
next)
543 setenv_dns_option(
es,
"dns_server_%d_resolve_domain_%d", i, j, d->name);
558 setenv_dns_option(
es,
"dns_server_%d_sni", i, -1, s->
sni);
569 setenv_str(
es,
"script_type", up ?
"dns-up" :
"dns-down");
570 setenv_dns_options(o,
es);
574do_run_up_down_command(
bool up,
const char *vars_file,
const struct dns_options *o,
587 updown_env_set(up, o, tt,
es);
607run_updown_runner(
bool up,
struct options *o,
const struct tuntap *tt,
612 if (pipe(dns_pipe_fd) != 0 || pipe(ack_pipe_fd) != 0)
617 updown_runner->pid = fork();
618 if (updown_runner->pid == -1)
621 close(dns_pipe_fd[0]);
622 close(dns_pipe_fd[1]);
623 close(ack_pipe_fd[0]);
624 close(ack_pipe_fd[1]);
627 else if (updown_runner->pid > 0)
630 close(dns_pipe_fd[0]);
631 close(ack_pipe_fd[1]);
632 updown_runner->
fds[0] = ack_pipe_fd[0];
633 updown_runner->
fds[1] = dns_pipe_fd[1];
638 for (
int fd = 3; fd < 100; ++fd)
640 if (fd != dns_pipe_fd[0] && fd != ack_pipe_fd[1])
652 signal(SIGPIPE, SIG_IGN);
659 ssize_t rlen =
read(dns_pipe_fd[0], &path,
sizeof(path));
662 if (rlen == -1 && errno == EINTR)
666 close(dns_pipe_fd[0]);
667 close(ack_pipe_fd[1]);
671 path[
sizeof(path) - 1] =
'\0';
672 int res = do_run_up_down_command(up, path, &o->
dns_options, tt);
678 ssize_t wlen =
write(ack_pipe_fd[1], &res,
sizeof(res));
679 if ((wlen == -1 && errno != EINTR) || wlen < (ssize_t)
sizeof(res))
682 close(dns_pipe_fd[0]);
683 close(ack_pipe_fd[1]);
686 else if (wlen ==
sizeof(res))
700run_up_down_command(
bool up,
struct options *o,
const struct tuntap *tt,
714 status = do_run_up_down_command(up, NULL, dns, tt);
718 if (updown_runner->pid < 1)
721 if (!run_updown_runner(up, o, tt, updown_runner))
731 msg(
M_ERR,
"could not create dns vars file");
739 int wfd = updown_runner->
fds[1];
740 ssize_t dvf_size = strlen(dvf) + 1;
743 ssize_t len =
write(wfd, dvf, dvf_size);
746 if (len == -1 && errno == EINTR)
755 int rfd = updown_runner->
fds[0];
759 if (len < (ssize_t)
sizeof(
status))
761 if (len == -1 && errno == EINTR)
774 msg(
M_INFO,
"dns %s command exited with status %d", up ?
"up" :
"down",
status);
793 const char *fmt_port;
797 fmt_port =
" address = %s:%s";
802 fmt_port =
" address = [%s]:%s";
837 domain = domain->
next;
841 server = server->
next;
848 while (search_domain)
851 search_domain = search_domain->
next;
879 size_t bad_count = 0;
891 "DNS server %ld only has address(es) from a family "
892 "the tunnel is not configured for - it will not be reachable",
898 "DNS server %ld has address(es) from a family "
899 "the tunnel is not configured for",
908 run_up_down_command(up, o, tt, duri);
void argv_msg(const msglvl_t msglevel, const struct argv *a)
Write the arguments stored in a struct argv via the msg() command.
void argv_free(struct argv *a)
Frees all memory allocations allocated by the struct argv related functions.
bool argv_printf(struct argv *argres, const char *format,...)
printf() variant which populates a struct argv.
struct argv argv_new(void)
Allocates a new struct argv and ensures it is initialised.
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
static void strncpynt(char *dest, const char *src, size_t maxlen)
static void gc_free(struct gc_arena *a)
static struct gc_arena gc_new(void)
bool dns_options_verify(msglvl_t msglevel, const struct dns_options *o)
Checks validity of DNS options.
static const char * dnssec_value(const enum dns_security dnssec)
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.
void dns_options_postprocess_pull(struct dns_options *o)
Merges pulled DNS servers with static ones into an ordered list.
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...
bool dns_domain_list_append(struct dns_domain **entry, char **domains, struct gc_arena *gc)
Appends safe DNS domain parameters to a linked list.
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.
static void run_up_down_service(bool add, const struct options *o, const struct tuntap *tt)
static void make_domain_list(const char *what, const struct dns_domain *src, bool nrpt_domains, char *dst, size_t dst_size)
static struct dns_server * clone_dns_servers(const struct dns_server *server, struct gc_arena *gc)
static struct dns_domain * clone_dns_domains(const struct dns_domain *domain, struct gc_arena *gc)
static const char * transport_value(const enum dns_server_transport transport)
bool dns_server_priority_parse(long *priority, const char *str, bool pulled)
Parses a string DNS server priority and validates it.
struct dns_options clone_dns_options(const struct dns_options *o, struct gc_arena *gc)
Makes a deep copy of the passed DNS options.
void show_dns_options(const struct dns_options *o)
Prints configured DNS options.
static bool dns_server_port_parse(in_port_t *port, char *port_str)
Parses a string as port and stores it.
void dns_options_preprocess_pull(struct dns_options *o)
Saves and resets the server options, so that pulled ones don't mix in.
static bool dns_updown_user_set(const struct dns_options *o)
Returns whether dns-updown is user defined.
static bool dns_updown_forced(const struct dns_options *o)
Returns whether dns-updown is forced to run.
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.
void setenv_str(struct env_set *es, const char *name, const char *value)
struct env_set * env_set_create(struct gc_arena *gc)
static SERVICE_STATUS status
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.
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.
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)
struct dns_server * servers
struct dhcp_options from_dhcp
struct dns_server * servers_prepull
enum dns_updown_flags updown_flags
struct dns_domain * search_domains
union dns_server_addr::@0 in
struct dns_server_addr addr[8]
struct dns_domain * domains
enum dns_server_transport transport
Garbage collection arena used to keep track of dynamically allocated memory.
char resolve_domains[512]
nrpt_address_t addresses[NRPT_ADDR_NUM]
struct tuntap_options tuntap_options
struct dns_options dns_options
bool did_ifconfig_ipv6_setup
if the internal variables related to ifconfig-ipv6 of this struct have been set up.
bool did_ifconfig_setup
if the internal variables related to ifconfig of this struct have been set up.
unsigned short sa_family_t
#define IPW32_SET_ADAPTIVE
#define IPW32_SET_DHCP_MASQ
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.