]> git.ipfire.org Git - thirdparty/wireguard-tools.git/commitdiff
persistent keepalive: add userspace support
authorJason A. Donenfeld <Jason@zx2c4.com>
Fri, 8 Jul 2016 00:30:03 +0000 (02:30 +0200)
committerJason A. Donenfeld <Jason@zx2c4.com>
Fri, 8 Jul 2016 00:43:33 +0000 (02:43 +0200)
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
src/config.c
src/set.c
src/show.c
src/showconf.c

index 9066178979edfbf7b5d853114635d8afab9baa6d..c24aa8706b930eb876bd9f32c3f2d68a4adea25e 100644 (file)
@@ -182,6 +182,27 @@ static inline bool parse_endpoint(struct sockaddr_storage *endpoint, const char
        return true;
 }
 
+static inline bool parse_persistent_keepalive(__u16 *interval, const char *value)
+{
+       unsigned long ret;
+       char *end;
+
+       if (!strcasecmp(value, "off")) {
+               *interval = 0;
+               return true;
+       }
+
+       ret = strtoul(value, &end, 10);
+       if (!*value || *value == '-' || *end || (ret && (ret < 10 || ret > 3600))) {
+               fprintf(stderr, "The persistent keepalive interval must be 0/off or 10-3600. Found: `%s`\n", value);
+               return false;
+       }
+
+       *interval = (__u16)ret;
+       return true;
+}
+
+
 static inline bool parse_ipmasks(struct inflatable_device *buf, size_t peer_offset, const char *value)
 {
        struct wgpeer *peer;
@@ -263,6 +284,7 @@ static bool process_line(struct config_ctx *ctx, const char *line)
                ctx->is_peer_section = true;
                ctx->is_device_section = false;
                peer_from_offset(ctx->buf.dev, ctx->peer_offset)->replace_ipmasks = true;
+               peer_from_offset(ctx->buf.dev, ctx->peer_offset)->persistent_keepalive_interval = (__u16)-1;
                return true;
        }
 
@@ -288,6 +310,8 @@ static bool process_line(struct config_ctx *ctx, const char *line)
                        ret = parse_key(peer_from_offset(ctx->buf.dev, ctx->peer_offset)->public_key, value);
                else if (key_match("AllowedIPs"))
                        ret = parse_ipmasks(&ctx->buf, ctx->peer_offset, value);
+               else if (key_match("PersistentKeepalive"))
+                       ret = parse_persistent_keepalive(&peer_from_offset(ctx->buf.dev, ctx->peer_offset)->persistent_keepalive_interval, value);
                else
                        goto error;
        } else
@@ -476,6 +500,7 @@ bool config_read_cmd(struct wgdevice **device, char *argv[], int argc)
                                perror("use_space");
                                goto error;
                        }
+                       peer_from_offset(buf.dev, peer_offset)->persistent_keepalive_interval = (__u16)-1;
                        ++buf.dev->num_peers;
                        if (!parse_key(peer_from_offset(buf.dev, peer_offset)->public_key, argv[1]))
                                goto error;
@@ -501,6 +526,11 @@ bool config_read_cmd(struct wgdevice **device, char *argv[], int argc)
                        free(line);
                        argv += 2;
                        argc -= 2;
+               } else if (!strcmp(argv[0], "persistent-keepalive") && argc >= 2 && buf.dev->num_peers) {
+                       if (!parse_persistent_keepalive(&peer_from_offset(buf.dev, peer_offset)->persistent_keepalive_interval, argv[1]))
+                               goto error;
+                       argv += 2;
+                       argc -= 2;
                } else {
                        fprintf(stderr, "Invalid argument: %s\n", argv[0]);
                        goto error;
index f85162d09806e6b66215dd11e8810d565ed69c0d..c7656e8e1ea236a214aa085c614f92d82feaf2e8 100644 (file)
--- a/src/set.c
+++ b/src/set.c
@@ -13,7 +13,7 @@ int set_main(int argc, char *argv[])
        int ret = 1;
 
        if (argc < 3) {
-               fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [private-key <file path>] [peer <base64 public key> [remove] [endpoint <ip>:<port>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>]...] ]...\n", PROG_NAME, argv[0]);
+               fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [private-key <file path>] [peer <base64 public key> [remove] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>]...] ]...\n", PROG_NAME, argv[0]);
                return 1;
        }
 
index 1662751bc65115ab6d74040998a25b5bf8f322f1..792753491b26b84f21f0684813b5ec15b288afcd 100644 (file)
@@ -121,13 +121,11 @@ static char *endpoint(const struct sockaddr_storage *addr)
        return buf;
 }
 
-static char *ago(const struct timeval *t)
+static size_t pretty_time(char *buf, const size_t len, unsigned long long left)
 {
-       static char buf[1024];
-       unsigned long long left, years, days, hours, minutes, seconds;
        size_t offset = 0;
+       unsigned long long years, days, hours, minutes, seconds;
 
-       left = time(NULL) - t->tv_sec;
        years = left / (365 * 24 * 60 * 60);
        left = left % (365 * 24 * 60 * 60);
        days = left / (24 * 60 * 60);
@@ -138,15 +136,25 @@ static char *ago(const struct timeval *t)
        seconds = left % 60;
 
        if (years)
-               offset += snprintf(buf + offset, sizeof(buf) - offset, "%s%llu " TERMINAL_FG_CYAN "year%s" TERMINAL_RESET, offset ? ", " : "", years, years == 1 ? "" : "s");
+               offset += snprintf(buf + offset, len - offset, "%s%llu " TERMINAL_FG_CYAN "year%s" TERMINAL_RESET, offset ? ", " : "", years, years == 1 ? "" : "s");
        if (days)
-               offset += snprintf(buf + offset, sizeof(buf) - offset, "%s%llu " TERMINAL_FG_CYAN  "day%s" TERMINAL_RESET, offset ? ", " : "", days, days == 1 ? "" : "s");
+               offset += snprintf(buf + offset, len - offset, "%s%llu " TERMINAL_FG_CYAN  "day%s" TERMINAL_RESET, offset ? ", " : "", days, days == 1 ? "" : "s");
        if (hours)
-               offset += snprintf(buf + offset, sizeof(buf) - offset, "%s%llu " TERMINAL_FG_CYAN  "hour%s" TERMINAL_RESET, offset ? ", " : "", hours, hours == 1 ? "" : "s");
+               offset += snprintf(buf + offset, len - offset, "%s%llu " TERMINAL_FG_CYAN  "hour%s" TERMINAL_RESET, offset ? ", " : "", hours, hours == 1 ? "" : "s");
        if (minutes)
-               offset += snprintf(buf + offset, sizeof(buf) - offset, "%s%llu " TERMINAL_FG_CYAN "minute%s" TERMINAL_RESET, offset ? ", " : "", minutes, minutes == 1 ? "" : "s");
+               offset += snprintf(buf + offset, len - offset, "%s%llu " TERMINAL_FG_CYAN "minute%s" TERMINAL_RESET, offset ? ", " : "", minutes, minutes == 1 ? "" : "s");
        if (seconds)
-               offset += snprintf(buf + offset, sizeof(buf) - offset, "%s%llu " TERMINAL_FG_CYAN  "second%s" TERMINAL_RESET, offset ? ", " : "", seconds, seconds == 1 ? "" : "s");
+               offset += snprintf(buf + offset, len - offset, "%s%llu " TERMINAL_FG_CYAN  "second%s" TERMINAL_RESET, offset ? ", " : "", seconds, seconds == 1 ? "" : "s");
+
+       return offset;
+}
+
+static char *ago(const struct timeval *t)
+{
+       static char buf[1024];
+       size_t offset;
+
+       offset = pretty_time(buf, sizeof(buf), time(NULL) - t->tv_sec);
        if (offset)
                snprintf(buf + offset, sizeof(buf) - offset, " ago");
        else
@@ -155,6 +163,13 @@ static char *ago(const struct timeval *t)
        return buf;
 }
 
+static char *every(uint16_t seconds)
+{
+       static char buf[1024] = "every ";
+       pretty_time(buf + strlen("every "), sizeof(buf) - strlen("every "), seconds);
+       return buf;
+}
+
 static char *bytes(uint64_t b)
 {
        static char buf[1024];
@@ -176,7 +191,7 @@ static char *bytes(uint64_t b)
 static const char *COMMAND_NAME = NULL;
 static void show_usage(void)
 {
-       fprintf(stderr, "Usage: %s %s { <interface> | all | interfaces } [public-key | private-key | preshared-key | listen-port | peers | endpoints | allowed-ips | latest-handshake | bandwidth]\n", PROG_NAME, COMMAND_NAME);
+       fprintf(stderr, "Usage: %s %s { <interface> | all | interfaces } [public-key | private-key | preshared-key | listen-port | peers | endpoints | allowed-ips | latest-handshake | bandwidth | persistent-keepalive]\n", PROG_NAME, COMMAND_NAME);
 }
 
 static void pretty_print(struct wgdevice *device)
@@ -216,6 +231,8 @@ static void pretty_print(struct wgdevice *device)
                        terminal_printf("%s received, ", bytes(peer->rx_bytes));
                        terminal_printf("%s sent\n", bytes(peer->tx_bytes));
                }
+               if (peer->persistent_keepalive_interval)
+                       terminal_printf("  " TERMINAL_BOLD "persistent keepalive" TERMINAL_RESET ": %s\n", every(peer->persistent_keepalive_interval));
                if (i + 1 < device->num_peers)
                        terminal_printf("\n");
        }
@@ -275,6 +292,15 @@ static bool ugly_print(struct wgdevice *device, const char *param, bool with_int
                                printf("%s\t", device->interface);
                        printf("%s\t%" PRIu64 "\t%" PRIu64 "\n", key(peer->public_key), (uint64_t)peer->rx_bytes, (uint64_t)peer->tx_bytes);
                }
+       } else if (!strcmp(param, "persistent-keepalive")) {
+               for_each_wgpeer(device, peer, i) {
+                       if (with_interface)
+                               printf("%s\t", device->interface);
+                       if (peer->persistent_keepalive_interval)
+                               printf("%s\t%u\n", key(peer->public_key), peer->persistent_keepalive_interval);
+                       else
+                               printf("%s\toff\n", key(peer->public_key));
+               }
        } else if (!strcmp(param, "peers")) {
                for_each_wgpeer(device, peer, i) {
                        if (with_interface)
index faf2482cc0538cf6f8d4a0d3aa36797f15733adb..95d2e17b976cb4f433de8a02893dc756eb09f0f8 100644 (file)
@@ -91,6 +91,9 @@ int showconf_main(int argc, char *argv[])
                        }
                }
 
+               if (peer->persistent_keepalive_interval)
+                       printf("PersistentKeepalive = %u\n", peer->persistent_keepalive_interval);
+
                if (i + 1 < device->num_peers)
                        printf("\n");
        }