persistent keepalive: add userspace support
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
		
							parent
							
								
									2a9625acf6
								
							
						
					
					
						commit
						fc743caf3b
					
				
							
								
								
									
										30
									
								
								src/config.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/config.c
									
									
									
									
									
								
							@ -182,6 +182,27 @@ static inline bool parse_endpoint(struct sockaddr_storage *endpoint, const char
 | 
				
			|||||||
	return true;
 | 
						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)
 | 
					static inline bool parse_ipmasks(struct inflatable_device *buf, size_t peer_offset, const char *value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wgpeer *peer;
 | 
						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_peer_section = true;
 | 
				
			||||||
		ctx->is_device_section = false;
 | 
							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)->replace_ipmasks = true;
 | 
				
			||||||
 | 
							peer_from_offset(ctx->buf.dev, ctx->peer_offset)->persistent_keepalive_interval = (__u16)-1;
 | 
				
			||||||
		return true;
 | 
							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);
 | 
								ret = parse_key(peer_from_offset(ctx->buf.dev, ctx->peer_offset)->public_key, value);
 | 
				
			||||||
		else if (key_match("AllowedIPs"))
 | 
							else if (key_match("AllowedIPs"))
 | 
				
			||||||
			ret = parse_ipmasks(&ctx->buf, ctx->peer_offset, value);
 | 
								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
 | 
							else
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
@ -476,6 +500,7 @@ bool config_read_cmd(struct wgdevice **device, char *argv[], int argc)
 | 
				
			|||||||
				perror("use_space");
 | 
									perror("use_space");
 | 
				
			||||||
				goto error;
 | 
									goto error;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								peer_from_offset(buf.dev, peer_offset)->persistent_keepalive_interval = (__u16)-1;
 | 
				
			||||||
			++buf.dev->num_peers;
 | 
								++buf.dev->num_peers;
 | 
				
			||||||
			if (!parse_key(peer_from_offset(buf.dev, peer_offset)->public_key, argv[1]))
 | 
								if (!parse_key(peer_from_offset(buf.dev, peer_offset)->public_key, argv[1]))
 | 
				
			||||||
				goto error;
 | 
									goto error;
 | 
				
			||||||
@ -501,6 +526,11 @@ bool config_read_cmd(struct wgdevice **device, char *argv[], int argc)
 | 
				
			|||||||
			free(line);
 | 
								free(line);
 | 
				
			||||||
			argv += 2;
 | 
								argv += 2;
 | 
				
			||||||
			argc -= 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 {
 | 
							} else {
 | 
				
			||||||
			fprintf(stderr, "Invalid argument: %s\n", argv[0]);
 | 
								fprintf(stderr, "Invalid argument: %s\n", argv[0]);
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ int set_main(int argc, char *argv[])
 | 
				
			|||||||
	int ret = 1;
 | 
						int ret = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (argc < 3) {
 | 
						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;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										46
									
								
								src/show.c
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								src/show.c
									
									
									
									
									
								
							@ -121,13 +121,11 @@ static char *endpoint(const struct sockaddr_storage *addr)
 | 
				
			|||||||
	return buf;
 | 
						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;
 | 
						size_t offset = 0;
 | 
				
			||||||
 | 
						unsigned long long years, days, hours, minutes, seconds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	left = time(NULL) - t->tv_sec;
 | 
					 | 
				
			||||||
	years = left / (365 * 24 * 60 * 60);
 | 
						years = left / (365 * 24 * 60 * 60);
 | 
				
			||||||
	left = left % (365 * 24 * 60 * 60);
 | 
						left = left % (365 * 24 * 60 * 60);
 | 
				
			||||||
	days = left / (24 * 60 * 60);
 | 
						days = left / (24 * 60 * 60);
 | 
				
			||||||
@ -138,15 +136,25 @@ static char *ago(const struct timeval *t)
 | 
				
			|||||||
	seconds = left % 60;
 | 
						seconds = left % 60;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (years)
 | 
						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)
 | 
						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)
 | 
						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)
 | 
						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)
 | 
						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)
 | 
						if (offset)
 | 
				
			||||||
		snprintf(buf + offset, sizeof(buf) - offset, " ago");
 | 
							snprintf(buf + offset, sizeof(buf) - offset, " ago");
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
@ -155,6 +163,13 @@ static char *ago(const struct timeval *t)
 | 
				
			|||||||
	return buf;
 | 
						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 *bytes(uint64_t b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static char buf[1024];
 | 
						static char buf[1024];
 | 
				
			||||||
@ -176,7 +191,7 @@ static char *bytes(uint64_t b)
 | 
				
			|||||||
static const char *COMMAND_NAME = NULL;
 | 
					static const char *COMMAND_NAME = NULL;
 | 
				
			||||||
static void show_usage(void)
 | 
					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)
 | 
					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 received, ", bytes(peer->rx_bytes));
 | 
				
			||||||
			terminal_printf("%s sent\n", bytes(peer->tx_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)
 | 
							if (i + 1 < device->num_peers)
 | 
				
			||||||
			terminal_printf("\n");
 | 
								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", device->interface);
 | 
				
			||||||
			printf("%s\t%" PRIu64 "\t%" PRIu64 "\n", key(peer->public_key), (uint64_t)peer->rx_bytes, (uint64_t)peer->tx_bytes);
 | 
								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")) {
 | 
						} else if (!strcmp(param, "peers")) {
 | 
				
			||||||
		for_each_wgpeer(device, peer, i) {
 | 
							for_each_wgpeer(device, peer, i) {
 | 
				
			||||||
			if (with_interface)
 | 
								if (with_interface)
 | 
				
			||||||
 | 
				
			|||||||
@ -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)
 | 
							if (i + 1 < device->num_peers)
 | 
				
			||||||
			printf("\n");
 | 
								printf("\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user