aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-05-28 22:45:15 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-05-29 01:23:24 +0200
commita1a1c1723b6423e43d71cfa52862fad9bbcd265b (patch)
tree13f43adf8bbd15da7eff9b383f84ed1da9357973
parentzinc: update copyright (diff)
downloadwireguard-monolithic-historical-a1a1c1723b6423e43d71cfa52862fad9bbcd265b.tar.xz
wireguard-monolithic-historical-a1a1c1723b6423e43d71cfa52862fad9bbcd265b.zip
tools: allow setting WG_ENDPOINT_RESOLUTION_RETRIES
-rw-r--r--src/tools/config.c26
-rw-r--r--src/tools/man/wg.83
2 files changed, 25 insertions, 4 deletions
diff --git a/src/tools/config.c b/src/tools/config.c
index d510ea7..db90228 100644
--- a/src/tools/config.c
+++ b/src/tools/config.c
@@ -174,11 +174,29 @@ static inline bool parse_ip(struct wgallowedip *allowedip, const char *value)
return true;
}
+static inline int parse_dns_retries(void)
+{
+ unsigned long ret;
+ char *retries = getenv("WG_ENDPOINT_RESOLUTION_RETRIES"), *end;
+
+ if (!retries)
+ return 15;
+ if (!strcmp(retries, "infinity"))
+ return -1;
+
+ ret = strtoul(retries, &end, 10);
+ if (*end || ret > INT_MAX) {
+ fprintf(stderr, "Unable to parse WG_ENDPOINT_RESOLUTION_RETRIES: `%s'\n", retries);
+ exit(1);
+ }
+ return (int)ret;
+}
+
static inline bool parse_endpoint(struct sockaddr *endpoint, const char *value)
{
char *mutable = strdup(value);
char *begin, *end;
- int ret;
+ int ret, retries = parse_dns_retries();
struct addrinfo *resolved;
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
@@ -219,11 +237,11 @@ static inline bool parse_endpoint(struct sockaddr *endpoint, const char *value)
*end++ = '\0';
}
- for (unsigned int timeout = 1000000;;) {
+ #define min(a, b) ((a) < (b) ? (a) : (b))
+ for (unsigned int timeout = 1000000;; timeout = min(20000000, timeout * 6 / 5)) {
ret = getaddrinfo(begin, end, &hints, &resolved);
if (!ret)
break;
- timeout = timeout * 3 / 2;
/* The set of return codes that are "permanent failures". All other possibilities are potentially transient.
*
* This is according to https://sourceware.org/glibc/wiki/NameResolver which states:
@@ -238,7 +256,7 @@ static inline bool parse_endpoint(struct sockaddr *endpoint, const char *value)
#ifdef EAI_NODATA
ret == EAI_NODATA ||
#endif
- timeout >= 90000000) {
+ (retries >= 0 && !retries--)) {
free(mutable);
fprintf(stderr, "%s: `%s'\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), value);
return false;
diff --git a/src/tools/man/wg.8 b/src/tools/man/wg.8
index 2013825..afff749 100644
--- a/src/tools/man/wg.8
+++ b/src/tools/man/wg.8
@@ -211,6 +211,9 @@ If set to \fIalways\fP, always print ANSI colorized output. If set to \fInever\f
.TP
.I WG_HIDE_KEYS
If set to \fInever\fP, then the pretty-printing \fBshow\fP sub-command will show private and preshared keys in the output. If set to \fIalways\fP, something invalid, or unset, then private and preshared keys will be printed as "(hidden)".
+.TP
+.I WG_ENDPOINT_RESOLUTION_RETRIES
+If set to an integer or to \fIinfinity\fP, DNS resolution for each peer's endpoint will be retried that many times for non-permanent errors, with an increasing delay between retries. If unset, the default is 15 retries.
.SH SEE ALSO
.BR ip (8),