git: 785abf57ab46 - stable/14 - Merge commit '2a7e45eef31292cf9dd82caf3346eb2acb5b6225'

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Mon, 21 Jul 2025 02:13:44 UTC
The branch stable/14 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=785abf57ab46cd890e5f5efc05d897b27edb2f35

commit 785abf57ab46cd890e5f5efc05d897b27edb2f35
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-05-21 01:36:07 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-07-21 02:12:24 +0000

    Merge commit '2a7e45eef31292cf9dd82caf3346eb2acb5b6225'
    
    Update wireguard-tools to the latest version, which has some stubbed out support
    for incremental Allowed-IPs updates that we would need to add kernel support
    for.
    
    (cherry picked from commit 137de4b34d45192985e21f6d6163533da547fbac)
---
 contrib/wireguard-tools/config.c      | 23 +++++++++++++++++++++++
 contrib/wireguard-tools/containers.h  |  5 +++++
 contrib/wireguard-tools/ipc-freebsd.h |  5 +++++
 contrib/wireguard-tools/ipc-uapi.h    |  2 +-
 contrib/wireguard-tools/man/wg.8      |  8 ++++++--
 contrib/wireguard-tools/set.c         |  2 +-
 contrib/wireguard-tools/show.c        |  4 ++--
 contrib/wireguard-tools/version.h     |  2 +-
 8 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/contrib/wireguard-tools/config.c b/contrib/wireguard-tools/config.c
index 81ccb479c367..6b8aa58700ce 100644
--- a/contrib/wireguard-tools/config.c
+++ b/contrib/wireguard-tools/config.c
@@ -337,6 +337,20 @@ static bool validate_netmask(struct wgallowedip *allowedip)
 	return true;
 }
 
+static inline void parse_ip_prefix(struct wgpeer *peer, uint32_t *flags, char **mask)
+{
+	/* If the IP is prefixed with either '+' or '-' consider this an
+	 * incremental change. Disable WGPEER_REPLACE_ALLOWEDIPS. */
+	switch ((*mask)[0]) {
+	case '-':
+		*flags |= WGALLOWEDIP_REMOVE_ME;
+		/* fall through */
+	case '+':
+		peer->flags &= ~WGPEER_REPLACE_ALLOWEDIPS;
+		++(*mask);
+	}
+}
+
 static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **last_allowedip, const char *value)
 {
 	struct wgallowedip *allowedip = *last_allowedip, *new_allowedip;
@@ -353,10 +367,18 @@ static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **la
 	}
 	sep = mutable;
 	while ((mask = strsep(&sep, ","))) {
+		uint32_t flags = 0;
 		unsigned long cidr;
 		char *end, *ip;
 
+		parse_ip_prefix(peer, &flags, &mask);
+
 		saved_entry = strdup(mask);
+		if (!saved_entry) {
+			perror("strdup");
+			free(mutable);
+			return false;
+		}
 		ip = strsep(&mask, "/");
 
 		new_allowedip = calloc(1, sizeof(*new_allowedip));
@@ -387,6 +409,7 @@ static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **la
 		else
 			goto err;
 		new_allowedip->cidr = cidr;
+		new_allowedip->flags = flags;
 
 		if (!validate_netmask(new_allowedip))
 			fprintf(stderr, "Warning: AllowedIP has nonzero host part: %s/%s\n", ip, mask);
diff --git a/contrib/wireguard-tools/containers.h b/contrib/wireguard-tools/containers.h
index a82e8ddee46a..8fd813aff342 100644
--- a/contrib/wireguard-tools/containers.h
+++ b/contrib/wireguard-tools/containers.h
@@ -28,6 +28,10 @@ struct timespec64 {
 	int64_t tv_nsec;
 };
 
+enum {
+	WGALLOWEDIP_REMOVE_ME = 1U << 0,
+};
+
 struct wgallowedip {
 	uint16_t family;
 	union {
@@ -35,6 +39,7 @@ struct wgallowedip {
 		struct in6_addr ip6;
 	};
 	uint8_t cidr;
+	uint32_t flags;
 	struct wgallowedip *next_allowedip;
 };
 
diff --git a/contrib/wireguard-tools/ipc-freebsd.h b/contrib/wireguard-tools/ipc-freebsd.h
index 446f13cacac2..58e5e71ce5cb 100644
--- a/contrib/wireguard-tools/ipc-freebsd.h
+++ b/contrib/wireguard-tools/ipc-freebsd.h
@@ -307,6 +307,11 @@ static int kernel_set_device(struct wgdevice *dev)
 			nvl_aips[j] = nvlist_create(0);
 			if (!nvl_aips[j])
 				goto err_peer;
+			if (aip->flags) {
+				//TODO: implement me
+				ret = -EOPNOTSUPP;
+				goto err_peer;
+			}
 			nvlist_add_number(nvl_aips[j], "cidr", aip->cidr);
 			if (aip->family == AF_INET)
 				nvlist_add_binary(nvl_aips[j], "ipv4", &aip->ip4, sizeof(aip->ip4));
diff --git a/contrib/wireguard-tools/ipc-uapi.h b/contrib/wireguard-tools/ipc-uapi.h
index f582916ecc9f..1d8a2710250a 100644
--- a/contrib/wireguard-tools/ipc-uapi.h
+++ b/contrib/wireguard-tools/ipc-uapi.h
@@ -89,7 +89,7 @@ static int userspace_set_device(struct wgdevice *dev)
 					continue;
 			} else
 				continue;
-			fprintf(f, "allowed_ip=%s/%d\n", ip, allowedip->cidr);
+			fprintf(f, "allowed_ip=%s%s/%d\n", (allowedip->flags & WGALLOWEDIP_REMOVE_ME) ? "-" : "", ip, allowedip->cidr);
 		}
 	}
 	fprintf(f, "\n");
diff --git a/contrib/wireguard-tools/man/wg.8 b/contrib/wireguard-tools/man/wg.8
index 79845391ec02..a0fc04c04cf1 100644
--- a/contrib/wireguard-tools/man/wg.8
+++ b/contrib/wireguard-tools/man/wg.8
@@ -55,7 +55,7 @@ transfer-rx, transfer-tx, persistent-keepalive.
 Shows the current configuration of \fI<interface>\fP in the format described
 by \fICONFIGURATION FILE FORMAT\fP below.
 .TP
-\fBset\fP \fI<interface>\fP [\fIlisten-port\fP \fI<port>\fP] [\fIfwmark\fP \fI<fwmark>\fP] [\fIprivate-key\fP \fI<file-path>\fP] [\fIpeer\fP \fI<base64-public-key>\fP [\fIremove\fP] [\fIpreshared-key\fP \fI<file-path>\fP] [\fIendpoint\fP \fI<ip>:<port>\fP] [\fIpersistent-keepalive\fP \fI<interval seconds>\fP] [\fIallowed-ips\fP \fI<ip1>/<cidr1>\fP[,\fI<ip2>/<cidr2>\fP]...] ]...
+\fBset\fP \fI<interface>\fP [\fIlisten-port\fP \fI<port>\fP] [\fIfwmark\fP \fI<fwmark>\fP] [\fIprivate-key\fP \fI<file-path>\fP] [\fIpeer\fP \fI<base64-public-key>\fP [\fIremove\fP] [\fIpreshared-key\fP \fI<file-path>\fP] [\fIendpoint\fP \fI<ip>:<port>\fP] [\fIpersistent-keepalive\fP \fI<interval seconds>\fP] [\fIallowed-ips\fP \fI[+|-]<ip1>/<cidr1>\fP[,\fI[+|-]<ip2>/<cidr2>\fP]...] ]...
 Sets configuration values for the specified \fI<interface>\fP. Multiple
 \fIpeer\fPs may be specified, and if the \fIremove\fP argument is given
 for a peer, that peer is removed, not configured. If \fIlisten-port\fP
@@ -72,7 +72,11 @@ the device. The use of \fIpreshared-key\fP is optional, and may be omitted;
 it adds an additional layer of symmetric-key cryptography to be mixed into
 the already existing public-key cryptography, for post-quantum resistance.
 If \fIallowed-ips\fP is specified, but the value is the empty string, all
-allowed ips are removed from the peer. The use of \fIpersistent-keepalive\fP
+allowed ips are removed from the peer. By default, \fIallowed-ips\fP replaces
+a peer's allowed ips. If + or - is prepended to any of the ips then
+the update is incremental; ips prefixed with '+' or '' are added to the peer's
+allowed ips if not present while ips prefixed with '-' are removed if present.
+The use of \fIpersistent-keepalive\fP
 is optional and is by default off; setting it to 0 or "off" disables it.
 Otherwise it represents, in seconds, between 1 and 65535 inclusive, how often
 to send an authenticated empty packet to the peer, for the purpose of keeping
diff --git a/contrib/wireguard-tools/set.c b/contrib/wireguard-tools/set.c
index 75560fd8cf62..992ffa205d6b 100644
--- a/contrib/wireguard-tools/set.c
+++ b/contrib/wireguard-tools/set.c
@@ -18,7 +18,7 @@ int set_main(int argc, const char *argv[])
 	int ret = 1;
 
 	if (argc < 3) {
-		fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>]...] ]...\n", PROG_NAME, argv[0]);
+		fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips [+|-]<ip1>/<cidr1>[,[+|-]<ip2>/<cidr2>]...] ]...\n", PROG_NAME, argv[0]);
 		return 1;
 	}
 
diff --git a/contrib/wireguard-tools/show.c b/contrib/wireguard-tools/show.c
index 3fd3d9e2a151..13777cf04280 100644
--- a/contrib/wireguard-tools/show.c
+++ b/contrib/wireguard-tools/show.c
@@ -312,9 +312,9 @@ static bool ugly_print(struct wgdevice *device, const char *param, bool with_int
 		else
 			printf("off\n");
 	} else if (!strcmp(param, "endpoints")) {
-		if (with_interface)
-			printf("%s\t", device->name);
 		for_each_wgpeer(device, peer) {
+			if (with_interface)
+				printf("%s\t", device->name);
 			printf("%s\t", key(peer->public_key));
 			if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6)
 				printf("%s\n", endpoint(&peer->endpoint.addr));
diff --git a/contrib/wireguard-tools/version.h b/contrib/wireguard-tools/version.h
index c3ca131aadf4..0a7ef8daf041 100644
--- a/contrib/wireguard-tools/version.h
+++ b/contrib/wireguard-tools/version.h
@@ -1,3 +1,3 @@
 #ifndef WIREGUARD_TOOLS_VERSION
-#define WIREGUARD_TOOLS_VERSION "1.0.20210914"
+#define WIREGUARD_TOOLS_VERSION "1.0.20250521"
 #endif