[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251029205123.286115-9-ast@fiberby.net>
Date: Wed, 29 Oct 2025 20:51:16 +0000
From: Asbjørn Sloth Tønnesen <ast@...erby.net>
To: "Jason A. Donenfeld" <Jason@...c4.com>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>
Cc: Asbjørn Sloth Tønnesen <ast@...erby.net>,
Donald Hunter <donald.hunter@...il.com>,
Simon Horman <horms@...nel.org>,
Jacob Keller <jacob.e.keller@...el.com>,
Andrew Lunn <andrew+netdev@...n.ch>,
wireguard@...ts.zx2c4.com,
netdev@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH net-next v1 08/11] tools: ynl: add sample for wireguard
Add a sample application for wireguard, using the generated C library,
The main benefit of this is to exercise the generated library,
which might be useful for future selftests.
The UAPI header is copied to tools/include/uapi/, when the header
changes ynl-gen will regenerate both copies.
Example:
$ make -C tools/net/ynl/lib
$ make -C tools/net/ynl/generated
$ make -C tools/net/ynl/samples wireguard
$ ./tools/net/ynl/samples/wireguard
usage: ./tools/net/ynl/samples/wireguard <ifindex|ifname>
$ sudo ./tools/net/ynl/samples/wireguard wg-test
Interface 3: wg-test
Peer 6adfb183a4a2c94a2f92dab5ade762a4788[...]:
Data: rx: 42 / tx: 42 bytes
Allowed IPs:
0.0.0.0/0
::/0
Signed-off-by: Asbjørn Sloth Tønnesen <ast@...erby.net>
---
MAINTAINERS | 2 +
tools/include/uapi/linux/wireguard.h | 79 ++++++++++++++++++++
tools/net/ynl/samples/.gitignore | 1 +
tools/net/ynl/samples/wireguard.c | 104 +++++++++++++++++++++++++++
4 files changed, 186 insertions(+)
create mode 100644 tools/include/uapi/linux/wireguard.h
create mode 100644 tools/net/ynl/samples/wireguard.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 1bceeb4f5d122..e7ec4cb4d044f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27632,6 +27632,8 @@ L: netdev@...r.kernel.org
S: Maintained
F: Documentation/netlink/specs/wireguard.yaml
F: drivers/net/wireguard/
+F: tools/include/uapi/linux/wireguard.h
+F: tools/net/ynl/samples/wireguard.c
F: tools/testing/selftests/wireguard/
WISTRON LAPTOP BUTTON DRIVER
diff --git a/tools/include/uapi/linux/wireguard.h b/tools/include/uapi/linux/wireguard.h
new file mode 100644
index 0000000000000..dc3924d0c5524
--- /dev/null
+++ b/tools/include/uapi/linux/wireguard.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/wireguard.yaml */
+/* YNL-GEN uapi header */
+
+#ifndef _UAPI_LINUX_WIREGUARD_H
+#define _UAPI_LINUX_WIREGUARD_H
+
+#define WG_GENL_NAME "wireguard"
+#define WG_GENL_VERSION 1
+
+#define WG_KEY_LEN 32
+
+enum wgdevice_flag {
+ WGDEVICE_F_REPLACE_PEERS = 1,
+};
+
+enum wgpeer_flag {
+ WGPEER_F_REMOVE_ME = 1,
+ WGPEER_F_REPLACE_ALLOWEDIPS = 2,
+ WGPEER_F_UPDATE_ONLY = 4,
+};
+
+enum wgallowedip_flag {
+ WGALLOWEDIP_F_REMOVE_ME = 1,
+};
+
+enum wgdevice_attribute {
+ WGDEVICE_A_UNSPEC,
+ WGDEVICE_A_IFINDEX,
+ WGDEVICE_A_IFNAME,
+ WGDEVICE_A_PRIVATE_KEY,
+ WGDEVICE_A_PUBLIC_KEY,
+ WGDEVICE_A_FLAGS,
+ WGDEVICE_A_LISTEN_PORT,
+ WGDEVICE_A_FWMARK,
+ WGDEVICE_A_PEERS,
+
+ __WGDEVICE_A_LAST
+};
+#define WGDEVICE_A_MAX (__WGDEVICE_A_LAST - 1)
+
+enum wgpeer_attribute {
+ WGPEER_A_UNSPEC,
+ WGPEER_A_PUBLIC_KEY,
+ WGPEER_A_PRESHARED_KEY,
+ WGPEER_A_FLAGS,
+ WGPEER_A_ENDPOINT,
+ WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL,
+ WGPEER_A_LAST_HANDSHAKE_TIME,
+ WGPEER_A_RX_BYTES,
+ WGPEER_A_TX_BYTES,
+ WGPEER_A_ALLOWEDIPS,
+ WGPEER_A_PROTOCOL_VERSION,
+
+ __WGPEER_A_LAST
+};
+#define WGPEER_A_MAX (__WGPEER_A_LAST - 1)
+
+enum wgallowedip_attribute {
+ WGALLOWEDIP_A_UNSPEC,
+ WGALLOWEDIP_A_FAMILY,
+ WGALLOWEDIP_A_IPADDR,
+ WGALLOWEDIP_A_CIDR_MASK,
+ WGALLOWEDIP_A_FLAGS,
+
+ __WGALLOWEDIP_A_LAST
+};
+#define WGALLOWEDIP_A_MAX (__WGALLOWEDIP_A_LAST - 1)
+
+enum wg_cmd {
+ WG_CMD_GET_DEVICE,
+ WG_CMD_SET_DEVICE,
+
+ __WG_CMD_MAX
+};
+#define WG_CMD_MAX (__WG_CMD_MAX - 1)
+
+#endif /* _UAPI_LINUX_WIREGUARD_H */
diff --git a/tools/net/ynl/samples/.gitignore b/tools/net/ynl/samples/.gitignore
index 7f5fca7682d74..09c61e4c18cd4 100644
--- a/tools/net/ynl/samples/.gitignore
+++ b/tools/net/ynl/samples/.gitignore
@@ -7,3 +7,4 @@ rt-addr
rt-link
rt-route
tc
+wireguard
diff --git a/tools/net/ynl/samples/wireguard.c b/tools/net/ynl/samples/wireguard.c
new file mode 100644
index 0000000000000..43f3551eb101a
--- /dev/null
+++ b/tools/net/ynl/samples/wireguard.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <arpa/inet.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ynl.h>
+
+#include "wireguard-user.h"
+
+static void print_allowed_ip(const struct wireguard_wgallowedip *aip)
+{
+ char addr_out[INET6_ADDRSTRLEN];
+
+ if (!inet_ntop(aip->family, aip->ipaddr, addr_out, sizeof(addr_out))) {
+ addr_out[0] = '?';
+ addr_out[1] = '\0';
+ }
+ printf("\t\t\t%s/%u\n", addr_out, aip->cidr_mask);
+}
+
+/* Only printing public key in this demo. For better key formatting,
+ * use the constant-time implementation as found in wireguard-tools.
+ */
+static void print_peer_header(const struct wireguard_wgpeer *peer)
+{
+ unsigned int i;
+ uint8_t *key = peer->public_key;
+ unsigned int len = peer->_len.public_key;
+
+ if (len != 32)
+ return;
+ printf("\tPeer ");
+ for (i = 0; i < len; i++)
+ printf("%02x", key[i]);
+ printf(":\n");
+}
+
+static void print_peer(const struct wireguard_wgpeer *peer)
+{
+ unsigned int i;
+
+ print_peer_header(peer);
+ printf("\t\tData: rx: %llu / tx: %llu bytes\n",
+ peer->rx_bytes, peer->tx_bytes);
+ printf("\t\tAllowed IPs:\n");
+ for (i = 0; i < peer->_count.allowedips; i++)
+ print_allowed_ip(&peer->allowedips[i]);
+}
+
+static void build_request(struct wireguard_get_device_req *req, char *arg)
+{
+ char *endptr;
+ int ifindex;
+
+ ifindex = strtol(arg, &endptr, 0);
+ if (endptr != arg + strlen(arg) || errno != 0)
+ ifindex = 0;
+ if (ifindex > 0)
+ wireguard_get_device_req_set_ifindex(req, ifindex);
+ else
+ wireguard_get_device_req_set_ifname(req, arg);
+}
+
+int main(int argc, char **argv)
+{
+ struct wireguard_get_device_list *devs;
+ struct wireguard_get_device_req *req;
+ struct ynl_sock *ys;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <ifindex|ifname>\n", argv[0]);
+ return 1;
+ }
+
+ req = wireguard_get_device_req_alloc();
+ build_request(req, argv[1]);
+
+ ys = ynl_sock_create(&ynl_wireguard_family, NULL);
+ if (!ys)
+ return 2;
+
+ devs = wireguard_get_device_dump(ys, req);
+ if (!devs)
+ goto err_close;
+
+ ynl_dump_foreach(devs, d) {
+ unsigned int i;
+
+ printf("Interface %d: %s\n", d->ifindex, d->ifname);
+ for (i = 0; i < d->_count.peers; i++)
+ print_peer(&d->peers[i]);
+ }
+ wireguard_get_device_list_free(devs);
+ wireguard_get_device_req_free(req);
+ ynl_sock_destroy(ys);
+
+ return 0;
+
+err_close:
+ fprintf(stderr, "YNL (%d): %s\n", ys->err.code, ys->err.msg);
+ wireguard_get_device_req_free(req);
+ ynl_sock_destroy(ys);
+ return 3;
+}
--
2.51.0
Powered by blists - more mailing lists