]> git.ipfire.org Git - thirdparty/wireguard-tools.git/commitdiff
wg: retry resolution except when fatal
authorJason A. Donenfeld <Jason@zx2c4.com>
Sun, 15 Oct 2017 20:52:38 +0000 (22:52 +0200)
committerJason A. Donenfeld <Jason@zx2c4.com>
Tue, 17 Oct 2017 17:26:07 +0000 (19:26 +0200)
The reference to this is <https://sourceware.org/glibc/wiki/NameResolver>,
which mentions:

"From the perspective of the application that calls getaddrinfo() it
perhaps doesn't matter that much since EAI_FAIL, EAI_NONAME and
EAI_NODATA are all permanent failure codes and the causes are all
permanent failures in the sense that there is no point in retrying
later."

This should cover more early-boot situations.

While we're at it, we clean up the logic a bit so that we don't have a
retry message on the final non-retrying attempt. We also peer into errno
when receiving EAI_SYSTEM, to report to the user what actually happened.

Also, fix the quoting back tick front tick mess.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
src/config.c
src/show.c
src/wg.c

index 9f3f990bb13002cf1c0f0b36efad33e0b6483b04..30e004c0e1dc6a0e947c7972878379d7377d8cf7 100644 (file)
@@ -51,7 +51,7 @@ static inline bool parse_port(uint16_t *port, uint32_t *flags, const char *value
 
        ret = getaddrinfo(NULL, value, &hints, &resolved);
        if (ret) {
-               fprintf(stderr, "%s: `%s`\n", gai_strerror(ret), value);
+               fprintf(stderr, "%s: `%s'\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), value);
                return false;
        }
 
@@ -63,7 +63,7 @@ static inline bool parse_port(uint16_t *port, uint32_t *flags, const char *value
                *port = ntohs(((struct sockaddr_in6 *)resolved->ai_addr)->sin6_port);
                ret = 0;
        } else
-               fprintf(stderr, "Neither IPv4 nor IPv6 address found: `%s`\n", value);
+               fprintf(stderr, "Neither IPv4 nor IPv6 address found: `%s'\n", value);
 
        freeaddrinfo(resolved);
        if (!ret)
@@ -98,7 +98,7 @@ static inline bool parse_fwmark(uint32_t *fwmark, uint32_t *flags, const char *v
 static inline bool parse_key(uint8_t key[static WG_KEY_LEN], const char *value)
 {
        if (!key_from_base64(key, value)) {
-               fprintf(stderr, "Key is not the correct length or format: `%s`\n", value);
+               fprintf(stderr, "Key is not the correct length or format: `%s'\n", value);
                return false;
        }
        return true;
@@ -115,7 +115,7 @@ static inline bool parse_ip(struct wgallowedip *allowedip, const char *value)
                        allowedip->family = AF_INET;
        }
        if (allowedip->family == AF_UNSPEC) {
-               fprintf(stderr, "Unable to parse IP address: `%s`\n", value);
+               fprintf(stderr, "Unable to parse IP address: `%s'\n", value);
                return false;
        }
        return true;
@@ -146,13 +146,13 @@ static inline bool parse_endpoint(struct sockaddr *endpoint, const char *value)
                end = strchr(mutable, ']');
                if (!end) {
                        free(mutable);
-                       fprintf(stderr, "Unable to find matching brace of endpoint: `%s`\n", value);
+                       fprintf(stderr, "Unable to find matching brace of endpoint: `%s'\n", value);
                        return false;
                }
                *end++ = '\0';
                if (*end++ != ':' || !*end) {
                        free(mutable);
-                       fprintf(stderr, "Unable to find port of endpoint: `%s`\n", value);
+                       fprintf(stderr, "Unable to find port of endpoint: `%s'\n", value);
                        return false;
                }
        } else {
@@ -160,32 +160,34 @@ static inline bool parse_endpoint(struct sockaddr *endpoint, const char *value)
                end = strrchr(mutable, ':');
                if (!end || !*(end + 1)) {
                        free(mutable);
-                       fprintf(stderr, "Unable to find port of endpoint: `%s`\n", value);
+                       fprintf(stderr, "Unable to find port of endpoint: `%s'\n", value);
                        return false;
                }
                *end++ = '\0';
        }
 
-       for (unsigned int timeout = 1000000; timeout < 90000000; timeout = timeout * 3 / 2) {
+       for (unsigned int timeout = 1000000;;) {
                ret = getaddrinfo(begin, end, &hints, &resolved);
-               if (ret != EAI_AGAIN)
+               if (!ret)
                        break;
-               fprintf(stderr, "%s: `%s`. Trying again in %.2f seconds...\n", gai_strerror(ret), value, timeout / 1000000.0);
+               timeout = timeout * 3 / 2;
+               /* The set of return codes that are "permanent failures". All other possibilities are potentially transient. */
+               if (ret == EAI_NONAME || ret == EAI_FAIL || ret == EAI_NODATA || timeout >= 90000000) {
+                       free(mutable);
+                       fprintf(stderr, "%s: `%s'\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), value);
+                       return false;
+               }
+               fprintf(stderr, "%s: `%s'. Trying again in %.2f seconds...\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), value, timeout / 1000000.0);
                usleep(timeout);
        }
 
-       if (ret != 0) {
-               free(mutable);
-               fprintf(stderr, "%s: `%s`\n", gai_strerror(ret), value);
-               return false;
-       }
        if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(struct sockaddr_in)) ||
            (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(struct sockaddr_in6)))
                memcpy(endpoint, resolved->ai_addr, resolved->ai_addrlen);
        else {
                freeaddrinfo(resolved);
                free(mutable);
-               fprintf(stderr, "Neither IPv4 nor IPv6 address found: `%s`\n", value);
+               fprintf(stderr, "Neither IPv4 nor IPv6 address found: `%s'\n", value);
                return false;
        }
        freeaddrinfo(resolved);
@@ -206,7 +208,7 @@ static inline bool parse_persistent_keepalive(uint16_t *interval, uint32_t *flag
 
        ret = strtoul(value, &end, 10);
        if (!*value || *value == '-' || *end || ret > 65535) {
-               fprintf(stderr, "The persistent keepalive interval must be 0/off or 1-65535. Found: `%s`\n", value);
+               fprintf(stderr, "The persistent keepalive interval must be 0/off or 1-65535. Found: `%s'\n", value);
                return false;
        }
 
@@ -431,7 +433,7 @@ static bool read_keyfile(char dst[WG_KEY_LEN_BASE64], const char *path)
 
        while ((c = getc(f)) != EOF) {
                if (!isspace(c)) {
-                       fprintf(stderr, "Found trailing character in key file: `%c`\n", c);
+                       fprintf(stderr, "Found trailing character in key file: `%c'\n", c);
                        goto out;
                }
        }
index 476d002df2240e878b826f7eff2bf745ecae111f..4203494166f695d0c775c678700d8905c56789d0 100644 (file)
@@ -352,7 +352,7 @@ static bool ugly_print(struct wgdevice *device, const char *param, bool with_int
        } else if (!strcmp(param, "dump"))
                dump_print(device, with_interface);
        else {
-               fprintf(stderr, "Invalid parameter: `%s`\n", param);
+               fprintf(stderr, "Invalid parameter: `%s'\n", param);
                show_usage();
                return false;
        }
index e1d9a6053d09d494150ab907280be07a24e19ff9..c340d665ac1be902d3b537afb45741e63e710205 100644 (file)
--- a/src/wg.c
+++ b/src/wg.c
@@ -14,7 +14,7 @@ static const struct {
        const char *description;
 } subcommands[] = {
        { "show", show_main, "Shows the current configuration and device information" },
-       { "showconf", showconf_main, "Shows the current configuration of a given WireGuard interface, for use with `setconf`" },
+       { "showconf", showconf_main, "Shows the current configuration of a given WireGuard interface, for use with `setconf'" },
        { "set", set_main, "Change the current configuration, add peers, remove peers, or change peers" },
        { "setconf", setconf_main, "Applies a configuration file to a WireGuard interface" },
        { "addconf", setconf_main, "Appends a configuration file to a WireGuard interface" },
@@ -61,7 +61,7 @@ findsubcommand:
                goto findsubcommand;
        }
 
-       fprintf(stderr, "Invalid subcommand: `%s`\n", argv[1]);
+       fprintf(stderr, "Invalid subcommand: `%s'\n", argv[1]);
        show_usage(stderr);
        return 1;
 }