Skip to content

Commit 6b0f4ca

Browse files
Asbjørn Sloth Tønnesenzx2c4
authored andcommitted
wireguard: netlink: add YNL specification
This patch adds a near[1] complete YNL specification for WireGuard, documenting the protocol in a machine-readable format, rather than comments in wireguard.h, and eases usage from C and non-C programming languages alike. The generated C library will be featured in a later patch, so in this patch I will use the in-kernel python client for examples. This makes the documentation in the UAPI header redundant, it is therefore removed. The in-line documentation in the spec is based on the existing comment in wireguard.h, and once released it will be available in the kernel documentation at: https://docs.kernel.org/netlink/specs/wireguard.html (until then run: make htmldocs) Generate wireguard.rst from this spec: $ make -C tools/net/ynl/generated/ wireguard.rst Query wireguard interface through pyynl: $ sudo ./tools/net/ynl/pyynl/cli.py --family wireguard \ --dump get-device \ --json '{"ifindex":3}' [{'fwmark': 0, 'ifindex': 3, 'ifname': 'wg-test', 'listen-port': 54318, 'peers': [{0: {'allowedips': [{0: {'cidr-mask': 0, 'family': 2, 'ipaddr': '0.0.0.0'}}, {0: {'cidr-mask': 0, 'family': 10, 'ipaddr': '::'}}], 'endpoint': b'[...]', 'last-handshake-time': {'nsec': 42, 'sec': 42}, 'persistent-keepalive-interval': 42, 'preshared-key': '[...]', 'protocol-version': 1, 'public-key': '[...]', 'rx-bytes': 42, 'tx-bytes': 42}}], 'private-key': '[...]', 'public-key': '[...]'}] Add another allowed IP prefix: $ sudo ./tools/net/ynl/pyynl/cli.py --family wireguard \ --do set-device --json '{"ifindex":3,"peers":[ {"public-key":"6a df b1 83 a4 ..","allowedips":[ {"cidr-mask":0,"family":10,"ipaddr":"::"}]}]}' [1] As can be seen above, the "endpoint" is only dumped as binary data, as it can't be fully described in YNL. It's either a struct sockaddr_in or struct sockaddr_in6 depending on the attribute length. Signed-off-by: Asbjørn Sloth Tønnesen <ast@fiberby.net> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
1 parent b8bcc17 commit 6b0f4ca

File tree

3 files changed

+299
-129
lines changed

3 files changed

+299
-129
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
@@ -27673,6 +27673,7 @@ M: Jason A. Donenfeld <Jason@zx2c4.com>
2767327673
L: wireguard@lists.zx2c4.com
2767427674
L: netdev@vger.kernel.org
2767527675
S: Maintained
27676+
F: Documentation/netlink/specs/wireguard.yaml
2767627677
F: drivers/net/wireguard/
2767727678
F: tools/testing/selftests/wireguard/
2767827679

0 commit comments

Comments
 (0)