Skip to content

Commit 31a3ed4

Browse files
committed
Jason A. Donenfeld says: ==================== WireGuard updates for Linux 6.19-rc1. Please find here Asbjørn's ynl series. This has been sitting in my testing for the last week or so, since he sent out the latest series. I've dropped the yml sample code, as he found an issue in that last minute, but otherwise, we've sat on this code for long enough, so let's see how it goes. * tag 'wireguard-6.19-rc1-for-jakub' of https://git.kernel.org/pub/scm/linux/kernel/git/zx2c4/wireguard-linux: wireguard: netlink: generate netlink code wireguard: uapi: generate header with ynl-gen wireguard: uapi: move flag enums wireguard: uapi: move enum wg_cmd wireguard: netlink: add YNL specification wireguard: netlink: lower .maxattr for WG_CMD_GET_DEVICE wireguard: netlink: convert to split ops wireguard: netlink: use WG_KEY_LEN in policies wireguard: netlink: validate nested arrays in policy wireguard: netlink: enable strict genetlink validation ==================== Link: https://patch.msgid.link/ Signed-off-by: Jakub Kicinski <[email protected]>
2 parents cbc19b3 + 3fd2f3d commit 31a3ed4

File tree

7 files changed

+448
-215
lines changed

7 files changed

+448
-215
lines changed
Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
2+
---
3+
name: wireguard
4+
protocol: genetlink-legacy
5+
6+
doc: |
7+
**Netlink protocol to control WireGuard network devices.**
8+
9+
The below enums and macros are for interfacing with WireGuard, using generic
10+
netlink, with family ``WG_GENL_NAME`` and version ``WG_GENL_VERSION``. It
11+
defines two commands: get and set. Note that while they share many common
12+
attributes, these two commands actually accept a slightly different set of
13+
inputs and outputs. These differences are noted under the individual
14+
attributes.
15+
c-family-name: wg-genl-name
16+
c-version-name: wg-genl-version
17+
max-by-define: true
18+
19+
definitions:
20+
-
21+
name-prefix: wg-
22+
name: key-len
23+
type: const
24+
value: 32
25+
-
26+
name: --kernel-timespec
27+
type: struct
28+
header: linux/time_types.h
29+
members:
30+
-
31+
name: sec
32+
type: u64
33+
doc: Number of seconds, since UNIX epoch.
34+
-
35+
name: nsec
36+
type: u64
37+
doc: Number of nanoseconds, after the second began.
38+
-
39+
name: wgdevice-flags
40+
name-prefix: wgdevice-f-
41+
enum-name: wgdevice-flag
42+
type: flags
43+
entries:
44+
- replace-peers
45+
-
46+
name: wgpeer-flags
47+
name-prefix: wgpeer-f-
48+
enum-name: wgpeer-flag
49+
type: flags
50+
entries:
51+
- remove-me
52+
- replace-allowedips
53+
- update-only
54+
-
55+
name: wgallowedip-flags
56+
name-prefix: wgallowedip-f-
57+
enum-name: wgallowedip-flag
58+
type: flags
59+
entries:
60+
- remove-me
61+
62+
attribute-sets:
63+
-
64+
name: wgdevice
65+
enum-name: wgdevice-attribute
66+
name-prefix: wgdevice-a-
67+
attr-cnt-name: --wgdevice-a-last
68+
attributes:
69+
-
70+
name: unspec
71+
type: unused
72+
value: 0
73+
-
74+
name: ifindex
75+
type: u32
76+
-
77+
name: ifname
78+
type: string
79+
checks:
80+
max-len: 15
81+
-
82+
name: private-key
83+
type: binary
84+
doc: Set to all zeros to remove.
85+
display-hint: hex
86+
checks:
87+
exact-len: wg-key-len
88+
-
89+
name: public-key
90+
type: binary
91+
display-hint: hex
92+
checks:
93+
exact-len: wg-key-len
94+
-
95+
name: flags
96+
type: u32
97+
doc: |
98+
``0`` or ``WGDEVICE_F_REPLACE_PEERS`` if all current peers should be
99+
removed prior to adding the list below.
100+
enum: wgdevice-flags
101+
-
102+
name: listen-port
103+
type: u16
104+
doc: Set as ``0`` to choose randomly.
105+
-
106+
name: fwmark
107+
type: u32
108+
doc: Set as ``0`` to disable.
109+
-
110+
name: peers
111+
type: indexed-array
112+
sub-type: nest
113+
nested-attributes: wgpeer
114+
doc: |
115+
The index/type parameter is unused on ``SET_DEVICE`` operations and is
116+
zero on ``GET_DEVICE`` operations.
117+
-
118+
name: wgpeer
119+
enum-name: wgpeer-attribute
120+
name-prefix: wgpeer-a-
121+
attr-cnt-name: --wgpeer-a-last
122+
attributes:
123+
-
124+
name: unspec
125+
type: unused
126+
value: 0
127+
-
128+
name: public-key
129+
type: binary
130+
display-hint: hex
131+
checks:
132+
exact-len: wg-key-len
133+
-
134+
name: preshared-key
135+
type: binary
136+
doc: Set as all zeros to remove.
137+
display-hint: hex
138+
checks:
139+
exact-len: wg-key-len
140+
-
141+
name: flags
142+
type: u32
143+
doc: |
144+
``0`` and/or ``WGPEER_F_REMOVE_ME`` if the specified peer should not
145+
exist at the end of the operation, rather than added/updated and/or
146+
``WGPEER_F_REPLACE_ALLOWEDIPS`` if all current allowed IPs of this
147+
peer should be removed prior to adding the list below and/or
148+
``WGPEER_F_UPDATE_ONLY`` if the peer should only be set if it already
149+
exists.
150+
enum: wgpeer-flags
151+
-
152+
name: endpoint
153+
type: binary
154+
doc: struct sockaddr_in or struct sockaddr_in6
155+
checks:
156+
min-len: 16
157+
-
158+
name: persistent-keepalive-interval
159+
type: u16
160+
doc: Set as ``0`` to disable.
161+
-
162+
name: last-handshake-time
163+
type: binary
164+
struct: --kernel-timespec
165+
checks:
166+
exact-len: 16
167+
-
168+
name: rx-bytes
169+
type: u64
170+
-
171+
name: tx-bytes
172+
type: u64
173+
-
174+
name: allowedips
175+
type: indexed-array
176+
sub-type: nest
177+
nested-attributes: wgallowedip
178+
doc: |
179+
The index/type parameter is unused on ``SET_DEVICE`` operations and is
180+
zero on ``GET_DEVICE`` operations.
181+
-
182+
name: protocol-version
183+
type: u32
184+
doc: |
185+
Should not be set or used at all by most users of this API, as the
186+
most recent protocol will be used when this is unset. Otherwise,
187+
must be set to ``1``.
188+
-
189+
name: wgallowedip
190+
enum-name: wgallowedip-attribute
191+
name-prefix: wgallowedip-a-
192+
attr-cnt-name: --wgallowedip-a-last
193+
attributes:
194+
-
195+
name: unspec
196+
type: unused
197+
value: 0
198+
-
199+
name: family
200+
type: u16
201+
doc: IP family, either ``AF_INET`` or ``AF_INET6``.
202+
-
203+
name: ipaddr
204+
type: binary
205+
doc: Either ``struct in_addr`` or ``struct in6_addr``.
206+
display-hint: ipv4-or-v6
207+
checks:
208+
min-len: 4
209+
-
210+
name: cidr-mask
211+
type: u8
212+
-
213+
name: flags
214+
type: u32
215+
doc: |
216+
``WGALLOWEDIP_F_REMOVE_ME`` if the specified IP should be removed;
217+
otherwise, this IP will be added if it is not already present.
218+
enum: wgallowedip-flags
219+
220+
operations:
221+
enum-name: wg-cmd
222+
name-prefix: wg-cmd-
223+
list:
224+
-
225+
name: get-device
226+
value: 0
227+
doc: |
228+
Retrieve WireGuard device
229+
~~~~~~~~~~~~~~~~~~~~~~~~~
230+
231+
The command should be called with one but not both of:
232+
233+
- ``WGDEVICE_A_IFINDEX``
234+
- ``WGDEVICE_A_IFNAME``
235+
236+
The kernel will then return several messages (``NLM_F_MULTI``). It is
237+
possible that all of the allowed IPs of a single peer will not fit
238+
within a single netlink message. In that case, the same peer will be
239+
written in the following message, except it will only contain
240+
``WGPEER_A_PUBLIC_KEY`` and ``WGPEER_A_ALLOWEDIPS``. This may occur
241+
several times in a row for the same peer. It is then up to the receiver
242+
to coalesce adjacent peers. Likewise, it is possible that all peers will
243+
not fit within a single message. So, subsequent peers will be sent in
244+
following messages, except those will only contain ``WGDEVICE_A_IFNAME``
245+
and ``WGDEVICE_A_PEERS``. It is then up to the receiver to coalesce
246+
these messages to form the complete list of peers.
247+
248+
Since this is an ``NLA_F_DUMP`` command, the final message will always
249+
be ``NLMSG_DONE``, even if an error occurs. However, this ``NLMSG_DONE``
250+
message contains an integer error code. It is either zero or a negative
251+
error code corresponding to the errno.
252+
attribute-set: wgdevice
253+
flags: [uns-admin-perm]
254+
255+
dump:
256+
pre: wg-get-device-start
257+
post: wg-get-device-done
258+
request:
259+
attributes:
260+
- ifindex
261+
- ifname
262+
reply: &all-attrs
263+
attributes:
264+
- ifindex
265+
- ifname
266+
- private-key
267+
- public-key
268+
- flags
269+
- listen-port
270+
- fwmark
271+
- peers
272+
-
273+
name: set-device
274+
value: 1
275+
doc: |
276+
Set WireGuard device
277+
~~~~~~~~~~~~~~~~~~~~
278+
279+
This command should be called with a wgdevice set, containing one but
280+
not both of ``WGDEVICE_A_IFINDEX`` and ``WGDEVICE_A_IFNAME``.
281+
282+
It is possible that the amount of configuration data exceeds that of the
283+
maximum message length accepted by the kernel. In that case, several
284+
messages should be sent one after another, with each successive one
285+
filling in information not contained in the prior. Note that if
286+
``WGDEVICE_F_REPLACE_PEERS`` is specified in the first message, it
287+
probably should not be specified in fragments that come after, so that
288+
the list of peers is only cleared the first time but appended after.
289+
Likewise for peers, if ``WGPEER_F_REPLACE_ALLOWEDIPS`` is specified in
290+
the first message of a peer, it likely should not be specified in
291+
subsequent fragments.
292+
293+
If an error occurs, ``NLMSG_ERROR`` will reply containing an errno.
294+
attribute-set: wgdevice
295+
flags: [uns-admin-perm]
296+
297+
do:
298+
request: *all-attrs

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27674,6 +27674,7 @@ M: Jason A. Donenfeld <[email protected]>
2767427674
2767527675
2767627676
S: Maintained
27677+
F: Documentation/netlink/specs/wireguard.yaml
2767727678
F: drivers/net/wireguard/
2767827679
F: tools/testing/selftests/wireguard/
2767927680

drivers/net/wireguard/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ wireguard-y += peerlookup.o
1313
wireguard-y += allowedips.o
1414
wireguard-y += ratelimiter.o
1515
wireguard-y += cookie.o
16-
wireguard-y += netlink.o
16+
wireguard-y += netlink.o generated/netlink.o
1717
obj-$(CONFIG_WIREGUARD) := wireguard.o
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
2+
/* Do not edit directly, auto-generated from: */
3+
/* Documentation/netlink/specs/wireguard.yaml */
4+
/* YNL-GEN kernel source */
5+
/* YNL-ARG --function-prefix wg */
6+
/* To regenerate run: tools/net/ynl/ynl-regen.sh */
7+
8+
#include <net/netlink.h>
9+
#include <net/genetlink.h>
10+
11+
#include "netlink.h"
12+
13+
#include <uapi/linux/wireguard.h>
14+
#include <linux/time_types.h>
15+
16+
/* Common nested types */
17+
const struct nla_policy wireguard_wgallowedip_nl_policy[WGALLOWEDIP_A_FLAGS + 1] = {
18+
[WGALLOWEDIP_A_FAMILY] = { .type = NLA_U16, },
19+
[WGALLOWEDIP_A_IPADDR] = NLA_POLICY_MIN_LEN(4),
20+
[WGALLOWEDIP_A_CIDR_MASK] = { .type = NLA_U8, },
21+
[WGALLOWEDIP_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0x1),
22+
};
23+
24+
const struct nla_policy wireguard_wgpeer_nl_policy[WGPEER_A_PROTOCOL_VERSION + 1] = {
25+
[WGPEER_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
26+
[WGPEER_A_PRESHARED_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
27+
[WGPEER_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0x7),
28+
[WGPEER_A_ENDPOINT] = NLA_POLICY_MIN_LEN(16),
29+
[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16, },
30+
[WGPEER_A_LAST_HANDSHAKE_TIME] = NLA_POLICY_EXACT_LEN(16),
31+
[WGPEER_A_RX_BYTES] = { .type = NLA_U64, },
32+
[WGPEER_A_TX_BYTES] = { .type = NLA_U64, },
33+
[WGPEER_A_ALLOWEDIPS] = NLA_POLICY_NESTED_ARRAY(wireguard_wgallowedip_nl_policy),
34+
[WGPEER_A_PROTOCOL_VERSION] = { .type = NLA_U32, },
35+
};
36+
37+
/* WG_CMD_GET_DEVICE - dump */
38+
static const struct nla_policy wireguard_get_device_nl_policy[WGDEVICE_A_IFNAME + 1] = {
39+
[WGDEVICE_A_IFINDEX] = { .type = NLA_U32, },
40+
[WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .len = 15, },
41+
};
42+
43+
/* WG_CMD_SET_DEVICE - do */
44+
static const struct nla_policy wireguard_set_device_nl_policy[WGDEVICE_A_PEERS + 1] = {
45+
[WGDEVICE_A_IFINDEX] = { .type = NLA_U32, },
46+
[WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .len = 15, },
47+
[WGDEVICE_A_PRIVATE_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
48+
[WGDEVICE_A_PUBLIC_KEY] = NLA_POLICY_EXACT_LEN(WG_KEY_LEN),
49+
[WGDEVICE_A_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0x1),
50+
[WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16, },
51+
[WGDEVICE_A_FWMARK] = { .type = NLA_U32, },
52+
[WGDEVICE_A_PEERS] = NLA_POLICY_NESTED_ARRAY(wireguard_wgpeer_nl_policy),
53+
};
54+
55+
/* Ops table for wireguard */
56+
const struct genl_split_ops wireguard_nl_ops[2] = {
57+
{
58+
.cmd = WG_CMD_GET_DEVICE,
59+
.start = wg_get_device_start,
60+
.dumpit = wg_get_device_dumpit,
61+
.done = wg_get_device_done,
62+
.policy = wireguard_get_device_nl_policy,
63+
.maxattr = WGDEVICE_A_IFNAME,
64+
.flags = GENL_UNS_ADMIN_PERM | GENL_CMD_CAP_DUMP,
65+
},
66+
{
67+
.cmd = WG_CMD_SET_DEVICE,
68+
.doit = wg_set_device_doit,
69+
.policy = wireguard_set_device_nl_policy,
70+
.maxattr = WGDEVICE_A_PEERS,
71+
.flags = GENL_UNS_ADMIN_PERM | GENL_CMD_CAP_DO,
72+
},
73+
};

0 commit comments

Comments
 (0)