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 const char *first_colon = strchr(addr,
':');
75 const char *last_colon = strrchr(addr,
':');
77 if (!first_colon || first_colon == last_colon)
86 copylen = first_colon - addr;
96 const 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 = %lu) using service",
472 (add ?
"Setting" :
"Deleting"), nrpt.
resolve_domains[0] != 0 ?
", resolve domains" :
"",
481#if defined(__GNUC__) || defined(__clang__)
482#pragma GCC diagnostic push
483#pragma GCC diagnostic ignored "-Wsign-compare"
487setenv_dns_option(
struct env_set *
es,
const char *format,
int i,
int j,
const char *value)
490 bool name_ok =
false;
503 msg(
M_WARN,
"WARNING: dns option setenv name buffer overflow");
519 setenv_dns_option(
es,
"dns_search_domain_%d", i, -1, d->
name);
522 for (i = 1, s = o->
servers; s != NULL; i++, s = s->
next)
528 setenv_dns_option(
es,
"dns_server_%d_address_%d", i, j + 1,
533 setenv_dns_option(
es,
"dns_server_%d_address_%d", i, j + 1,
538 setenv_dns_option(
es,
"dns_server_%d_port_%d", i, j + 1,
545 for (j = 1, d = s->
domains; d != NULL; j++, d = d->
next)
547 setenv_dns_option(
es,
"dns_server_%d_resolve_domain_%d", i, j, d->name);
562 setenv_dns_option(
es,
"dns_server_%d_sni", i, -1, s->
sni);
569#if defined(__GNUC__) || defined(__clang__)
570#pragma GCC diagnostic pop
577 setenv_str(
es,
"script_type", up ?
"dns-up" :
"dns-down");
578 setenv_dns_options(o,
es);
582do_run_up_down_command(
bool up,
const char *vars_file,
const struct dns_options *o,
595 updown_env_set(up, o, tt,
es);
615run_updown_runner(
bool up,
struct options *o,
const struct tuntap *tt,
620 if (pipe(dns_pipe_fd) != 0 || pipe(ack_pipe_fd) != 0)
625 updown_runner->pid = fork();
626 if (updown_runner->pid == -1)
629 close(dns_pipe_fd[0]);
630 close(dns_pipe_fd[1]);
631 close(ack_pipe_fd[0]);
632 close(ack_pipe_fd[1]);
635 else if (updown_runner->pid > 0)
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];
646 for (
int fd = 3; fd < 100; ++fd)
648 if (fd != dns_pipe_fd[0] && fd != ack_pipe_fd[1])
660 signal(SIGPIPE, SIG_IGN);
667 ssize_t rlen =
read(dns_pipe_fd[0], &path,
sizeof(path));
670 if (rlen == -1 && errno == EINTR)
674 close(dns_pipe_fd[0]);
675 close(ack_pipe_fd[1]);
679 path[
sizeof(path) - 1] =
'\0';
680 int res = do_run_up_down_command(up, path, &o->
dns_options, tt);
686 ssize_t wlen =
write(ack_pipe_fd[1], &res,
sizeof(res));
687 if ((wlen == -1 && errno != EINTR) || wlen < (ssize_t)
sizeof(res))
690 close(dns_pipe_fd[0]);
691 close(ack_pipe_fd[1]);
694 else if (wlen ==
sizeof(res))
708run_up_down_command(
bool up,
struct options *o,
const struct tuntap *tt,
722 status = do_run_up_down_command(up, NULL, dns, tt);
726 if (updown_runner->pid < 1)
729 if (!run_updown_runner(up, o, tt, updown_runner))
739 msg(
M_ERR,
"could not create dns vars file");
747 int wfd = updown_runner->
fds[1];
748 ssize_t dvf_size = strlen(dvf) + 1;
751 ssize_t len =
write(wfd, dvf, dvf_size);
754 if (len == -1 && errno == EINTR)
763 int rfd = updown_runner->
fds[0];
767 if (len < (ssize_t)
sizeof(
status))
769 if (len == -1 && errno == EINTR)
782 msg(
M_INFO,
"dns %s command exited with status %d", up ?
"up" :
"down",
status);
798 for (
size_t j = 0; j < server->
addr_count; ++j)
801 const char *fmt_port;
805 fmt_port =
" address = %s:%s";
810 fmt_port =
" address = [%s]:%s";
845 domain = domain->
next;
849 server = server->
next;
856 while (search_domain)
859 search_domain = search_domain->
next;
887 size_t bad_count = 0;
899 "DNS server %ld only has address(es) from a family "
900 "the tunnel is not configured for - it will not be reachable",
906 "DNS server %ld has address(es) from a family "
907 "the tunnel is not configured for",
916 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.
bool checked_snprintf(char *str, size_t size, const char *format,...)
Like snprintf() but returns an boolean.
#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 bool dns_server_port_parse(in_port_t *port, const char *port_str)
Parses a string as port and stores it.
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.
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.