Mon Aug 31 20:31:43 2020 UTC ()
wg: M_NOWAIT -> M_DONTWAIT

These happen to be aliases, but M_NOWAIT is part of the legacy malloc
API whereas M_DONTWAIT is part of the mbuf API.


(riastradh)
diff -r1.47 -r1.48 src/sys/net/if_wg.c

cvs diff -r1.47 -r1.48 src/sys/net/if_wg.c (switch to unified diff)

--- src/sys/net/if_wg.c 2020/08/31 20:31:03 1.47
+++ src/sys/net/if_wg.c 2020/08/31 20:31:43 1.48
@@ -1,1043 +1,1043 @@ @@ -1,1043 +1,1043 @@
1/* $NetBSD: if_wg.c,v 1.47 2020/08/31 20:31:03 riastradh Exp $ */ 1/* $NetBSD: if_wg.c,v 1.48 2020/08/31 20:31:43 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com> 4 * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors 15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software 16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission. 17 * without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * This network interface aims to implement the WireGuard protocol. 33 * This network interface aims to implement the WireGuard protocol.
34 * The implementation is based on the paper of WireGuard as of 34 * The implementation is based on the paper of WireGuard as of
35 * 2018-06-30 [1]. The paper is referred in the source code with label 35 * 2018-06-30 [1]. The paper is referred in the source code with label
36 * [W]. Also the specification of the Noise protocol framework as of 36 * [W]. Also the specification of the Noise protocol framework as of
37 * 2018-07-11 [2] is referred with label [N]. 37 * 2018-07-11 [2] is referred with label [N].
38 * 38 *
39 * [1] https://www.wireguard.com/papers/wireguard.pdf 39 * [1] https://www.wireguard.com/papers/wireguard.pdf
40 * [2] http://noiseprotocol.org/noise.pdf 40 * [2] http://noiseprotocol.org/noise.pdf
41 */ 41 */
42 42
43#include <sys/cdefs.h> 43#include <sys/cdefs.h>
44__KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.47 2020/08/31 20:31:03 riastradh Exp $"); 44__KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.48 2020/08/31 20:31:43 riastradh Exp $");
45 45
46#ifdef _KERNEL_OPT 46#ifdef _KERNEL_OPT
47#include "opt_inet.h" 47#include "opt_inet.h"
48#endif 48#endif
49 49
50#include <sys/param.h> 50#include <sys/param.h>
51#include <sys/types.h> 51#include <sys/types.h>
52 52
53#include <sys/atomic.h> 53#include <sys/atomic.h>
54#include <sys/callout.h> 54#include <sys/callout.h>
55#include <sys/cprng.h> 55#include <sys/cprng.h>
56#include <sys/cpu.h> 56#include <sys/cpu.h>
57#include <sys/device.h> 57#include <sys/device.h>
58#include <sys/domain.h> 58#include <sys/domain.h>
59#include <sys/errno.h> 59#include <sys/errno.h>
60#include <sys/intr.h> 60#include <sys/intr.h>
61#include <sys/ioctl.h> 61#include <sys/ioctl.h>
62#include <sys/kernel.h> 62#include <sys/kernel.h>
63#include <sys/kmem.h> 63#include <sys/kmem.h>
64#include <sys/kthread.h> 64#include <sys/kthread.h>
65#include <sys/mbuf.h> 65#include <sys/mbuf.h>
66#include <sys/module.h> 66#include <sys/module.h>
67#include <sys/mutex.h> 67#include <sys/mutex.h>
68#include <sys/pcq.h> 68#include <sys/pcq.h>
69#include <sys/percpu.h> 69#include <sys/percpu.h>
70#include <sys/pserialize.h> 70#include <sys/pserialize.h>
71#include <sys/psref.h> 71#include <sys/psref.h>
72#include <sys/queue.h> 72#include <sys/queue.h>
73#include <sys/rwlock.h> 73#include <sys/rwlock.h>
74#include <sys/socket.h> 74#include <sys/socket.h>
75#include <sys/socketvar.h> 75#include <sys/socketvar.h>
76#include <sys/sockio.h> 76#include <sys/sockio.h>
77#include <sys/sysctl.h> 77#include <sys/sysctl.h>
78#include <sys/syslog.h> 78#include <sys/syslog.h>
79#include <sys/systm.h> 79#include <sys/systm.h>
80#include <sys/thmap.h> 80#include <sys/thmap.h>
81#include <sys/time.h> 81#include <sys/time.h>
82#include <sys/timespec.h> 82#include <sys/timespec.h>
83 83
84#include <net/bpf.h> 84#include <net/bpf.h>
85#include <net/if.h> 85#include <net/if.h>
86#include <net/if_types.h> 86#include <net/if_types.h>
87#include <net/if_wg.h> 87#include <net/if_wg.h>
88#include <net/route.h> 88#include <net/route.h>
89 89
90#include <netinet/in.h> 90#include <netinet/in.h>
91#include <netinet/in_pcb.h> 91#include <netinet/in_pcb.h>
92#include <netinet/in_var.h> 92#include <netinet/in_var.h>
93#include <netinet/ip.h> 93#include <netinet/ip.h>
94#include <netinet/ip_var.h> 94#include <netinet/ip_var.h>
95#include <netinet/udp.h> 95#include <netinet/udp.h>
96#include <netinet/udp_var.h> 96#include <netinet/udp_var.h>
97 97
98#ifdef INET6 98#ifdef INET6
99#include <netinet/ip6.h> 99#include <netinet/ip6.h>
100#include <netinet6/in6_pcb.h> 100#include <netinet6/in6_pcb.h>
101#include <netinet6/in6_var.h> 101#include <netinet6/in6_var.h>
102#include <netinet6/ip6_var.h> 102#include <netinet6/ip6_var.h>
103#include <netinet6/udp6_var.h> 103#include <netinet6/udp6_var.h>
104#endif /* INET6 */ 104#endif /* INET6 */
105 105
106#include <prop/proplib.h> 106#include <prop/proplib.h>
107 107
108#include <crypto/blake2/blake2s.h> 108#include <crypto/blake2/blake2s.h>
109#include <crypto/sodium/crypto_aead_chacha20poly1305.h> 109#include <crypto/sodium/crypto_aead_chacha20poly1305.h>
110#include <crypto/sodium/crypto_aead_xchacha20poly1305.h> 110#include <crypto/sodium/crypto_aead_xchacha20poly1305.h>
111#include <crypto/sodium/crypto_scalarmult.h> 111#include <crypto/sodium/crypto_scalarmult.h>
112 112
113#include "ioconf.h" 113#include "ioconf.h"
114 114
115#ifdef WG_RUMPKERNEL 115#ifdef WG_RUMPKERNEL
116#include "wg_user.h" 116#include "wg_user.h"
117#endif 117#endif
118 118
119/* 119/*
120 * Data structures 120 * Data structures
121 * - struct wg_softc is an instance of wg interfaces 121 * - struct wg_softc is an instance of wg interfaces
122 * - It has a list of peers (struct wg_peer) 122 * - It has a list of peers (struct wg_peer)
123 * - It has a kthread that sends/receives handshake messages and 123 * - It has a kthread that sends/receives handshake messages and
124 * runs event handlers 124 * runs event handlers
125 * - It has its own two routing tables: one is for IPv4 and the other IPv6 125 * - It has its own two routing tables: one is for IPv4 and the other IPv6
126 * - struct wg_peer is a representative of a peer 126 * - struct wg_peer is a representative of a peer
127 * - It has a softint that is used to send packets over an wg interface 127 * - It has a softint that is used to send packets over an wg interface
128 * to a peer 128 * to a peer
129 * - It has a pair of session instances (struct wg_session) 129 * - It has a pair of session instances (struct wg_session)
130 * - It has a pair of endpoint instances (struct wg_sockaddr) 130 * - It has a pair of endpoint instances (struct wg_sockaddr)
131 * - Normally one endpoint is used and the second one is used only on 131 * - Normally one endpoint is used and the second one is used only on
132 * a peer migration (a change of peer's IP address) 132 * a peer migration (a change of peer's IP address)
133 * - It has a list of IP addresses and sub networks called allowedips 133 * - It has a list of IP addresses and sub networks called allowedips
134 * (struct wg_allowedip) 134 * (struct wg_allowedip)
135 * - A packets sent over a session is allowed if its destination matches 135 * - A packets sent over a session is allowed if its destination matches
136 * any IP addresses or sub networks of the list 136 * any IP addresses or sub networks of the list
137 * - struct wg_session represents a session of a secure tunnel with a peer 137 * - struct wg_session represents a session of a secure tunnel with a peer
138 * - Two instances of sessions belong to a peer; a stable session and a 138 * - Two instances of sessions belong to a peer; a stable session and a
139 * unstable session 139 * unstable session
140 * - A handshake process of a session always starts with a unstable instace 140 * - A handshake process of a session always starts with a unstable instace
141 * - Once a session is established, its instance becomes stable and the 141 * - Once a session is established, its instance becomes stable and the
142 * other becomes unstable instead 142 * other becomes unstable instead
143 * - Data messages are always sent via a stable session 143 * - Data messages are always sent via a stable session
144 * 144 *
145 * Locking notes: 145 * Locking notes:
146 * - wg interfaces (struct wg_softc, wg) is listed in wg_softcs.list and 146 * - wg interfaces (struct wg_softc, wg) is listed in wg_softcs.list and
147 * protected by wg_softcs.lock 147 * protected by wg_softcs.lock
148 * - Each wg has a mutex(9) and a rwlock(9) 148 * - Each wg has a mutex(9) and a rwlock(9)
149 * - The mutex (wg_lock) protects its peer list (wg_peers) 149 * - The mutex (wg_lock) protects its peer list (wg_peers)
150 * - A peer on the list is also protected by pserialize(9) or psref(9) 150 * - A peer on the list is also protected by pserialize(9) or psref(9)
151 * - The rwlock (wg_rwlock) protects the routing tables (wg_rtable_ipv[46]) 151 * - The rwlock (wg_rwlock) protects the routing tables (wg_rtable_ipv[46])
152 * - Each peer (struct wg_peer, wgp) has a mutex 152 * - Each peer (struct wg_peer, wgp) has a mutex
153 * - The mutex (wgp_lock) protects wgp_session_unstable and wgp_state 153 * - The mutex (wgp_lock) protects wgp_session_unstable and wgp_state
154 * - Each session (struct wg_session, wgs) has a mutex 154 * - Each session (struct wg_session, wgs) has a mutex
155 * - The mutex (wgs_lock) protects its state (wgs_state) and its handshake 155 * - The mutex (wgs_lock) protects its state (wgs_state) and its handshake
156 * states 156 * states
157 * - wgs_state of a unstable session can be changed while it never be 157 * - wgs_state of a unstable session can be changed while it never be
158 * changed on a stable session, so once get a session instace via 158 * changed on a stable session, so once get a session instace via
159 * wgp_session_stable we can safely access wgs_state without 159 * wgp_session_stable we can safely access wgs_state without
160 * holding wgs_lock 160 * holding wgs_lock
161 * - A session is protected by pserialize or psref like wgp 161 * - A session is protected by pserialize or psref like wgp
162 * - On a session swap, we must wait for all readers to release a 162 * - On a session swap, we must wait for all readers to release a
163 * reference to a stable session before changing wgs_state and 163 * reference to a stable session before changing wgs_state and
164 * session states 164 * session states
165 * 165 *
166 * Lock order: wg_lock -> wgp_lock -> wgs_lock 166 * Lock order: wg_lock -> wgp_lock -> wgs_lock
167 */ 167 */
168 168
169 169
170#define WGLOG(level, fmt, args...) \ 170#define WGLOG(level, fmt, args...) \
171 log(level, "%s: " fmt, __func__, ##args) 171 log(level, "%s: " fmt, __func__, ##args)
172 172
173/* Debug options */ 173/* Debug options */
174#ifdef WG_DEBUG 174#ifdef WG_DEBUG
175/* Output debug logs */ 175/* Output debug logs */
176#ifndef WG_DEBUG_LOG 176#ifndef WG_DEBUG_LOG
177#define WG_DEBUG_LOG 177#define WG_DEBUG_LOG
178#endif 178#endif
179/* Output trace logs */ 179/* Output trace logs */
180#ifndef WG_DEBUG_TRACE 180#ifndef WG_DEBUG_TRACE
181#define WG_DEBUG_TRACE 181#define WG_DEBUG_TRACE
182#endif 182#endif
183/* Output hash values, etc. */ 183/* Output hash values, etc. */
184#ifndef WG_DEBUG_DUMP 184#ifndef WG_DEBUG_DUMP
185#define WG_DEBUG_DUMP 185#define WG_DEBUG_DUMP
186#endif 186#endif
187/* Make some internal parameters configurable for testing and debugging */ 187/* Make some internal parameters configurable for testing and debugging */
188#ifndef WG_DEBUG_PARAMS 188#ifndef WG_DEBUG_PARAMS
189#define WG_DEBUG_PARAMS 189#define WG_DEBUG_PARAMS
190#endif 190#endif
191#endif 191#endif
192 192
193#ifdef WG_DEBUG_TRACE 193#ifdef WG_DEBUG_TRACE
194#define WG_TRACE(msg) \ 194#define WG_TRACE(msg) \
195 log(LOG_DEBUG, "%s:%d: %s\n", __func__, __LINE__, (msg)) 195 log(LOG_DEBUG, "%s:%d: %s\n", __func__, __LINE__, (msg))
196#else 196#else
197#define WG_TRACE(msg) __nothing 197#define WG_TRACE(msg) __nothing
198#endif 198#endif
199 199
200#ifdef WG_DEBUG_LOG 200#ifdef WG_DEBUG_LOG
201#define WG_DLOG(fmt, args...) log(LOG_DEBUG, "%s: " fmt, __func__, ##args) 201#define WG_DLOG(fmt, args...) log(LOG_DEBUG, "%s: " fmt, __func__, ##args)
202#else 202#else
203#define WG_DLOG(fmt, args...) __nothing 203#define WG_DLOG(fmt, args...) __nothing
204#endif 204#endif
205 205
206#define WG_LOG_RATECHECK(wgprc, level, fmt, args...) do { \ 206#define WG_LOG_RATECHECK(wgprc, level, fmt, args...) do { \
207 if (ppsratecheck(&(wgprc)->wgprc_lasttime, \ 207 if (ppsratecheck(&(wgprc)->wgprc_lasttime, \
208 &(wgprc)->wgprc_curpps, 1)) { \ 208 &(wgprc)->wgprc_curpps, 1)) { \
209 log(level, fmt, ##args); \ 209 log(level, fmt, ##args); \
210 } \ 210 } \
211} while (0) 211} while (0)
212 212
213#ifdef WG_DEBUG_PARAMS 213#ifdef WG_DEBUG_PARAMS
214static bool wg_force_underload = false; 214static bool wg_force_underload = false;
215#endif 215#endif
216 216
217#ifdef WG_DEBUG_DUMP 217#ifdef WG_DEBUG_DUMP
218 218
219#ifdef WG_RUMPKERNEL 219#ifdef WG_RUMPKERNEL
220static void 220static void
221wg_dump_buf(const char *func, const char *buf, const size_t size) 221wg_dump_buf(const char *func, const char *buf, const size_t size)
222{ 222{
223 223
224 log(LOG_DEBUG, "%s: ", func); 224 log(LOG_DEBUG, "%s: ", func);
225 for (int i = 0; i < size; i++) 225 for (int i = 0; i < size; i++)
226 log(LOG_DEBUG, "%02x ", (int)(0xff & buf[i])); 226 log(LOG_DEBUG, "%02x ", (int)(0xff & buf[i]));
227 log(LOG_DEBUG, "\n"); 227 log(LOG_DEBUG, "\n");
228} 228}
229#endif 229#endif
230 230
231static void 231static void
232wg_dump_hash(const uint8_t *func, const uint8_t *name, const uint8_t *hash, 232wg_dump_hash(const uint8_t *func, const uint8_t *name, const uint8_t *hash,
233 const size_t size) 233 const size_t size)
234{ 234{
235 235
236 log(LOG_DEBUG, "%s: %s: ", func, name); 236 log(LOG_DEBUG, "%s: %s: ", func, name);
237 for (int i = 0; i < size; i++) 237 for (int i = 0; i < size; i++)
238 log(LOG_DEBUG, "%02x ", (int)(0xff & hash[i])); 238 log(LOG_DEBUG, "%02x ", (int)(0xff & hash[i]));
239 log(LOG_DEBUG, "\n"); 239 log(LOG_DEBUG, "\n");
240} 240}
241 241
242#define WG_DUMP_HASH(name, hash) \ 242#define WG_DUMP_HASH(name, hash) \
243 wg_dump_hash(__func__, name, hash, WG_HASH_LEN) 243 wg_dump_hash(__func__, name, hash, WG_HASH_LEN)
244#define WG_DUMP_HASH48(name, hash) \ 244#define WG_DUMP_HASH48(name, hash) \
245 wg_dump_hash(__func__, name, hash, 48) 245 wg_dump_hash(__func__, name, hash, 48)
246#define WG_DUMP_BUF(buf, size) \ 246#define WG_DUMP_BUF(buf, size) \
247 wg_dump_buf(__func__, buf, size) 247 wg_dump_buf(__func__, buf, size)
248#else 248#else
249#define WG_DUMP_HASH(name, hash) __nothing 249#define WG_DUMP_HASH(name, hash) __nothing
250#define WG_DUMP_HASH48(name, hash) __nothing 250#define WG_DUMP_HASH48(name, hash) __nothing
251#define WG_DUMP_BUF(buf, size) __nothing 251#define WG_DUMP_BUF(buf, size) __nothing
252#endif /* WG_DEBUG_DUMP */ 252#endif /* WG_DEBUG_DUMP */
253 253
254#define WG_MTU 1420 254#define WG_MTU 1420
255#define WG_ALLOWEDIPS 16 255#define WG_ALLOWEDIPS 16
256 256
257#define CURVE25519_KEY_LEN 32 257#define CURVE25519_KEY_LEN 32
258#define TAI64N_LEN sizeof(uint32_t) * 3 258#define TAI64N_LEN sizeof(uint32_t) * 3
259#define POLY1305_AUTHTAG_LEN 16 259#define POLY1305_AUTHTAG_LEN 16
260#define HMAC_BLOCK_LEN 64 260#define HMAC_BLOCK_LEN 64
261 261
262/* [N] 4.1: "DHLEN must be 32 or greater." WireGuard chooses 32. */ 262/* [N] 4.1: "DHLEN must be 32 or greater." WireGuard chooses 32. */
263/* [N] 4.3: Hash functions */ 263/* [N] 4.3: Hash functions */
264#define NOISE_DHLEN 32 264#define NOISE_DHLEN 32
265/* [N] 4.3: "Must be 32 or 64." WireGuard chooses 32. */ 265/* [N] 4.3: "Must be 32 or 64." WireGuard chooses 32. */
266#define NOISE_HASHLEN 32 266#define NOISE_HASHLEN 32
267#define NOISE_BLOCKLEN 64 267#define NOISE_BLOCKLEN 64
268#define NOISE_HKDF_OUTPUT_LEN NOISE_HASHLEN 268#define NOISE_HKDF_OUTPUT_LEN NOISE_HASHLEN
269/* [N] 5.1: "k" */ 269/* [N] 5.1: "k" */
270#define NOISE_CIPHER_KEY_LEN 32 270#define NOISE_CIPHER_KEY_LEN 32
271/* 271/*
272 * [N] 9.2: "psk" 272 * [N] 9.2: "psk"
273 * "... psk is a 32-byte secret value provided by the application." 273 * "... psk is a 32-byte secret value provided by the application."
274 */ 274 */
275#define NOISE_PRESHARED_KEY_LEN 32 275#define NOISE_PRESHARED_KEY_LEN 32
276 276
277#define WG_STATIC_KEY_LEN CURVE25519_KEY_LEN 277#define WG_STATIC_KEY_LEN CURVE25519_KEY_LEN
278#define WG_TIMESTAMP_LEN TAI64N_LEN 278#define WG_TIMESTAMP_LEN TAI64N_LEN
279 279
280#define WG_PRESHARED_KEY_LEN NOISE_PRESHARED_KEY_LEN 280#define WG_PRESHARED_KEY_LEN NOISE_PRESHARED_KEY_LEN
281 281
282#define WG_COOKIE_LEN 16 282#define WG_COOKIE_LEN 16
283#define WG_MAC_LEN 16 283#define WG_MAC_LEN 16
284#define WG_RANDVAL_LEN 24 284#define WG_RANDVAL_LEN 24
285 285
286#define WG_EPHEMERAL_KEY_LEN CURVE25519_KEY_LEN 286#define WG_EPHEMERAL_KEY_LEN CURVE25519_KEY_LEN
287/* [N] 5.2: "ck: A chaining key of HASHLEN bytes" */ 287/* [N] 5.2: "ck: A chaining key of HASHLEN bytes" */
288#define WG_CHAINING_KEY_LEN NOISE_HASHLEN 288#define WG_CHAINING_KEY_LEN NOISE_HASHLEN
289/* [N] 5.2: "h: A hash output of HASHLEN bytes" */ 289/* [N] 5.2: "h: A hash output of HASHLEN bytes" */
290#define WG_HASH_LEN NOISE_HASHLEN 290#define WG_HASH_LEN NOISE_HASHLEN
291#define WG_CIPHER_KEY_LEN NOISE_CIPHER_KEY_LEN 291#define WG_CIPHER_KEY_LEN NOISE_CIPHER_KEY_LEN
292#define WG_DH_OUTPUT_LEN NOISE_DHLEN 292#define WG_DH_OUTPUT_LEN NOISE_DHLEN
293#define WG_KDF_OUTPUT_LEN NOISE_HKDF_OUTPUT_LEN 293#define WG_KDF_OUTPUT_LEN NOISE_HKDF_OUTPUT_LEN
294#define WG_AUTHTAG_LEN POLY1305_AUTHTAG_LEN 294#define WG_AUTHTAG_LEN POLY1305_AUTHTAG_LEN
295#define WG_DATA_KEY_LEN 32 295#define WG_DATA_KEY_LEN 32
296#define WG_SALT_LEN 24 296#define WG_SALT_LEN 24
297 297
298/* 298/*
299 * The protocol messages 299 * The protocol messages
300 */ 300 */
301struct wg_msg { 301struct wg_msg {
302 uint32_t wgm_type; 302 uint32_t wgm_type;
303} __packed; 303} __packed;
304 304
305/* [W] 5.4.2 First Message: Initiator to Responder */ 305/* [W] 5.4.2 First Message: Initiator to Responder */
306struct wg_msg_init { 306struct wg_msg_init {
307 uint32_t wgmi_type; 307 uint32_t wgmi_type;
308 uint32_t wgmi_sender; 308 uint32_t wgmi_sender;
309 uint8_t wgmi_ephemeral[WG_EPHEMERAL_KEY_LEN]; 309 uint8_t wgmi_ephemeral[WG_EPHEMERAL_KEY_LEN];
310 uint8_t wgmi_static[WG_STATIC_KEY_LEN + WG_AUTHTAG_LEN]; 310 uint8_t wgmi_static[WG_STATIC_KEY_LEN + WG_AUTHTAG_LEN];
311 uint8_t wgmi_timestamp[WG_TIMESTAMP_LEN + WG_AUTHTAG_LEN]; 311 uint8_t wgmi_timestamp[WG_TIMESTAMP_LEN + WG_AUTHTAG_LEN];
312 uint8_t wgmi_mac1[WG_MAC_LEN]; 312 uint8_t wgmi_mac1[WG_MAC_LEN];
313 uint8_t wgmi_mac2[WG_MAC_LEN]; 313 uint8_t wgmi_mac2[WG_MAC_LEN];
314} __packed; 314} __packed;
315 315
316/* [W] 5.4.3 Second Message: Responder to Initiator */ 316/* [W] 5.4.3 Second Message: Responder to Initiator */
317struct wg_msg_resp { 317struct wg_msg_resp {
318 uint32_t wgmr_type; 318 uint32_t wgmr_type;
319 uint32_t wgmr_sender; 319 uint32_t wgmr_sender;
320 uint32_t wgmr_receiver; 320 uint32_t wgmr_receiver;
321 uint8_t wgmr_ephemeral[WG_EPHEMERAL_KEY_LEN]; 321 uint8_t wgmr_ephemeral[WG_EPHEMERAL_KEY_LEN];
322 uint8_t wgmr_empty[0 + WG_AUTHTAG_LEN]; 322 uint8_t wgmr_empty[0 + WG_AUTHTAG_LEN];
323 uint8_t wgmr_mac1[WG_MAC_LEN]; 323 uint8_t wgmr_mac1[WG_MAC_LEN];
324 uint8_t wgmr_mac2[WG_MAC_LEN]; 324 uint8_t wgmr_mac2[WG_MAC_LEN];
325} __packed; 325} __packed;
326 326
327/* [W] 5.4.6 Subsequent Messages: Transport Data Messages */ 327/* [W] 5.4.6 Subsequent Messages: Transport Data Messages */
328struct wg_msg_data { 328struct wg_msg_data {
329 uint32_t wgmd_type; 329 uint32_t wgmd_type;
330 uint32_t wgmd_receiver; 330 uint32_t wgmd_receiver;
331 uint64_t wgmd_counter; 331 uint64_t wgmd_counter;
332 uint32_t wgmd_packet[0]; 332 uint32_t wgmd_packet[0];
333} __packed; 333} __packed;
334 334
335/* [W] 5.4.7 Under Load: Cookie Reply Message */ 335/* [W] 5.4.7 Under Load: Cookie Reply Message */
336struct wg_msg_cookie { 336struct wg_msg_cookie {
337 uint32_t wgmc_type; 337 uint32_t wgmc_type;
338 uint32_t wgmc_receiver; 338 uint32_t wgmc_receiver;
339 uint8_t wgmc_salt[WG_SALT_LEN]; 339 uint8_t wgmc_salt[WG_SALT_LEN];
340 uint8_t wgmc_cookie[WG_COOKIE_LEN + WG_AUTHTAG_LEN]; 340 uint8_t wgmc_cookie[WG_COOKIE_LEN + WG_AUTHTAG_LEN];
341} __packed; 341} __packed;
342 342
343#define WG_MSG_TYPE_INIT 1 343#define WG_MSG_TYPE_INIT 1
344#define WG_MSG_TYPE_RESP 2 344#define WG_MSG_TYPE_RESP 2
345#define WG_MSG_TYPE_COOKIE 3 345#define WG_MSG_TYPE_COOKIE 3
346#define WG_MSG_TYPE_DATA 4 346#define WG_MSG_TYPE_DATA 4
347#define WG_MSG_TYPE_MAX WG_MSG_TYPE_DATA 347#define WG_MSG_TYPE_MAX WG_MSG_TYPE_DATA
348 348
349/* Sliding windows */ 349/* Sliding windows */
350 350
351#define SLIWIN_BITS 2048u 351#define SLIWIN_BITS 2048u
352#define SLIWIN_TYPE uint32_t 352#define SLIWIN_TYPE uint32_t
353#define SLIWIN_BPW NBBY*sizeof(SLIWIN_TYPE) 353#define SLIWIN_BPW NBBY*sizeof(SLIWIN_TYPE)
354#define SLIWIN_WORDS howmany(SLIWIN_BITS, SLIWIN_BPW) 354#define SLIWIN_WORDS howmany(SLIWIN_BITS, SLIWIN_BPW)
355#define SLIWIN_NPKT (SLIWIN_BITS - NBBY*sizeof(SLIWIN_TYPE)) 355#define SLIWIN_NPKT (SLIWIN_BITS - NBBY*sizeof(SLIWIN_TYPE))
356 356
357struct sliwin { 357struct sliwin {
358 SLIWIN_TYPE B[SLIWIN_WORDS]; 358 SLIWIN_TYPE B[SLIWIN_WORDS];
359 uint64_t T; 359 uint64_t T;
360}; 360};
361 361
362static void 362static void
363sliwin_reset(struct sliwin *W) 363sliwin_reset(struct sliwin *W)
364{ 364{
365 365
366 memset(W, 0, sizeof(*W)); 366 memset(W, 0, sizeof(*W));
367} 367}
368 368
369static int 369static int
370sliwin_check_fast(const volatile struct sliwin *W, uint64_t S) 370sliwin_check_fast(const volatile struct sliwin *W, uint64_t S)
371{ 371{
372 372
373 /* 373 /*
374 * If it's more than one window older than the highest sequence 374 * If it's more than one window older than the highest sequence
375 * number we've seen, reject. 375 * number we've seen, reject.
376 */ 376 */
377#ifdef __HAVE_ATOMIC64_LOADSTORE 377#ifdef __HAVE_ATOMIC64_LOADSTORE
378 if (S + SLIWIN_NPKT < atomic_load_relaxed(&W->T)) 378 if (S + SLIWIN_NPKT < atomic_load_relaxed(&W->T))
379 return EAUTH; 379 return EAUTH;
380#endif 380#endif
381 381
382 /* 382 /*
383 * Otherwise, we need to take the lock to decide, so don't 383 * Otherwise, we need to take the lock to decide, so don't
384 * reject just yet. Caller must serialize a call to 384 * reject just yet. Caller must serialize a call to
385 * sliwin_update in this case. 385 * sliwin_update in this case.
386 */ 386 */
387 return 0; 387 return 0;
388} 388}
389 389
390static int 390static int
391sliwin_update(struct sliwin *W, uint64_t S) 391sliwin_update(struct sliwin *W, uint64_t S)
392{ 392{
393 unsigned word, bit; 393 unsigned word, bit;
394 394
395 /* 395 /*
396 * If it's more than one window older than the highest sequence 396 * If it's more than one window older than the highest sequence
397 * number we've seen, reject. 397 * number we've seen, reject.
398 */ 398 */
399 if (S + SLIWIN_NPKT < W->T) 399 if (S + SLIWIN_NPKT < W->T)
400 return EAUTH; 400 return EAUTH;
401 401
402 /* 402 /*
403 * If it's higher than the highest sequence number we've seen, 403 * If it's higher than the highest sequence number we've seen,
404 * advance the window. 404 * advance the window.
405 */ 405 */
406 if (S > W->T) { 406 if (S > W->T) {
407 uint64_t i = W->T / SLIWIN_BPW; 407 uint64_t i = W->T / SLIWIN_BPW;
408 uint64_t j = S / SLIWIN_BPW; 408 uint64_t j = S / SLIWIN_BPW;
409 unsigned k; 409 unsigned k;
410 410
411 for (k = 0; k < MIN(j - i, SLIWIN_WORDS); k++) 411 for (k = 0; k < MIN(j - i, SLIWIN_WORDS); k++)
412 W->B[(i + k + 1) % SLIWIN_WORDS] = 0; 412 W->B[(i + k + 1) % SLIWIN_WORDS] = 0;
413#ifdef __HAVE_ATOMIC64_LOADSTORE 413#ifdef __HAVE_ATOMIC64_LOADSTORE
414 atomic_store_relaxed(&W->T, S); 414 atomic_store_relaxed(&W->T, S);
415#else 415#else
416 W->T = S; 416 W->T = S;
417#endif 417#endif
418 } 418 }
419 419
420 /* Test and set the bit -- if already set, reject. */ 420 /* Test and set the bit -- if already set, reject. */
421 word = (S / SLIWIN_BPW) % SLIWIN_WORDS; 421 word = (S / SLIWIN_BPW) % SLIWIN_WORDS;
422 bit = S % SLIWIN_BPW; 422 bit = S % SLIWIN_BPW;
423 if (W->B[word] & (1UL << bit)) 423 if (W->B[word] & (1UL << bit))
424 return EAUTH; 424 return EAUTH;
425 W->B[word] |= 1UL << bit; 425 W->B[word] |= 1UL << bit;
426 426
427 /* Accept! */ 427 /* Accept! */
428 return 0; 428 return 0;
429} 429}
430 430
431struct wg_worker { 431struct wg_worker {
432 kmutex_t wgw_lock; 432 kmutex_t wgw_lock;
433 kcondvar_t wgw_cv; 433 kcondvar_t wgw_cv;
434 bool wgw_todie; 434 bool wgw_todie;
435 struct socket *wgw_so4; 435 struct socket *wgw_so4;
436 struct socket *wgw_so6; 436 struct socket *wgw_so6;
437 int wgw_wakeup_reasons; 437 int wgw_wakeup_reasons;
438#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 __BIT(0) 438#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 __BIT(0)
439#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6 __BIT(1) 439#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6 __BIT(1)
440#define WG_WAKEUP_REASON_PEER __BIT(2) 440#define WG_WAKEUP_REASON_PEER __BIT(2)
441}; 441};
442 442
443struct wg_session { 443struct wg_session {
444 struct wg_peer *wgs_peer; 444 struct wg_peer *wgs_peer;
445 struct psref_target 445 struct psref_target
446 wgs_psref; 446 wgs_psref;
447 kmutex_t *wgs_lock; 447 kmutex_t *wgs_lock;
448 448
449 int wgs_state; 449 int wgs_state;
450#define WGS_STATE_UNKNOWN 0 450#define WGS_STATE_UNKNOWN 0
451#define WGS_STATE_INIT_ACTIVE 1 451#define WGS_STATE_INIT_ACTIVE 1
452#define WGS_STATE_INIT_PASSIVE 2 452#define WGS_STATE_INIT_PASSIVE 2
453#define WGS_STATE_ESTABLISHED 3 453#define WGS_STATE_ESTABLISHED 3
454#define WGS_STATE_DESTROYING 4 454#define WGS_STATE_DESTROYING 4
455 455
456 time_t wgs_time_established; 456 time_t wgs_time_established;
457 time_t wgs_time_last_data_sent; 457 time_t wgs_time_last_data_sent;
458 bool wgs_is_initiator; 458 bool wgs_is_initiator;
459 459
460 uint32_t wgs_sender_index; 460 uint32_t wgs_sender_index;
461 uint32_t wgs_receiver_index; 461 uint32_t wgs_receiver_index;
462#ifdef __HAVE_ATOMIC64_LOADSTORE 462#ifdef __HAVE_ATOMIC64_LOADSTORE
463 volatile uint64_t 463 volatile uint64_t
464 wgs_send_counter; 464 wgs_send_counter;
465#else 465#else
466 kmutex_t wgs_send_counter_lock; 466 kmutex_t wgs_send_counter_lock;
467 uint64_t wgs_send_counter; 467 uint64_t wgs_send_counter;
468#endif 468#endif
469 469
470 struct { 470 struct {
471 kmutex_t lock; 471 kmutex_t lock;
472 struct sliwin window; 472 struct sliwin window;
473 } *wgs_recvwin; 473 } *wgs_recvwin;
474 474
475 uint8_t wgs_handshake_hash[WG_HASH_LEN]; 475 uint8_t wgs_handshake_hash[WG_HASH_LEN];
476 uint8_t wgs_chaining_key[WG_CHAINING_KEY_LEN]; 476 uint8_t wgs_chaining_key[WG_CHAINING_KEY_LEN];
477 uint8_t wgs_ephemeral_key_pub[WG_EPHEMERAL_KEY_LEN]; 477 uint8_t wgs_ephemeral_key_pub[WG_EPHEMERAL_KEY_LEN];
478 uint8_t wgs_ephemeral_key_priv[WG_EPHEMERAL_KEY_LEN]; 478 uint8_t wgs_ephemeral_key_priv[WG_EPHEMERAL_KEY_LEN];
479 uint8_t wgs_ephemeral_key_peer[WG_EPHEMERAL_KEY_LEN]; 479 uint8_t wgs_ephemeral_key_peer[WG_EPHEMERAL_KEY_LEN];
480 uint8_t wgs_tkey_send[WG_DATA_KEY_LEN]; 480 uint8_t wgs_tkey_send[WG_DATA_KEY_LEN];
481 uint8_t wgs_tkey_recv[WG_DATA_KEY_LEN]; 481 uint8_t wgs_tkey_recv[WG_DATA_KEY_LEN];
482}; 482};
483 483
484struct wg_sockaddr { 484struct wg_sockaddr {
485 union { 485 union {
486 struct sockaddr_storage _ss; 486 struct sockaddr_storage _ss;
487 struct sockaddr _sa; 487 struct sockaddr _sa;
488 struct sockaddr_in _sin; 488 struct sockaddr_in _sin;
489 struct sockaddr_in6 _sin6; 489 struct sockaddr_in6 _sin6;
490 }; 490 };
491 struct psref_target wgsa_psref; 491 struct psref_target wgsa_psref;
492}; 492};
493 493
494#define wgsatoss(wgsa) (&(wgsa)->_ss) 494#define wgsatoss(wgsa) (&(wgsa)->_ss)
495#define wgsatosa(wgsa) (&(wgsa)->_sa) 495#define wgsatosa(wgsa) (&(wgsa)->_sa)
496#define wgsatosin(wgsa) (&(wgsa)->_sin) 496#define wgsatosin(wgsa) (&(wgsa)->_sin)
497#define wgsatosin6(wgsa) (&(wgsa)->_sin6) 497#define wgsatosin6(wgsa) (&(wgsa)->_sin6)
498 498
499#define wgsa_family(wgsa) (wgsatosa(wgsa)->sa_family) 499#define wgsa_family(wgsa) (wgsatosa(wgsa)->sa_family)
500 500
501struct wg_peer; 501struct wg_peer;
502struct wg_allowedip { 502struct wg_allowedip {
503 struct radix_node wga_nodes[2]; 503 struct radix_node wga_nodes[2];
504 struct wg_sockaddr _wga_sa_addr; 504 struct wg_sockaddr _wga_sa_addr;
505 struct wg_sockaddr _wga_sa_mask; 505 struct wg_sockaddr _wga_sa_mask;
506#define wga_sa_addr _wga_sa_addr._sa 506#define wga_sa_addr _wga_sa_addr._sa
507#define wga_sa_mask _wga_sa_mask._sa 507#define wga_sa_mask _wga_sa_mask._sa
508 508
509 int wga_family; 509 int wga_family;
510 uint8_t wga_cidr; 510 uint8_t wga_cidr;
511 union { 511 union {
512 struct in_addr _ip4; 512 struct in_addr _ip4;
513 struct in6_addr _ip6; 513 struct in6_addr _ip6;
514 } wga_addr; 514 } wga_addr;
515#define wga_addr4 wga_addr._ip4 515#define wga_addr4 wga_addr._ip4
516#define wga_addr6 wga_addr._ip6 516#define wga_addr6 wga_addr._ip6
517 517
518 struct wg_peer *wga_peer; 518 struct wg_peer *wga_peer;
519}; 519};
520 520
521typedef uint8_t wg_timestamp_t[WG_TIMESTAMP_LEN]; 521typedef uint8_t wg_timestamp_t[WG_TIMESTAMP_LEN];
522 522
523struct wg_ppsratecheck { 523struct wg_ppsratecheck {
524 struct timeval wgprc_lasttime; 524 struct timeval wgprc_lasttime;
525 int wgprc_curpps; 525 int wgprc_curpps;
526}; 526};
527 527
528struct wg_softc; 528struct wg_softc;
529struct wg_peer { 529struct wg_peer {
530 struct wg_softc *wgp_sc; 530 struct wg_softc *wgp_sc;
531 char wgp_name[WG_PEER_NAME_MAXLEN + 1]; 531 char wgp_name[WG_PEER_NAME_MAXLEN + 1];
532 struct pslist_entry wgp_peerlist_entry; 532 struct pslist_entry wgp_peerlist_entry;
533 pserialize_t wgp_psz; 533 pserialize_t wgp_psz;
534 struct psref_target wgp_psref; 534 struct psref_target wgp_psref;
535 kmutex_t *wgp_lock; 535 kmutex_t *wgp_lock;
536 536
537 uint8_t wgp_pubkey[WG_STATIC_KEY_LEN]; 537 uint8_t wgp_pubkey[WG_STATIC_KEY_LEN];
538 struct wg_sockaddr *wgp_endpoint; 538 struct wg_sockaddr *wgp_endpoint;
539 struct wg_sockaddr *wgp_endpoint0; 539 struct wg_sockaddr *wgp_endpoint0;
540 bool wgp_endpoint_changing; 540 bool wgp_endpoint_changing;
541 bool wgp_endpoint_available; 541 bool wgp_endpoint_available;
542 542
543 /* The preshared key (optional) */ 543 /* The preshared key (optional) */
544 uint8_t wgp_psk[WG_PRESHARED_KEY_LEN]; 544 uint8_t wgp_psk[WG_PRESHARED_KEY_LEN];
545 545
546 int wgp_state; 546 int wgp_state;
547#define WGP_STATE_INIT 0 547#define WGP_STATE_INIT 0
548#define WGP_STATE_ESTABLISHED 1 548#define WGP_STATE_ESTABLISHED 1
549#define WGP_STATE_GIVEUP 2 549#define WGP_STATE_GIVEUP 2
550#define WGP_STATE_DESTROYING 3 550#define WGP_STATE_DESTROYING 3
551 551
552 void *wgp_si; 552 void *wgp_si;
553 pcq_t *wgp_q; 553 pcq_t *wgp_q;
554 554
555 struct wg_session *wgp_session_stable; 555 struct wg_session *wgp_session_stable;
556 struct wg_session *wgp_session_unstable; 556 struct wg_session *wgp_session_unstable;
557 557
558 /* timestamp in big-endian */ 558 /* timestamp in big-endian */
559 wg_timestamp_t wgp_timestamp_latest_init; 559 wg_timestamp_t wgp_timestamp_latest_init;
560 560
561 struct timespec wgp_last_handshake_time; 561 struct timespec wgp_last_handshake_time;
562 562
563 callout_t wgp_rekey_timer; 563 callout_t wgp_rekey_timer;
564 callout_t wgp_handshake_timeout_timer; 564 callout_t wgp_handshake_timeout_timer;
565 callout_t wgp_session_dtor_timer; 565 callout_t wgp_session_dtor_timer;
566 566
567 time_t wgp_handshake_start_time; 567 time_t wgp_handshake_start_time;
568 568
569 int wgp_n_allowedips; 569 int wgp_n_allowedips;
570 struct wg_allowedip wgp_allowedips[WG_ALLOWEDIPS]; 570 struct wg_allowedip wgp_allowedips[WG_ALLOWEDIPS];
571 571
572 time_t wgp_latest_cookie_time; 572 time_t wgp_latest_cookie_time;
573 uint8_t wgp_latest_cookie[WG_COOKIE_LEN]; 573 uint8_t wgp_latest_cookie[WG_COOKIE_LEN];
574 uint8_t wgp_last_sent_mac1[WG_MAC_LEN]; 574 uint8_t wgp_last_sent_mac1[WG_MAC_LEN];
575 bool wgp_last_sent_mac1_valid; 575 bool wgp_last_sent_mac1_valid;
576 uint8_t wgp_last_sent_cookie[WG_COOKIE_LEN]; 576 uint8_t wgp_last_sent_cookie[WG_COOKIE_LEN];
577 bool wgp_last_sent_cookie_valid; 577 bool wgp_last_sent_cookie_valid;
578 578
579 time_t wgp_last_msg_received_time[WG_MSG_TYPE_MAX]; 579 time_t wgp_last_msg_received_time[WG_MSG_TYPE_MAX];
580 580
581 time_t wgp_last_genrandval_time; 581 time_t wgp_last_genrandval_time;
582 uint32_t wgp_randval; 582 uint32_t wgp_randval;
583 583
584 struct wg_ppsratecheck wgp_ppsratecheck; 584 struct wg_ppsratecheck wgp_ppsratecheck;
585 585
586 volatile unsigned int wgp_tasks; 586 volatile unsigned int wgp_tasks;
587#define WGP_TASK_SEND_INIT_MESSAGE __BIT(0) 587#define WGP_TASK_SEND_INIT_MESSAGE __BIT(0)
588#define WGP_TASK_ENDPOINT_CHANGED __BIT(1) 588#define WGP_TASK_ENDPOINT_CHANGED __BIT(1)
589#define WGP_TASK_SEND_KEEPALIVE_MESSAGE __BIT(2) 589#define WGP_TASK_SEND_KEEPALIVE_MESSAGE __BIT(2)
590#define WGP_TASK_DESTROY_PREV_SESSION __BIT(3) 590#define WGP_TASK_DESTROY_PREV_SESSION __BIT(3)
591}; 591};
592 592
593struct wg_ops; 593struct wg_ops;
594 594
595struct wg_softc { 595struct wg_softc {
596 struct ifnet wg_if; 596 struct ifnet wg_if;
597 LIST_ENTRY(wg_softc) wg_list; 597 LIST_ENTRY(wg_softc) wg_list;
598 kmutex_t *wg_lock; 598 kmutex_t *wg_lock;
599 krwlock_t *wg_rwlock; 599 krwlock_t *wg_rwlock;
600 600
601 uint8_t wg_privkey[WG_STATIC_KEY_LEN]; 601 uint8_t wg_privkey[WG_STATIC_KEY_LEN];
602 uint8_t wg_pubkey[WG_STATIC_KEY_LEN]; 602 uint8_t wg_pubkey[WG_STATIC_KEY_LEN];
603 603
604 int wg_npeers; 604 int wg_npeers;
605 struct pslist_head wg_peers; 605 struct pslist_head wg_peers;
606 struct thmap *wg_peers_bypubkey; 606 struct thmap *wg_peers_bypubkey;
607 struct thmap *wg_peers_byname; 607 struct thmap *wg_peers_byname;
608 struct thmap *wg_sessions_byindex; 608 struct thmap *wg_sessions_byindex;
609 uint16_t wg_listen_port; 609 uint16_t wg_listen_port;
610 610
611 struct wg_worker *wg_worker; 611 struct wg_worker *wg_worker;
612 lwp_t *wg_worker_lwp; 612 lwp_t *wg_worker_lwp;
613 613
614 struct radix_node_head *wg_rtable_ipv4; 614 struct radix_node_head *wg_rtable_ipv4;
615 struct radix_node_head *wg_rtable_ipv6; 615 struct radix_node_head *wg_rtable_ipv6;
616 616
617 struct wg_ppsratecheck wg_ppsratecheck; 617 struct wg_ppsratecheck wg_ppsratecheck;
618 618
619 struct wg_ops *wg_ops; 619 struct wg_ops *wg_ops;
620 620
621#ifdef WG_RUMPKERNEL 621#ifdef WG_RUMPKERNEL
622 struct wg_user *wg_user; 622 struct wg_user *wg_user;
623#endif 623#endif
624}; 624};
625 625
626/* [W] 6.1 Preliminaries */ 626/* [W] 6.1 Preliminaries */
627#define WG_REKEY_AFTER_MESSAGES (1ULL << 60) 627#define WG_REKEY_AFTER_MESSAGES (1ULL << 60)
628#define WG_REJECT_AFTER_MESSAGES (UINT64_MAX - (1 << 13)) 628#define WG_REJECT_AFTER_MESSAGES (UINT64_MAX - (1 << 13))
629#define WG_REKEY_AFTER_TIME 120 629#define WG_REKEY_AFTER_TIME 120
630#define WG_REJECT_AFTER_TIME 180 630#define WG_REJECT_AFTER_TIME 180
631#define WG_REKEY_ATTEMPT_TIME 90 631#define WG_REKEY_ATTEMPT_TIME 90
632#define WG_REKEY_TIMEOUT 5 632#define WG_REKEY_TIMEOUT 5
633#define WG_KEEPALIVE_TIMEOUT 10 633#define WG_KEEPALIVE_TIMEOUT 10
634 634
635#define WG_COOKIE_TIME 120 635#define WG_COOKIE_TIME 120
636#define WG_RANDVAL_TIME (2 * 60) 636#define WG_RANDVAL_TIME (2 * 60)
637 637
638static uint64_t wg_rekey_after_messages = WG_REKEY_AFTER_MESSAGES; 638static uint64_t wg_rekey_after_messages = WG_REKEY_AFTER_MESSAGES;
639static uint64_t wg_reject_after_messages = WG_REJECT_AFTER_MESSAGES; 639static uint64_t wg_reject_after_messages = WG_REJECT_AFTER_MESSAGES;
640static unsigned wg_rekey_after_time = WG_REKEY_AFTER_TIME; 640static unsigned wg_rekey_after_time = WG_REKEY_AFTER_TIME;
641static unsigned wg_reject_after_time = WG_REJECT_AFTER_TIME; 641static unsigned wg_reject_after_time = WG_REJECT_AFTER_TIME;
642static unsigned wg_rekey_attempt_time = WG_REKEY_ATTEMPT_TIME; 642static unsigned wg_rekey_attempt_time = WG_REKEY_ATTEMPT_TIME;
643static unsigned wg_rekey_timeout = WG_REKEY_TIMEOUT; 643static unsigned wg_rekey_timeout = WG_REKEY_TIMEOUT;
644static unsigned wg_keepalive_timeout = WG_KEEPALIVE_TIMEOUT; 644static unsigned wg_keepalive_timeout = WG_KEEPALIVE_TIMEOUT;
645 645
646static struct mbuf * 646static struct mbuf *
647 wg_get_mbuf(size_t, size_t); 647 wg_get_mbuf(size_t, size_t);
648 648
649static void wg_wakeup_worker(struct wg_worker *, int); 649static void wg_wakeup_worker(struct wg_worker *, int);
650 650
651static int wg_send_data_msg(struct wg_peer *, struct wg_session *, 651static int wg_send_data_msg(struct wg_peer *, struct wg_session *,
652 struct mbuf *); 652 struct mbuf *);
653static int wg_send_cookie_msg(struct wg_softc *, struct wg_peer *, 653static int wg_send_cookie_msg(struct wg_softc *, struct wg_peer *,
654 const uint32_t, const uint8_t [], const struct sockaddr *); 654 const uint32_t, const uint8_t [], const struct sockaddr *);
655static int wg_send_handshake_msg_resp(struct wg_softc *, 655static int wg_send_handshake_msg_resp(struct wg_softc *,
656 struct wg_peer *, const struct wg_msg_init *); 656 struct wg_peer *, const struct wg_msg_init *);
657static void wg_send_keepalive_msg(struct wg_peer *, struct wg_session *); 657static void wg_send_keepalive_msg(struct wg_peer *, struct wg_session *);
658 658
659static struct wg_peer * 659static struct wg_peer *
660 wg_pick_peer_by_sa(struct wg_softc *, const struct sockaddr *, 660 wg_pick_peer_by_sa(struct wg_softc *, const struct sockaddr *,
661 struct psref *); 661 struct psref *);
662static struct wg_peer * 662static struct wg_peer *
663 wg_lookup_peer_by_pubkey(struct wg_softc *, 663 wg_lookup_peer_by_pubkey(struct wg_softc *,
664 const uint8_t [], struct psref *); 664 const uint8_t [], struct psref *);
665 665
666static struct wg_session * 666static struct wg_session *
667 wg_lookup_session_by_index(struct wg_softc *, 667 wg_lookup_session_by_index(struct wg_softc *,
668 const uint32_t, struct psref *); 668 const uint32_t, struct psref *);
669 669
670static void wg_update_endpoint_if_necessary(struct wg_peer *, 670static void wg_update_endpoint_if_necessary(struct wg_peer *,
671 const struct sockaddr *); 671 const struct sockaddr *);
672 672
673static void wg_schedule_rekey_timer(struct wg_peer *); 673static void wg_schedule_rekey_timer(struct wg_peer *);
674static void wg_schedule_session_dtor_timer(struct wg_peer *); 674static void wg_schedule_session_dtor_timer(struct wg_peer *);
675 675
676static bool wg_is_underload(struct wg_softc *, struct wg_peer *, int); 676static bool wg_is_underload(struct wg_softc *, struct wg_peer *, int);
677static void wg_calculate_keys(struct wg_session *, const bool); 677static void wg_calculate_keys(struct wg_session *, const bool);
678 678
679static void wg_clear_states(struct wg_session *); 679static void wg_clear_states(struct wg_session *);
680 680
681static void wg_get_peer(struct wg_peer *, struct psref *); 681static void wg_get_peer(struct wg_peer *, struct psref *);
682static void wg_put_peer(struct wg_peer *, struct psref *); 682static void wg_put_peer(struct wg_peer *, struct psref *);
683 683
684static int wg_send_so(struct wg_peer *, struct mbuf *); 684static int wg_send_so(struct wg_peer *, struct mbuf *);
685static int wg_send_udp(struct wg_peer *, struct mbuf *); 685static int wg_send_udp(struct wg_peer *, struct mbuf *);
686static int wg_output(struct ifnet *, struct mbuf *, 686static int wg_output(struct ifnet *, struct mbuf *,
687 const struct sockaddr *, const struct rtentry *); 687 const struct sockaddr *, const struct rtentry *);
688static void wg_input(struct ifnet *, struct mbuf *, const int); 688static void wg_input(struct ifnet *, struct mbuf *, const int);
689static int wg_ioctl(struct ifnet *, u_long, void *); 689static int wg_ioctl(struct ifnet *, u_long, void *);
690static int wg_bind_port(struct wg_softc *, const uint16_t); 690static int wg_bind_port(struct wg_softc *, const uint16_t);
691static int wg_init(struct ifnet *); 691static int wg_init(struct ifnet *);
692static void wg_stop(struct ifnet *, int); 692static void wg_stop(struct ifnet *, int);
693 693
694static int wg_clone_create(struct if_clone *, int); 694static int wg_clone_create(struct if_clone *, int);
695static int wg_clone_destroy(struct ifnet *); 695static int wg_clone_destroy(struct ifnet *);
696 696
697struct wg_ops { 697struct wg_ops {
698 int (*send_hs_msg)(struct wg_peer *, struct mbuf *); 698 int (*send_hs_msg)(struct wg_peer *, struct mbuf *);
699 int (*send_data_msg)(struct wg_peer *, struct mbuf *); 699 int (*send_data_msg)(struct wg_peer *, struct mbuf *);
700 void (*input)(struct ifnet *, struct mbuf *, const int); 700 void (*input)(struct ifnet *, struct mbuf *, const int);
701 int (*bind_port)(struct wg_softc *, const uint16_t); 701 int (*bind_port)(struct wg_softc *, const uint16_t);
702}; 702};
703 703
704struct wg_ops wg_ops_rumpkernel = { 704struct wg_ops wg_ops_rumpkernel = {
705 .send_hs_msg = wg_send_so, 705 .send_hs_msg = wg_send_so,
706 .send_data_msg = wg_send_udp, 706 .send_data_msg = wg_send_udp,
707 .input = wg_input, 707 .input = wg_input,
708 .bind_port = wg_bind_port, 708 .bind_port = wg_bind_port,
709}; 709};
710 710
711#ifdef WG_RUMPKERNEL 711#ifdef WG_RUMPKERNEL
712static bool wg_user_mode(struct wg_softc *); 712static bool wg_user_mode(struct wg_softc *);
713static int wg_ioctl_linkstr(struct wg_softc *, struct ifdrv *); 713static int wg_ioctl_linkstr(struct wg_softc *, struct ifdrv *);
714 714
715static int wg_send_user(struct wg_peer *, struct mbuf *); 715static int wg_send_user(struct wg_peer *, struct mbuf *);
716static void wg_input_user(struct ifnet *, struct mbuf *, const int); 716static void wg_input_user(struct ifnet *, struct mbuf *, const int);
717static int wg_bind_port_user(struct wg_softc *, const uint16_t); 717static int wg_bind_port_user(struct wg_softc *, const uint16_t);
718 718
719struct wg_ops wg_ops_rumpuser = { 719struct wg_ops wg_ops_rumpuser = {
720 .send_hs_msg = wg_send_user, 720 .send_hs_msg = wg_send_user,
721 .send_data_msg = wg_send_user, 721 .send_data_msg = wg_send_user,
722 .input = wg_input_user, 722 .input = wg_input_user,
723 .bind_port = wg_bind_port_user, 723 .bind_port = wg_bind_port_user,
724}; 724};
725#endif 725#endif
726 726
727#define WG_PEER_READER_FOREACH(wgp, wg) \ 727#define WG_PEER_READER_FOREACH(wgp, wg) \
728 PSLIST_READER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \ 728 PSLIST_READER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \
729 wgp_peerlist_entry) 729 wgp_peerlist_entry)
730#define WG_PEER_WRITER_FOREACH(wgp, wg) \ 730#define WG_PEER_WRITER_FOREACH(wgp, wg) \
731 PSLIST_WRITER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \ 731 PSLIST_WRITER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \
732 wgp_peerlist_entry) 732 wgp_peerlist_entry)
733#define WG_PEER_WRITER_INSERT_HEAD(wgp, wg) \ 733#define WG_PEER_WRITER_INSERT_HEAD(wgp, wg) \
734 PSLIST_WRITER_INSERT_HEAD(&(wg)->wg_peers, (wgp), wgp_peerlist_entry) 734 PSLIST_WRITER_INSERT_HEAD(&(wg)->wg_peers, (wgp), wgp_peerlist_entry)
735#define WG_PEER_WRITER_REMOVE(wgp) \ 735#define WG_PEER_WRITER_REMOVE(wgp) \
736 PSLIST_WRITER_REMOVE((wgp), wgp_peerlist_entry) 736 PSLIST_WRITER_REMOVE((wgp), wgp_peerlist_entry)
737 737
738struct wg_route { 738struct wg_route {
739 struct radix_node wgr_nodes[2]; 739 struct radix_node wgr_nodes[2];
740 struct wg_peer *wgr_peer; 740 struct wg_peer *wgr_peer;
741}; 741};
742 742
743static struct radix_node_head * 743static struct radix_node_head *
744wg_rnh(struct wg_softc *wg, const int family) 744wg_rnh(struct wg_softc *wg, const int family)
745{ 745{
746 746
747 switch (family) { 747 switch (family) {
748 case AF_INET: 748 case AF_INET:
749 return wg->wg_rtable_ipv4; 749 return wg->wg_rtable_ipv4;
750#ifdef INET6 750#ifdef INET6
751 case AF_INET6: 751 case AF_INET6:
752 return wg->wg_rtable_ipv6; 752 return wg->wg_rtable_ipv6;
753#endif 753#endif
754 default: 754 default:
755 return NULL; 755 return NULL;
756 } 756 }
757} 757}
758 758
759 759
760/* 760/*
761 * Global variables 761 * Global variables
762 */ 762 */
763LIST_HEAD(wg_sclist, wg_softc); 763LIST_HEAD(wg_sclist, wg_softc);
764static struct { 764static struct {
765 struct wg_sclist list; 765 struct wg_sclist list;
766 kmutex_t lock; 766 kmutex_t lock;
767} wg_softcs __cacheline_aligned; 767} wg_softcs __cacheline_aligned;
768 768
769struct psref_class *wg_psref_class __read_mostly; 769struct psref_class *wg_psref_class __read_mostly;
770 770
771static struct if_clone wg_cloner = 771static struct if_clone wg_cloner =
772 IF_CLONE_INITIALIZER("wg", wg_clone_create, wg_clone_destroy); 772 IF_CLONE_INITIALIZER("wg", wg_clone_create, wg_clone_destroy);
773 773
774 774
775void wgattach(int); 775void wgattach(int);
776/* ARGSUSED */ 776/* ARGSUSED */
777void 777void
778wgattach(int count) 778wgattach(int count)
779{ 779{
780 /* 780 /*
781 * Nothing to do here, initialization is handled by the 781 * Nothing to do here, initialization is handled by the
782 * module initialization code in wginit() below). 782 * module initialization code in wginit() below).
783 */ 783 */
784} 784}
785 785
786static void 786static void
787wginit(void) 787wginit(void)
788{ 788{
789 789
790 wg_psref_class = psref_class_create("wg", IPL_SOFTNET); 790 wg_psref_class = psref_class_create("wg", IPL_SOFTNET);
791 791
792 mutex_init(&wg_softcs.lock, MUTEX_DEFAULT, IPL_NONE); 792 mutex_init(&wg_softcs.lock, MUTEX_DEFAULT, IPL_NONE);
793 LIST_INIT(&wg_softcs.list); 793 LIST_INIT(&wg_softcs.list);
794 if_clone_attach(&wg_cloner); 794 if_clone_attach(&wg_cloner);
795} 795}
796 796
797static int 797static int
798wgdetach(void) 798wgdetach(void)
799{ 799{
800 int error = 0; 800 int error = 0;
801 801
802 mutex_enter(&wg_softcs.lock); 802 mutex_enter(&wg_softcs.lock);
803 if (!LIST_EMPTY(&wg_softcs.list)) { 803 if (!LIST_EMPTY(&wg_softcs.list)) {
804 mutex_exit(&wg_softcs.lock); 804 mutex_exit(&wg_softcs.lock);
805 error = EBUSY; 805 error = EBUSY;
806 } 806 }
807 807
808 if (error == 0) { 808 if (error == 0) {
809 psref_class_destroy(wg_psref_class); 809 psref_class_destroy(wg_psref_class);
810 810
811 if_clone_detach(&wg_cloner); 811 if_clone_detach(&wg_cloner);
812 } 812 }
813 813
814 return error; 814 return error;
815} 815}
816 816
817static void 817static void
818wg_init_key_and_hash(uint8_t ckey[WG_CHAINING_KEY_LEN], 818wg_init_key_and_hash(uint8_t ckey[WG_CHAINING_KEY_LEN],
819 uint8_t hash[WG_HASH_LEN]) 819 uint8_t hash[WG_HASH_LEN])
820{ 820{
821 /* [W] 5.4: CONSTRUCTION */ 821 /* [W] 5.4: CONSTRUCTION */
822 const char *signature = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; 822 const char *signature = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s";
823 /* [W] 5.4: IDENTIFIER */ 823 /* [W] 5.4: IDENTIFIER */
824 const char *id = "WireGuard v1 zx2c4 Jason@zx2c4.com"; 824 const char *id = "WireGuard v1 zx2c4 Jason@zx2c4.com";
825 struct blake2s state; 825 struct blake2s state;
826 826
827 blake2s(ckey, WG_CHAINING_KEY_LEN, NULL, 0, 827 blake2s(ckey, WG_CHAINING_KEY_LEN, NULL, 0,
828 signature, strlen(signature)); 828 signature, strlen(signature));
829 829
830 CTASSERT(WG_HASH_LEN == WG_CHAINING_KEY_LEN); 830 CTASSERT(WG_HASH_LEN == WG_CHAINING_KEY_LEN);
831 memcpy(hash, ckey, WG_CHAINING_KEY_LEN); 831 memcpy(hash, ckey, WG_CHAINING_KEY_LEN);
832 832
833 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 833 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
834 blake2s_update(&state, ckey, WG_CHAINING_KEY_LEN); 834 blake2s_update(&state, ckey, WG_CHAINING_KEY_LEN);
835 blake2s_update(&state, id, strlen(id)); 835 blake2s_update(&state, id, strlen(id));
836 blake2s_final(&state, hash); 836 blake2s_final(&state, hash);
837 837
838 WG_DUMP_HASH("ckey", ckey); 838 WG_DUMP_HASH("ckey", ckey);
839 WG_DUMP_HASH("hash", hash); 839 WG_DUMP_HASH("hash", hash);
840} 840}
841 841
842static void 842static void
843wg_algo_hash(uint8_t hash[WG_HASH_LEN], const uint8_t input[], 843wg_algo_hash(uint8_t hash[WG_HASH_LEN], const uint8_t input[],
844 const size_t inputsize) 844 const size_t inputsize)
845{ 845{
846 struct blake2s state; 846 struct blake2s state;
847 847
848 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 848 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
849 blake2s_update(&state, hash, WG_HASH_LEN); 849 blake2s_update(&state, hash, WG_HASH_LEN);
850 blake2s_update(&state, input, inputsize); 850 blake2s_update(&state, input, inputsize);
851 blake2s_final(&state, hash); 851 blake2s_final(&state, hash);
852} 852}
853 853
854static void 854static void
855wg_algo_mac(uint8_t out[], const size_t outsize, 855wg_algo_mac(uint8_t out[], const size_t outsize,
856 const uint8_t key[], const size_t keylen, 856 const uint8_t key[], const size_t keylen,
857 const uint8_t input1[], const size_t input1len, 857 const uint8_t input1[], const size_t input1len,
858 const uint8_t input2[], const size_t input2len) 858 const uint8_t input2[], const size_t input2len)
859{ 859{
860 struct blake2s state; 860 struct blake2s state;
861 861
862 blake2s_init(&state, outsize, key, keylen); 862 blake2s_init(&state, outsize, key, keylen);
863 863
864 blake2s_update(&state, input1, input1len); 864 blake2s_update(&state, input1, input1len);
865 if (input2 != NULL) 865 if (input2 != NULL)
866 blake2s_update(&state, input2, input2len); 866 blake2s_update(&state, input2, input2len);
867 blake2s_final(&state, out); 867 blake2s_final(&state, out);
868} 868}
869 869
870static void 870static void
871wg_algo_mac_mac1(uint8_t out[], const size_t outsize, 871wg_algo_mac_mac1(uint8_t out[], const size_t outsize,
872 const uint8_t input1[], const size_t input1len, 872 const uint8_t input1[], const size_t input1len,
873 const uint8_t input2[], const size_t input2len) 873 const uint8_t input2[], const size_t input2len)
874{ 874{
875 struct blake2s state; 875 struct blake2s state;
876 /* [W] 5.4: LABEL-MAC1 */ 876 /* [W] 5.4: LABEL-MAC1 */
877 const char *label = "mac1----"; 877 const char *label = "mac1----";
878 uint8_t key[WG_HASH_LEN]; 878 uint8_t key[WG_HASH_LEN];
879 879
880 blake2s_init(&state, sizeof(key), NULL, 0); 880 blake2s_init(&state, sizeof(key), NULL, 0);
881 blake2s_update(&state, label, strlen(label)); 881 blake2s_update(&state, label, strlen(label));
882 blake2s_update(&state, input1, input1len); 882 blake2s_update(&state, input1, input1len);
883 blake2s_final(&state, key); 883 blake2s_final(&state, key);
884 884
885 blake2s_init(&state, outsize, key, sizeof(key)); 885 blake2s_init(&state, outsize, key, sizeof(key));
886 if (input2 != NULL) 886 if (input2 != NULL)
887 blake2s_update(&state, input2, input2len); 887 blake2s_update(&state, input2, input2len);
888 blake2s_final(&state, out); 888 blake2s_final(&state, out);
889} 889}
890 890
891static void 891static void
892wg_algo_mac_cookie(uint8_t out[], const size_t outsize, 892wg_algo_mac_cookie(uint8_t out[], const size_t outsize,
893 const uint8_t input1[], const size_t input1len) 893 const uint8_t input1[], const size_t input1len)
894{ 894{
895 struct blake2s state; 895 struct blake2s state;
896 /* [W] 5.4: LABEL-COOKIE */ 896 /* [W] 5.4: LABEL-COOKIE */
897 const char *label = "cookie--"; 897 const char *label = "cookie--";
898 898
899 blake2s_init(&state, outsize, NULL, 0); 899 blake2s_init(&state, outsize, NULL, 0);
900 blake2s_update(&state, label, strlen(label)); 900 blake2s_update(&state, label, strlen(label));
901 blake2s_update(&state, input1, input1len); 901 blake2s_update(&state, input1, input1len);
902 blake2s_final(&state, out); 902 blake2s_final(&state, out);
903} 903}
904 904
905static void 905static void
906wg_algo_generate_keypair(uint8_t pubkey[WG_EPHEMERAL_KEY_LEN], 906wg_algo_generate_keypair(uint8_t pubkey[WG_EPHEMERAL_KEY_LEN],
907 uint8_t privkey[WG_EPHEMERAL_KEY_LEN]) 907 uint8_t privkey[WG_EPHEMERAL_KEY_LEN])
908{ 908{
909 909
910 CTASSERT(WG_EPHEMERAL_KEY_LEN == crypto_scalarmult_curve25519_BYTES); 910 CTASSERT(WG_EPHEMERAL_KEY_LEN == crypto_scalarmult_curve25519_BYTES);
911 911
912 cprng_strong(kern_cprng, privkey, WG_EPHEMERAL_KEY_LEN, 0); 912 cprng_strong(kern_cprng, privkey, WG_EPHEMERAL_KEY_LEN, 0);
913 crypto_scalarmult_base(pubkey, privkey); 913 crypto_scalarmult_base(pubkey, privkey);
914} 914}
915 915
916static void 916static void
917wg_algo_dh(uint8_t out[WG_DH_OUTPUT_LEN], 917wg_algo_dh(uint8_t out[WG_DH_OUTPUT_LEN],
918 const uint8_t privkey[WG_STATIC_KEY_LEN], 918 const uint8_t privkey[WG_STATIC_KEY_LEN],
919 const uint8_t pubkey[WG_STATIC_KEY_LEN]) 919 const uint8_t pubkey[WG_STATIC_KEY_LEN])
920{ 920{
921 921
922 CTASSERT(WG_STATIC_KEY_LEN == crypto_scalarmult_curve25519_BYTES); 922 CTASSERT(WG_STATIC_KEY_LEN == crypto_scalarmult_curve25519_BYTES);
923 923
924 int ret __diagused = crypto_scalarmult(out, privkey, pubkey); 924 int ret __diagused = crypto_scalarmult(out, privkey, pubkey);
925 KASSERT(ret == 0); 925 KASSERT(ret == 0);
926} 926}
927 927
928static void 928static void
929wg_algo_hmac(uint8_t out[], const size_t outlen, 929wg_algo_hmac(uint8_t out[], const size_t outlen,
930 const uint8_t key[], const size_t keylen, 930 const uint8_t key[], const size_t keylen,
931 const uint8_t in[], const size_t inlen) 931 const uint8_t in[], const size_t inlen)
932{ 932{
933#define IPAD 0x36 933#define IPAD 0x36
934#define OPAD 0x5c 934#define OPAD 0x5c
935 uint8_t hmackey[HMAC_BLOCK_LEN] = {0}; 935 uint8_t hmackey[HMAC_BLOCK_LEN] = {0};
936 uint8_t ipad[HMAC_BLOCK_LEN]; 936 uint8_t ipad[HMAC_BLOCK_LEN];
937 uint8_t opad[HMAC_BLOCK_LEN]; 937 uint8_t opad[HMAC_BLOCK_LEN];
938 int i; 938 int i;
939 struct blake2s state; 939 struct blake2s state;
940 940
941 KASSERT(outlen == WG_HASH_LEN); 941 KASSERT(outlen == WG_HASH_LEN);
942 KASSERT(keylen <= HMAC_BLOCK_LEN); 942 KASSERT(keylen <= HMAC_BLOCK_LEN);
943 943
944 memcpy(hmackey, key, keylen); 944 memcpy(hmackey, key, keylen);
945 945
946 for (i = 0; i < sizeof(hmackey); i++) { 946 for (i = 0; i < sizeof(hmackey); i++) {
947 ipad[i] = hmackey[i] ^ IPAD; 947 ipad[i] = hmackey[i] ^ IPAD;
948 opad[i] = hmackey[i] ^ OPAD; 948 opad[i] = hmackey[i] ^ OPAD;
949 } 949 }
950 950
951 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 951 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
952 blake2s_update(&state, ipad, sizeof(ipad)); 952 blake2s_update(&state, ipad, sizeof(ipad));
953 blake2s_update(&state, in, inlen); 953 blake2s_update(&state, in, inlen);
954 blake2s_final(&state, out); 954 blake2s_final(&state, out);
955 955
956 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 956 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
957 blake2s_update(&state, opad, sizeof(opad)); 957 blake2s_update(&state, opad, sizeof(opad));
958 blake2s_update(&state, out, WG_HASH_LEN); 958 blake2s_update(&state, out, WG_HASH_LEN);
959 blake2s_final(&state, out); 959 blake2s_final(&state, out);
960#undef IPAD 960#undef IPAD
961#undef OPAD 961#undef OPAD
962} 962}
963 963
964static void 964static void
965wg_algo_kdf(uint8_t out1[WG_KDF_OUTPUT_LEN], uint8_t out2[WG_KDF_OUTPUT_LEN], 965wg_algo_kdf(uint8_t out1[WG_KDF_OUTPUT_LEN], uint8_t out2[WG_KDF_OUTPUT_LEN],
966 uint8_t out3[WG_KDF_OUTPUT_LEN], const uint8_t ckey[WG_CHAINING_KEY_LEN], 966 uint8_t out3[WG_KDF_OUTPUT_LEN], const uint8_t ckey[WG_CHAINING_KEY_LEN],
967 const uint8_t input[], const size_t inputlen) 967 const uint8_t input[], const size_t inputlen)
968{ 968{
969 uint8_t tmp1[WG_KDF_OUTPUT_LEN], tmp2[WG_KDF_OUTPUT_LEN + 1]; 969 uint8_t tmp1[WG_KDF_OUTPUT_LEN], tmp2[WG_KDF_OUTPUT_LEN + 1];
970 uint8_t one[1]; 970 uint8_t one[1];
971 971
972 /* 972 /*
973 * [N] 4.3: "an input_key_material byte sequence with length 973 * [N] 4.3: "an input_key_material byte sequence with length
974 * either zero bytes, 32 bytes, or DHLEN bytes." 974 * either zero bytes, 32 bytes, or DHLEN bytes."
975 */ 975 */
976 KASSERT(inputlen == 0 || inputlen == 32 || inputlen == NOISE_DHLEN); 976 KASSERT(inputlen == 0 || inputlen == 32 || inputlen == NOISE_DHLEN);
977 977
978 WG_DUMP_HASH("ckey", ckey); 978 WG_DUMP_HASH("ckey", ckey);
979 if (input != NULL) 979 if (input != NULL)
980 WG_DUMP_HASH("input", input); 980 WG_DUMP_HASH("input", input);
981 wg_algo_hmac(tmp1, sizeof(tmp1), ckey, WG_CHAINING_KEY_LEN, 981 wg_algo_hmac(tmp1, sizeof(tmp1), ckey, WG_CHAINING_KEY_LEN,
982 input, inputlen); 982 input, inputlen);
983 WG_DUMP_HASH("tmp1", tmp1); 983 WG_DUMP_HASH("tmp1", tmp1);
984 one[0] = 1; 984 one[0] = 1;
985 wg_algo_hmac(out1, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1), 985 wg_algo_hmac(out1, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1),
986 one, sizeof(one)); 986 one, sizeof(one));
987 WG_DUMP_HASH("out1", out1); 987 WG_DUMP_HASH("out1", out1);
988 if (out2 == NULL) 988 if (out2 == NULL)
989 return; 989 return;
990 memcpy(tmp2, out1, WG_KDF_OUTPUT_LEN); 990 memcpy(tmp2, out1, WG_KDF_OUTPUT_LEN);
991 tmp2[WG_KDF_OUTPUT_LEN] = 2; 991 tmp2[WG_KDF_OUTPUT_LEN] = 2;
992 wg_algo_hmac(out2, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1), 992 wg_algo_hmac(out2, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1),
993 tmp2, sizeof(tmp2)); 993 tmp2, sizeof(tmp2));
994 WG_DUMP_HASH("out2", out2); 994 WG_DUMP_HASH("out2", out2);
995 if (out3 == NULL) 995 if (out3 == NULL)
996 return; 996 return;
997 memcpy(tmp2, out2, WG_KDF_OUTPUT_LEN); 997 memcpy(tmp2, out2, WG_KDF_OUTPUT_LEN);
998 tmp2[WG_KDF_OUTPUT_LEN] = 3; 998 tmp2[WG_KDF_OUTPUT_LEN] = 3;
999 wg_algo_hmac(out3, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1), 999 wg_algo_hmac(out3, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1),
1000 tmp2, sizeof(tmp2)); 1000 tmp2, sizeof(tmp2));
1001 WG_DUMP_HASH("out3", out3); 1001 WG_DUMP_HASH("out3", out3);
1002} 1002}
1003 1003
1004static void 1004static void
1005wg_algo_dh_kdf(uint8_t ckey[WG_CHAINING_KEY_LEN], 1005wg_algo_dh_kdf(uint8_t ckey[WG_CHAINING_KEY_LEN],
1006 uint8_t cipher_key[WG_CIPHER_KEY_LEN], 1006 uint8_t cipher_key[WG_CIPHER_KEY_LEN],
1007 const uint8_t local_key[WG_STATIC_KEY_LEN], 1007 const uint8_t local_key[WG_STATIC_KEY_LEN],
1008 const uint8_t remote_key[WG_STATIC_KEY_LEN]) 1008 const uint8_t remote_key[WG_STATIC_KEY_LEN])
1009{ 1009{
1010 uint8_t dhout[WG_DH_OUTPUT_LEN]; 1010 uint8_t dhout[WG_DH_OUTPUT_LEN];
1011 1011
1012 wg_algo_dh(dhout, local_key, remote_key); 1012 wg_algo_dh(dhout, local_key, remote_key);
1013 wg_algo_kdf(ckey, cipher_key, NULL, ckey, dhout, sizeof(dhout)); 1013 wg_algo_kdf(ckey, cipher_key, NULL, ckey, dhout, sizeof(dhout));
1014 1014
1015 WG_DUMP_HASH("dhout", dhout); 1015 WG_DUMP_HASH("dhout", dhout);
1016 WG_DUMP_HASH("ckey", ckey); 1016 WG_DUMP_HASH("ckey", ckey);
1017 if (cipher_key != NULL) 1017 if (cipher_key != NULL)
1018 WG_DUMP_HASH("cipher_key", cipher_key); 1018 WG_DUMP_HASH("cipher_key", cipher_key);
1019} 1019}
1020 1020
1021static void 1021static void
1022wg_algo_aead_enc(uint8_t out[], size_t expected_outsize, const uint8_t key[], 1022wg_algo_aead_enc(uint8_t out[], size_t expected_outsize, const uint8_t key[],
1023 const uint64_t counter, const uint8_t plain[], const size_t plainsize, 1023 const uint64_t counter, const uint8_t plain[], const size_t plainsize,
1024 const uint8_t auth[], size_t authlen) 1024 const uint8_t auth[], size_t authlen)
1025{ 1025{
1026 uint8_t nonce[(32 + 64) / 8] = {0}; 1026 uint8_t nonce[(32 + 64) / 8] = {0};
1027 long long unsigned int outsize; 1027 long long unsigned int outsize;
1028 int error __diagused; 1028 int error __diagused;
1029 1029
1030 le64enc(&nonce[4], counter); 1030 le64enc(&nonce[4], counter);
1031 1031
1032 error = crypto_aead_chacha20poly1305_ietf_encrypt(out, &outsize, plain, 1032 error = crypto_aead_chacha20poly1305_ietf_encrypt(out, &outsize, plain,
1033 plainsize, auth, authlen, NULL, nonce, key); 1033 plainsize, auth, authlen, NULL, nonce, key);
1034 KASSERT(error == 0); 1034 KASSERT(error == 0);
1035 KASSERT(outsize == expected_outsize); 1035 KASSERT(outsize == expected_outsize);
1036} 1036}
1037 1037
1038static int 1038static int
1039wg_algo_aead_dec(uint8_t out[], size_t expected_outsize, const uint8_t key[], 1039wg_algo_aead_dec(uint8_t out[], size_t expected_outsize, const uint8_t key[],
1040 const uint64_t counter, const uint8_t encrypted[], 1040 const uint64_t counter, const uint8_t encrypted[],
1041 const size_t encryptedsize, const uint8_t auth[], size_t authlen) 1041 const size_t encryptedsize, const uint8_t auth[], size_t authlen)
1042{ 1042{
1043 uint8_t nonce[(32 + 64) / 8] = {0}; 1043 uint8_t nonce[(32 + 64) / 8] = {0};
@@ -3722,1043 +3722,1043 @@ wg_get_mbuf(size_t leading_len, size_t l @@ -3722,1043 +3722,1043 @@ wg_get_mbuf(size_t leading_len, size_t l
3722 m = m_gethdr(M_DONTWAIT, MT_DATA); 3722 m = m_gethdr(M_DONTWAIT, MT_DATA);
3723 if (m == NULL) 3723 if (m == NULL)
3724 return NULL; 3724 return NULL;
3725 if (len + leading_len > MHLEN) { 3725 if (len + leading_len > MHLEN) {
3726 m_clget(m, M_DONTWAIT); 3726 m_clget(m, M_DONTWAIT);
3727 if ((m->m_flags & M_EXT) == 0) { 3727 if ((m->m_flags & M_EXT) == 0) {
3728 m_free(m); 3728 m_free(m);
3729 return NULL; 3729 return NULL;
3730 } 3730 }
3731 } 3731 }
3732 m->m_data += leading_len; 3732 m->m_data += leading_len;
3733 m->m_pkthdr.len = m->m_len = len; 3733 m->m_pkthdr.len = m->m_len = len;
3734 3734
3735 return m; 3735 return m;
3736} 3736}
3737 3737
3738static int 3738static int
3739wg_send_data_msg(struct wg_peer *wgp, struct wg_session *wgs, 3739wg_send_data_msg(struct wg_peer *wgp, struct wg_session *wgs,
3740 struct mbuf *m) 3740 struct mbuf *m)
3741{ 3741{
3742 struct wg_softc *wg = wgp->wgp_sc; 3742 struct wg_softc *wg = wgp->wgp_sc;
3743 int error; 3743 int error;
3744 size_t inner_len, padded_len, encrypted_len; 3744 size_t inner_len, padded_len, encrypted_len;
3745 char *padded_buf = NULL; 3745 char *padded_buf = NULL;
3746 size_t mlen; 3746 size_t mlen;
3747 struct wg_msg_data *wgmd; 3747 struct wg_msg_data *wgmd;
3748 bool free_padded_buf = false; 3748 bool free_padded_buf = false;
3749 struct mbuf *n; 3749 struct mbuf *n;
3750 size_t leading_len = max_linkhdr + sizeof(struct ip6_hdr) + 3750 size_t leading_len = max_linkhdr + sizeof(struct ip6_hdr) +
3751 sizeof(struct udphdr); 3751 sizeof(struct udphdr);
3752 3752
3753 mlen = m_length(m); 3753 mlen = m_length(m);
3754 inner_len = mlen; 3754 inner_len = mlen;
3755 padded_len = roundup(mlen, 16); 3755 padded_len = roundup(mlen, 16);
3756 encrypted_len = padded_len + WG_AUTHTAG_LEN; 3756 encrypted_len = padded_len + WG_AUTHTAG_LEN;
3757 WG_DLOG("inner=%lu, padded=%lu, encrypted_len=%lu\n", 3757 WG_DLOG("inner=%lu, padded=%lu, encrypted_len=%lu\n",
3758 inner_len, padded_len, encrypted_len); 3758 inner_len, padded_len, encrypted_len);
3759 if (mlen != 0) { 3759 if (mlen != 0) {
3760 bool success; 3760 bool success;
3761 success = m_ensure_contig(&m, padded_len); 3761 success = m_ensure_contig(&m, padded_len);
3762 if (success) { 3762 if (success) {
3763 padded_buf = mtod(m, char *); 3763 padded_buf = mtod(m, char *);
3764 } else { 3764 } else {
3765 padded_buf = kmem_intr_alloc(padded_len, KM_NOSLEEP); 3765 padded_buf = kmem_intr_alloc(padded_len, KM_NOSLEEP);
3766 if (padded_buf == NULL) { 3766 if (padded_buf == NULL) {
3767 error = ENOBUFS; 3767 error = ENOBUFS;
3768 goto end; 3768 goto end;
3769 } 3769 }
3770 free_padded_buf = true; 3770 free_padded_buf = true;
3771 m_copydata(m, 0, mlen, padded_buf); 3771 m_copydata(m, 0, mlen, padded_buf);
3772 } 3772 }
3773 memset(padded_buf + mlen, 0, padded_len - inner_len); 3773 memset(padded_buf + mlen, 0, padded_len - inner_len);
3774 } 3774 }
3775 3775
3776 n = wg_get_mbuf(leading_len, sizeof(*wgmd) + encrypted_len); 3776 n = wg_get_mbuf(leading_len, sizeof(*wgmd) + encrypted_len);
3777 if (n == NULL) { 3777 if (n == NULL) {
3778 error = ENOBUFS; 3778 error = ENOBUFS;
3779 goto end; 3779 goto end;
3780 } 3780 }
3781 KASSERT(n->m_len >= sizeof(*wgmd)); 3781 KASSERT(n->m_len >= sizeof(*wgmd));
3782 wgmd = mtod(n, struct wg_msg_data *); 3782 wgmd = mtod(n, struct wg_msg_data *);
3783 wg_fill_msg_data(wg, wgp, wgs, wgmd); 3783 wg_fill_msg_data(wg, wgp, wgs, wgmd);
3784 /* [W] 5.4.6: AEAD(Tm^send, Nm^send, P, e) */ 3784 /* [W] 5.4.6: AEAD(Tm^send, Nm^send, P, e) */
3785 wg_algo_aead_enc((char *)wgmd + sizeof(*wgmd), encrypted_len, 3785 wg_algo_aead_enc((char *)wgmd + sizeof(*wgmd), encrypted_len,
3786 wgs->wgs_tkey_send, le64toh(wgmd->wgmd_counter), 3786 wgs->wgs_tkey_send, le64toh(wgmd->wgmd_counter),
3787 padded_buf, padded_len, 3787 padded_buf, padded_len,
3788 NULL, 0); 3788 NULL, 0);
3789 3789
3790 error = wg->wg_ops->send_data_msg(wgp, n); 3790 error = wg->wg_ops->send_data_msg(wgp, n);
3791 if (error == 0) { 3791 if (error == 0) {
3792 struct ifnet *ifp = &wg->wg_if; 3792 struct ifnet *ifp = &wg->wg_if;
3793 if_statadd(ifp, if_obytes, mlen); 3793 if_statadd(ifp, if_obytes, mlen);
3794 if_statinc(ifp, if_opackets); 3794 if_statinc(ifp, if_opackets);
3795 if (wgs->wgs_is_initiator && 3795 if (wgs->wgs_is_initiator &&
3796 wgs->wgs_time_last_data_sent == 0) { 3796 wgs->wgs_time_last_data_sent == 0) {
3797 /* 3797 /*
3798 * [W] 6.2 Transport Message Limits 3798 * [W] 6.2 Transport Message Limits
3799 * "if a peer is the initiator of a current secure 3799 * "if a peer is the initiator of a current secure
3800 * session, WireGuard will send a handshake initiation 3800 * session, WireGuard will send a handshake initiation
3801 * message to begin a new secure session if, after 3801 * message to begin a new secure session if, after
3802 * transmitting a transport data message, the current 3802 * transmitting a transport data message, the current
3803 * secure session is REKEY-AFTER-TIME seconds old," 3803 * secure session is REKEY-AFTER-TIME seconds old,"
3804 */ 3804 */
3805 wg_schedule_rekey_timer(wgp); 3805 wg_schedule_rekey_timer(wgp);
3806 } 3806 }
3807 wgs->wgs_time_last_data_sent = time_uptime; 3807 wgs->wgs_time_last_data_sent = time_uptime;
3808 if (wg_session_get_send_counter(wgs) >= 3808 if (wg_session_get_send_counter(wgs) >=
3809 wg_rekey_after_messages) { 3809 wg_rekey_after_messages) {
3810 /* 3810 /*
3811 * [W] 6.2 Transport Message Limits 3811 * [W] 6.2 Transport Message Limits
3812 * "WireGuard will try to create a new session, by 3812 * "WireGuard will try to create a new session, by
3813 * sending a handshake initiation message (section 3813 * sending a handshake initiation message (section
3814 * 5.4.2), after it has sent REKEY-AFTER-MESSAGES 3814 * 5.4.2), after it has sent REKEY-AFTER-MESSAGES
3815 * transport data messages..." 3815 * transport data messages..."
3816 */ 3816 */
3817 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3817 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3818 } 3818 }
3819 } 3819 }
3820end: 3820end:
3821 m_freem(m); 3821 m_freem(m);
3822 if (free_padded_buf) 3822 if (free_padded_buf)
3823 kmem_intr_free(padded_buf, padded_len); 3823 kmem_intr_free(padded_buf, padded_len);
3824 return error; 3824 return error;
3825} 3825}
3826 3826
3827static void 3827static void
3828wg_input(struct ifnet *ifp, struct mbuf *m, const int af) 3828wg_input(struct ifnet *ifp, struct mbuf *m, const int af)
3829{ 3829{
3830 pktqueue_t *pktq; 3830 pktqueue_t *pktq;
3831 size_t pktlen; 3831 size_t pktlen;
3832 3832
3833 KASSERT(af == AF_INET || af == AF_INET6); 3833 KASSERT(af == AF_INET || af == AF_INET6);
3834 3834
3835 WG_TRACE(""); 3835 WG_TRACE("");
3836 3836
3837 m_set_rcvif(m, ifp); 3837 m_set_rcvif(m, ifp);
3838 pktlen = m->m_pkthdr.len; 3838 pktlen = m->m_pkthdr.len;
3839 3839
3840 bpf_mtap_af(ifp, af, m, BPF_D_IN); 3840 bpf_mtap_af(ifp, af, m, BPF_D_IN);
3841 3841
3842 switch (af) { 3842 switch (af) {
3843 case AF_INET: 3843 case AF_INET:
3844 pktq = ip_pktq; 3844 pktq = ip_pktq;
3845 break; 3845 break;
3846#ifdef INET6 3846#ifdef INET6
3847 case AF_INET6: 3847 case AF_INET6:
3848 pktq = ip6_pktq; 3848 pktq = ip6_pktq;
3849 break; 3849 break;
3850#endif 3850#endif
3851 default: 3851 default:
3852 panic("invalid af=%d", af); 3852 panic("invalid af=%d", af);
3853 } 3853 }
3854 3854
3855 const u_int h = curcpu()->ci_index; 3855 const u_int h = curcpu()->ci_index;
3856 if (__predict_true(pktq_enqueue(pktq, m, h))) { 3856 if (__predict_true(pktq_enqueue(pktq, m, h))) {
3857 if_statadd(ifp, if_ibytes, pktlen); 3857 if_statadd(ifp, if_ibytes, pktlen);
3858 if_statinc(ifp, if_ipackets); 3858 if_statinc(ifp, if_ipackets);
3859 } else { 3859 } else {
3860 m_freem(m); 3860 m_freem(m);
3861 } 3861 }
3862} 3862}
3863 3863
3864static void 3864static void
3865wg_calc_pubkey(uint8_t pubkey[WG_STATIC_KEY_LEN], 3865wg_calc_pubkey(uint8_t pubkey[WG_STATIC_KEY_LEN],
3866 const uint8_t privkey[WG_STATIC_KEY_LEN]) 3866 const uint8_t privkey[WG_STATIC_KEY_LEN])
3867{ 3867{
3868 3868
3869 crypto_scalarmult_base(pubkey, privkey); 3869 crypto_scalarmult_base(pubkey, privkey);
3870} 3870}
3871 3871
3872static int 3872static int
3873wg_rtable_add_route(struct wg_softc *wg, struct wg_allowedip *wga) 3873wg_rtable_add_route(struct wg_softc *wg, struct wg_allowedip *wga)
3874{ 3874{
3875 struct radix_node_head *rnh; 3875 struct radix_node_head *rnh;
3876 struct radix_node *rn; 3876 struct radix_node *rn;
3877 int error = 0; 3877 int error = 0;
3878 3878
3879 rw_enter(wg->wg_rwlock, RW_WRITER); 3879 rw_enter(wg->wg_rwlock, RW_WRITER);
3880 rnh = wg_rnh(wg, wga->wga_family); 3880 rnh = wg_rnh(wg, wga->wga_family);
3881 KASSERT(rnh != NULL); 3881 KASSERT(rnh != NULL);
3882 rn = rnh->rnh_addaddr(&wga->wga_sa_addr, &wga->wga_sa_mask, rnh, 3882 rn = rnh->rnh_addaddr(&wga->wga_sa_addr, &wga->wga_sa_mask, rnh,
3883 wga->wga_nodes); 3883 wga->wga_nodes);
3884 rw_exit(wg->wg_rwlock); 3884 rw_exit(wg->wg_rwlock);
3885 3885
3886 if (rn == NULL) 3886 if (rn == NULL)
3887 error = EEXIST; 3887 error = EEXIST;
3888 3888
3889 return error; 3889 return error;
3890} 3890}
3891 3891
3892static int 3892static int
3893wg_handle_prop_peer(struct wg_softc *wg, prop_dictionary_t peer, 3893wg_handle_prop_peer(struct wg_softc *wg, prop_dictionary_t peer,
3894 struct wg_peer **wgpp) 3894 struct wg_peer **wgpp)
3895{ 3895{
3896 int error = 0; 3896 int error = 0;
3897 const void *pubkey; 3897 const void *pubkey;
3898 size_t pubkey_len; 3898 size_t pubkey_len;
3899 const void *psk; 3899 const void *psk;
3900 size_t psk_len; 3900 size_t psk_len;
3901 const char *name = NULL; 3901 const char *name = NULL;
3902 3902
3903 if (prop_dictionary_get_string(peer, "name", &name)) { 3903 if (prop_dictionary_get_string(peer, "name", &name)) {
3904 if (strlen(name) > WG_PEER_NAME_MAXLEN) { 3904 if (strlen(name) > WG_PEER_NAME_MAXLEN) {
3905 error = EINVAL; 3905 error = EINVAL;
3906 goto out; 3906 goto out;
3907 } 3907 }
3908 } 3908 }
3909 3909
3910 if (!prop_dictionary_get_data(peer, "public_key", 3910 if (!prop_dictionary_get_data(peer, "public_key",
3911 &pubkey, &pubkey_len)) { 3911 &pubkey, &pubkey_len)) {
3912 error = EINVAL; 3912 error = EINVAL;
3913 goto out; 3913 goto out;
3914 } 3914 }
3915#ifdef WG_DEBUG_DUMP 3915#ifdef WG_DEBUG_DUMP
3916 log(LOG_DEBUG, "pubkey=%p, pubkey_len=%lu\n", pubkey, pubkey_len); 3916 log(LOG_DEBUG, "pubkey=%p, pubkey_len=%lu\n", pubkey, pubkey_len);
3917 for (int _i = 0; _i < pubkey_len; _i++) 3917 for (int _i = 0; _i < pubkey_len; _i++)
3918 log(LOG_DEBUG, "%c", ((const char *)pubkey)[_i]); 3918 log(LOG_DEBUG, "%c", ((const char *)pubkey)[_i]);
3919 log(LOG_DEBUG, "\n"); 3919 log(LOG_DEBUG, "\n");
3920#endif 3920#endif
3921 3921
3922 struct wg_peer *wgp = wg_alloc_peer(wg); 3922 struct wg_peer *wgp = wg_alloc_peer(wg);
3923 memcpy(wgp->wgp_pubkey, pubkey, sizeof(wgp->wgp_pubkey)); 3923 memcpy(wgp->wgp_pubkey, pubkey, sizeof(wgp->wgp_pubkey));
3924 if (name != NULL) 3924 if (name != NULL)
3925 strncpy(wgp->wgp_name, name, sizeof(wgp->wgp_name)); 3925 strncpy(wgp->wgp_name, name, sizeof(wgp->wgp_name));
3926 3926
3927 if (prop_dictionary_get_data(peer, "preshared_key", &psk, &psk_len)) { 3927 if (prop_dictionary_get_data(peer, "preshared_key", &psk, &psk_len)) {
3928 if (psk_len != sizeof(wgp->wgp_psk)) { 3928 if (psk_len != sizeof(wgp->wgp_psk)) {
3929 error = EINVAL; 3929 error = EINVAL;
3930 goto out; 3930 goto out;
3931 } 3931 }
3932 memcpy(wgp->wgp_psk, psk, sizeof(wgp->wgp_psk)); 3932 memcpy(wgp->wgp_psk, psk, sizeof(wgp->wgp_psk));
3933 } 3933 }
3934 3934
3935 const void *addr; 3935 const void *addr;
3936 size_t addr_len; 3936 size_t addr_len;
3937 struct wg_sockaddr *wgsa = wgp->wgp_endpoint; 3937 struct wg_sockaddr *wgsa = wgp->wgp_endpoint;
3938 3938
3939 if (!prop_dictionary_get_data(peer, "endpoint", &addr, &addr_len)) 3939 if (!prop_dictionary_get_data(peer, "endpoint", &addr, &addr_len))
3940 goto skip_endpoint; 3940 goto skip_endpoint;
3941 if (addr_len < sizeof(*wgsatosa(wgsa)) || 3941 if (addr_len < sizeof(*wgsatosa(wgsa)) ||
3942 addr_len > sizeof(*wgsatoss(wgsa))) { 3942 addr_len > sizeof(*wgsatoss(wgsa))) {
3943 error = EINVAL; 3943 error = EINVAL;
3944 goto out; 3944 goto out;
3945 } 3945 }
3946 memcpy(wgsatoss(wgsa), addr, addr_len); 3946 memcpy(wgsatoss(wgsa), addr, addr_len);
3947 switch (wgsa_family(wgsa)) { 3947 switch (wgsa_family(wgsa)) {
3948 case AF_INET: 3948 case AF_INET:
3949#ifdef INET6 3949#ifdef INET6
3950 case AF_INET6: 3950 case AF_INET6:
3951#endif 3951#endif
3952 break; 3952 break;
3953 default: 3953 default:
3954 error = EPFNOSUPPORT; 3954 error = EPFNOSUPPORT;
3955 goto out; 3955 goto out;
3956 } 3956 }
3957 if (addr_len != sockaddr_getsize_by_family(wgsa_family(wgsa))) { 3957 if (addr_len != sockaddr_getsize_by_family(wgsa_family(wgsa))) {
3958 error = EINVAL; 3958 error = EINVAL;
3959 goto out; 3959 goto out;
3960 } 3960 }
3961 { 3961 {
3962 char addrstr[128]; 3962 char addrstr[128];
3963 sockaddr_format(wgsatosa(wgsa), addrstr, sizeof(addrstr)); 3963 sockaddr_format(wgsatosa(wgsa), addrstr, sizeof(addrstr));
3964 WG_DLOG("addr=%s\n", addrstr); 3964 WG_DLOG("addr=%s\n", addrstr);
3965 } 3965 }
3966 wgp->wgp_endpoint_available = true; 3966 wgp->wgp_endpoint_available = true;
3967 3967
3968 prop_array_t allowedips; 3968 prop_array_t allowedips;
3969skip_endpoint: 3969skip_endpoint:
3970 allowedips = prop_dictionary_get(peer, "allowedips"); 3970 allowedips = prop_dictionary_get(peer, "allowedips");
3971 if (allowedips == NULL) 3971 if (allowedips == NULL)
3972 goto skip; 3972 goto skip;
3973 3973
3974 prop_object_iterator_t _it = prop_array_iterator(allowedips); 3974 prop_object_iterator_t _it = prop_array_iterator(allowedips);
3975 prop_dictionary_t prop_allowedip; 3975 prop_dictionary_t prop_allowedip;
3976 int j = 0; 3976 int j = 0;
3977 while ((prop_allowedip = prop_object_iterator_next(_it)) != NULL) { 3977 while ((prop_allowedip = prop_object_iterator_next(_it)) != NULL) {
3978 struct wg_allowedip *wga = &wgp->wgp_allowedips[j]; 3978 struct wg_allowedip *wga = &wgp->wgp_allowedips[j];
3979 3979
3980 if (!prop_dictionary_get_int(prop_allowedip, "family", 3980 if (!prop_dictionary_get_int(prop_allowedip, "family",
3981 &wga->wga_family)) 3981 &wga->wga_family))
3982 continue; 3982 continue;
3983 if (!prop_dictionary_get_data(prop_allowedip, "ip", 3983 if (!prop_dictionary_get_data(prop_allowedip, "ip",
3984 &addr, &addr_len)) 3984 &addr, &addr_len))
3985 continue; 3985 continue;
3986 if (!prop_dictionary_get_uint8(prop_allowedip, "cidr", 3986 if (!prop_dictionary_get_uint8(prop_allowedip, "cidr",
3987 &wga->wga_cidr)) 3987 &wga->wga_cidr))
3988 continue; 3988 continue;
3989 3989
3990 switch (wga->wga_family) { 3990 switch (wga->wga_family) {
3991 case AF_INET: { 3991 case AF_INET: {
3992 struct sockaddr_in sin; 3992 struct sockaddr_in sin;
3993 char addrstr[128]; 3993 char addrstr[128];
3994 struct in_addr mask; 3994 struct in_addr mask;
3995 struct sockaddr_in sin_mask; 3995 struct sockaddr_in sin_mask;
3996 3996
3997 if (addr_len != sizeof(struct in_addr)) 3997 if (addr_len != sizeof(struct in_addr))
3998 return EINVAL; 3998 return EINVAL;
3999 memcpy(&wga->wga_addr4, addr, addr_len); 3999 memcpy(&wga->wga_addr4, addr, addr_len);
4000 4000
4001 sockaddr_in_init(&sin, (const struct in_addr *)addr, 4001 sockaddr_in_init(&sin, (const struct in_addr *)addr,
4002 0); 4002 0);
4003 sockaddr_copy(&wga->wga_sa_addr, 4003 sockaddr_copy(&wga->wga_sa_addr,
4004 sizeof(sin), sintosa(&sin)); 4004 sizeof(sin), sintosa(&sin));
4005 4005
4006 sockaddr_format(sintosa(&sin), 4006 sockaddr_format(sintosa(&sin),
4007 addrstr, sizeof(addrstr)); 4007 addrstr, sizeof(addrstr));
4008 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr); 4008 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr);
4009 4009
4010 in_len2mask(&mask, wga->wga_cidr); 4010 in_len2mask(&mask, wga->wga_cidr);
4011 sockaddr_in_init(&sin_mask, &mask, 0); 4011 sockaddr_in_init(&sin_mask, &mask, 0);
4012 sockaddr_copy(&wga->wga_sa_mask, 4012 sockaddr_copy(&wga->wga_sa_mask,
4013 sizeof(sin_mask), sintosa(&sin_mask)); 4013 sizeof(sin_mask), sintosa(&sin_mask));
4014 4014
4015 break; 4015 break;
4016 } 4016 }
4017#ifdef INET6 4017#ifdef INET6
4018 case AF_INET6: { 4018 case AF_INET6: {
4019 struct sockaddr_in6 sin6; 4019 struct sockaddr_in6 sin6;
4020 char addrstr[128]; 4020 char addrstr[128];
4021 struct in6_addr mask; 4021 struct in6_addr mask;
4022 struct sockaddr_in6 sin6_mask; 4022 struct sockaddr_in6 sin6_mask;
4023 4023
4024 if (addr_len != sizeof(struct in6_addr)) 4024 if (addr_len != sizeof(struct in6_addr))
4025 return EINVAL; 4025 return EINVAL;
4026 memcpy(&wga->wga_addr6, addr, addr_len); 4026 memcpy(&wga->wga_addr6, addr, addr_len);
4027 4027
4028 sockaddr_in6_init(&sin6, (const struct in6_addr *)addr, 4028 sockaddr_in6_init(&sin6, (const struct in6_addr *)addr,
4029 0, 0, 0); 4029 0, 0, 0);
4030 sockaddr_copy(&wga->wga_sa_addr, 4030 sockaddr_copy(&wga->wga_sa_addr,
4031 sizeof(sin6), sin6tosa(&sin6)); 4031 sizeof(sin6), sin6tosa(&sin6));
4032 4032
4033 sockaddr_format(sin6tosa(&sin6), 4033 sockaddr_format(sin6tosa(&sin6),
4034 addrstr, sizeof(addrstr)); 4034 addrstr, sizeof(addrstr));
4035 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr); 4035 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr);
4036 4036
4037 in6_prefixlen2mask(&mask, wga->wga_cidr); 4037 in6_prefixlen2mask(&mask, wga->wga_cidr);
4038 sockaddr_in6_init(&sin6_mask, &mask, 0, 0, 0); 4038 sockaddr_in6_init(&sin6_mask, &mask, 0, 0, 0);
4039 sockaddr_copy(&wga->wga_sa_mask, 4039 sockaddr_copy(&wga->wga_sa_mask,
4040 sizeof(sin6_mask), sin6tosa(&sin6_mask)); 4040 sizeof(sin6_mask), sin6tosa(&sin6_mask));
4041 4041
4042 break; 4042 break;
4043 } 4043 }
4044#endif 4044#endif
4045 default: 4045 default:
4046 error = EINVAL; 4046 error = EINVAL;
4047 goto out; 4047 goto out;
4048 } 4048 }
4049 wga->wga_peer = wgp; 4049 wga->wga_peer = wgp;
4050 4050
4051 error = wg_rtable_add_route(wg, wga); 4051 error = wg_rtable_add_route(wg, wga);
4052 if (error != 0) 4052 if (error != 0)
4053 goto out; 4053 goto out;
4054 4054
4055 j++; 4055 j++;
4056 } 4056 }
4057 wgp->wgp_n_allowedips = j; 4057 wgp->wgp_n_allowedips = j;
4058skip: 4058skip:
4059 *wgpp = wgp; 4059 *wgpp = wgp;
4060out: 4060out:
4061 return error; 4061 return error;
4062} 4062}
4063 4063
4064static int 4064static int
4065wg_alloc_prop_buf(char **_buf, struct ifdrv *ifd) 4065wg_alloc_prop_buf(char **_buf, struct ifdrv *ifd)
4066{ 4066{
4067 int error; 4067 int error;
4068 char *buf; 4068 char *buf;
4069 4069
4070 WG_DLOG("buf=%p, len=%lu\n", ifd->ifd_data, ifd->ifd_len); 4070 WG_DLOG("buf=%p, len=%lu\n", ifd->ifd_data, ifd->ifd_len);
4071 buf = kmem_alloc(ifd->ifd_len + 1, KM_SLEEP); 4071 buf = kmem_alloc(ifd->ifd_len + 1, KM_SLEEP);
4072 error = copyin(ifd->ifd_data, buf, ifd->ifd_len); 4072 error = copyin(ifd->ifd_data, buf, ifd->ifd_len);
4073 if (error != 0) 4073 if (error != 0)
4074 return error; 4074 return error;
4075 buf[ifd->ifd_len] = '\0'; 4075 buf[ifd->ifd_len] = '\0';
4076#ifdef WG_DEBUG_DUMP 4076#ifdef WG_DEBUG_DUMP
4077 for (int i = 0; i < ifd->ifd_len; i++) 4077 for (int i = 0; i < ifd->ifd_len; i++)
4078 log(LOG_DEBUG, "%c", buf[i]); 4078 log(LOG_DEBUG, "%c", buf[i]);
4079 log(LOG_DEBUG, "\n"); 4079 log(LOG_DEBUG, "\n");
4080#endif 4080#endif
4081 *_buf = buf; 4081 *_buf = buf;
4082 return 0; 4082 return 0;
4083} 4083}
4084 4084
4085static int 4085static int
4086wg_ioctl_set_private_key(struct wg_softc *wg, struct ifdrv *ifd) 4086wg_ioctl_set_private_key(struct wg_softc *wg, struct ifdrv *ifd)
4087{ 4087{
4088 int error; 4088 int error;
4089 prop_dictionary_t prop_dict; 4089 prop_dictionary_t prop_dict;
4090 char *buf = NULL; 4090 char *buf = NULL;
4091 const void *privkey; 4091 const void *privkey;
4092 size_t privkey_len; 4092 size_t privkey_len;
4093 4093
4094 error = wg_alloc_prop_buf(&buf, ifd); 4094 error = wg_alloc_prop_buf(&buf, ifd);
4095 if (error != 0) 4095 if (error != 0)
4096 return error; 4096 return error;
4097 error = EINVAL; 4097 error = EINVAL;
4098 prop_dict = prop_dictionary_internalize(buf); 4098 prop_dict = prop_dictionary_internalize(buf);
4099 if (prop_dict == NULL) 4099 if (prop_dict == NULL)
4100 goto out; 4100 goto out;
4101 if (!prop_dictionary_get_data(prop_dict, "private_key", 4101 if (!prop_dictionary_get_data(prop_dict, "private_key",
4102 &privkey, &privkey_len)) 4102 &privkey, &privkey_len))
4103 goto out; 4103 goto out;
4104#ifdef WG_DEBUG_DUMP 4104#ifdef WG_DEBUG_DUMP
4105 log(LOG_DEBUG, "privkey=%p, privkey_len=%lu\n", privkey, privkey_len); 4105 log(LOG_DEBUG, "privkey=%p, privkey_len=%lu\n", privkey, privkey_len);
4106 for (int i = 0; i < privkey_len; i++) 4106 for (int i = 0; i < privkey_len; i++)
4107 log(LOG_DEBUG, "%c", ((const char *)privkey)[i]); 4107 log(LOG_DEBUG, "%c", ((const char *)privkey)[i]);
4108 log(LOG_DEBUG, "\n"); 4108 log(LOG_DEBUG, "\n");
4109#endif 4109#endif
4110 if (privkey_len != WG_STATIC_KEY_LEN) 4110 if (privkey_len != WG_STATIC_KEY_LEN)
4111 goto out; 4111 goto out;
4112 memcpy(wg->wg_privkey, privkey, WG_STATIC_KEY_LEN); 4112 memcpy(wg->wg_privkey, privkey, WG_STATIC_KEY_LEN);
4113 wg_calc_pubkey(wg->wg_pubkey, wg->wg_privkey); 4113 wg_calc_pubkey(wg->wg_pubkey, wg->wg_privkey);
4114 error = 0; 4114 error = 0;
4115 4115
4116out: 4116out:
4117 kmem_free(buf, ifd->ifd_len + 1); 4117 kmem_free(buf, ifd->ifd_len + 1);
4118 return error; 4118 return error;
4119} 4119}
4120 4120
4121static int 4121static int
4122wg_ioctl_set_listen_port(struct wg_softc *wg, struct ifdrv *ifd) 4122wg_ioctl_set_listen_port(struct wg_softc *wg, struct ifdrv *ifd)
4123{ 4123{
4124 int error; 4124 int error;
4125 prop_dictionary_t prop_dict; 4125 prop_dictionary_t prop_dict;
4126 char *buf = NULL; 4126 char *buf = NULL;
4127 uint16_t port; 4127 uint16_t port;
4128 4128
4129 error = wg_alloc_prop_buf(&buf, ifd); 4129 error = wg_alloc_prop_buf(&buf, ifd);
4130 if (error != 0) 4130 if (error != 0)
4131 return error; 4131 return error;
4132 error = EINVAL; 4132 error = EINVAL;
4133 prop_dict = prop_dictionary_internalize(buf); 4133 prop_dict = prop_dictionary_internalize(buf);
4134 if (prop_dict == NULL) 4134 if (prop_dict == NULL)
4135 goto out; 4135 goto out;
4136 if (!prop_dictionary_get_uint16(prop_dict, "listen_port", &port)) 4136 if (!prop_dictionary_get_uint16(prop_dict, "listen_port", &port))
4137 goto out; 4137 goto out;
4138 4138
4139 error = wg->wg_ops->bind_port(wg, (uint16_t)port); 4139 error = wg->wg_ops->bind_port(wg, (uint16_t)port);
4140 4140
4141out: 4141out:
4142 kmem_free(buf, ifd->ifd_len + 1); 4142 kmem_free(buf, ifd->ifd_len + 1);
4143 return error; 4143 return error;
4144} 4144}
4145 4145
4146static int 4146static int
4147wg_ioctl_add_peer(struct wg_softc *wg, struct ifdrv *ifd) 4147wg_ioctl_add_peer(struct wg_softc *wg, struct ifdrv *ifd)
4148{ 4148{
4149 int error; 4149 int error;
4150 prop_dictionary_t prop_dict; 4150 prop_dictionary_t prop_dict;
4151 char *buf = NULL; 4151 char *buf = NULL;
4152 struct wg_peer *wgp = NULL, *wgp0 __diagused; 4152 struct wg_peer *wgp = NULL, *wgp0 __diagused;
4153 4153
4154 error = wg_alloc_prop_buf(&buf, ifd); 4154 error = wg_alloc_prop_buf(&buf, ifd);
4155 if (error != 0) 4155 if (error != 0)
4156 return error; 4156 return error;
4157 error = EINVAL; 4157 error = EINVAL;
4158 prop_dict = prop_dictionary_internalize(buf); 4158 prop_dict = prop_dictionary_internalize(buf);
4159 if (prop_dict == NULL) 4159 if (prop_dict == NULL)
4160 goto out; 4160 goto out;
4161 4161
4162 error = wg_handle_prop_peer(wg, prop_dict, &wgp); 4162 error = wg_handle_prop_peer(wg, prop_dict, &wgp);
4163 if (error != 0) 4163 if (error != 0)
4164 goto out; 4164 goto out;
4165 4165
4166 mutex_enter(wg->wg_lock); 4166 mutex_enter(wg->wg_lock);
4167 if (thmap_get(wg->wg_peers_bypubkey, wgp->wgp_pubkey, 4167 if (thmap_get(wg->wg_peers_bypubkey, wgp->wgp_pubkey,
4168 sizeof(wgp->wgp_pubkey)) != NULL || 4168 sizeof(wgp->wgp_pubkey)) != NULL ||
4169 (wgp->wgp_name[0] && 4169 (wgp->wgp_name[0] &&
4170 thmap_get(wg->wg_peers_byname, wgp->wgp_name, 4170 thmap_get(wg->wg_peers_byname, wgp->wgp_name,
4171 strlen(wgp->wgp_name)) != NULL)) { 4171 strlen(wgp->wgp_name)) != NULL)) {
4172 mutex_exit(wg->wg_lock); 4172 mutex_exit(wg->wg_lock);
4173 wg_destroy_peer(wgp); 4173 wg_destroy_peer(wgp);
4174 error = EEXIST; 4174 error = EEXIST;
4175 goto out; 4175 goto out;
4176 } 4176 }
4177 wgp0 = thmap_put(wg->wg_peers_bypubkey, wgp->wgp_pubkey, 4177 wgp0 = thmap_put(wg->wg_peers_bypubkey, wgp->wgp_pubkey,
4178 sizeof(wgp->wgp_pubkey), wgp); 4178 sizeof(wgp->wgp_pubkey), wgp);
4179 KASSERT(wgp0 == wgp); 4179 KASSERT(wgp0 == wgp);
4180 if (wgp->wgp_name[0]) { 4180 if (wgp->wgp_name[0]) {
4181 wgp0 = thmap_put(wg->wg_peers_byname, wgp->wgp_name, 4181 wgp0 = thmap_put(wg->wg_peers_byname, wgp->wgp_name,
4182 strlen(wgp->wgp_name), wgp); 4182 strlen(wgp->wgp_name), wgp);
4183 KASSERT(wgp0 == wgp); 4183 KASSERT(wgp0 == wgp);
4184 } 4184 }
4185 WG_PEER_WRITER_INSERT_HEAD(wgp, wg); 4185 WG_PEER_WRITER_INSERT_HEAD(wgp, wg);
4186 wg->wg_npeers++; 4186 wg->wg_npeers++;
4187 mutex_exit(wg->wg_lock); 4187 mutex_exit(wg->wg_lock);
4188 4188
4189out: 4189out:
4190 kmem_free(buf, ifd->ifd_len + 1); 4190 kmem_free(buf, ifd->ifd_len + 1);
4191 return error; 4191 return error;
4192} 4192}
4193 4193
4194static int 4194static int
4195wg_ioctl_delete_peer(struct wg_softc *wg, struct ifdrv *ifd) 4195wg_ioctl_delete_peer(struct wg_softc *wg, struct ifdrv *ifd)
4196{ 4196{
4197 int error; 4197 int error;
4198 prop_dictionary_t prop_dict; 4198 prop_dictionary_t prop_dict;
4199 char *buf = NULL; 4199 char *buf = NULL;
4200 const char *name; 4200 const char *name;
4201 4201
4202 error = wg_alloc_prop_buf(&buf, ifd); 4202 error = wg_alloc_prop_buf(&buf, ifd);
4203 if (error != 0) 4203 if (error != 0)
4204 return error; 4204 return error;
4205 error = EINVAL; 4205 error = EINVAL;
4206 prop_dict = prop_dictionary_internalize(buf); 4206 prop_dict = prop_dictionary_internalize(buf);
4207 if (prop_dict == NULL) 4207 if (prop_dict == NULL)
4208 goto out; 4208 goto out;
4209 4209
4210 if (!prop_dictionary_get_string(prop_dict, "name", &name)) 4210 if (!prop_dictionary_get_string(prop_dict, "name", &name))
4211 goto out; 4211 goto out;
4212 if (strlen(name) > WG_PEER_NAME_MAXLEN) 4212 if (strlen(name) > WG_PEER_NAME_MAXLEN)
4213 goto out; 4213 goto out;
4214 4214
4215 error = wg_destroy_peer_name(wg, name); 4215 error = wg_destroy_peer_name(wg, name);
4216out: 4216out:
4217 kmem_free(buf, ifd->ifd_len + 1); 4217 kmem_free(buf, ifd->ifd_len + 1);
4218 return error; 4218 return error;
4219} 4219}
4220 4220
4221static int 4221static int
4222wg_ioctl_get(struct wg_softc *wg, struct ifdrv *ifd) 4222wg_ioctl_get(struct wg_softc *wg, struct ifdrv *ifd)
4223{ 4223{
4224 int error = ENOMEM; 4224 int error = ENOMEM;
4225 prop_dictionary_t prop_dict; 4225 prop_dictionary_t prop_dict;
4226 prop_array_t peers = NULL; 4226 prop_array_t peers = NULL;
4227 char *buf; 4227 char *buf;
4228 struct wg_peer *wgp; 4228 struct wg_peer *wgp;
4229 int s, i; 4229 int s, i;
4230 4230
4231 prop_dict = prop_dictionary_create(); 4231 prop_dict = prop_dictionary_create();
4232 if (prop_dict == NULL) 4232 if (prop_dict == NULL)
4233 goto error; 4233 goto error;
4234 4234
4235 if (!prop_dictionary_set_data(prop_dict, "private_key", wg->wg_privkey, 4235 if (!prop_dictionary_set_data(prop_dict, "private_key", wg->wg_privkey,
4236 WG_STATIC_KEY_LEN)) 4236 WG_STATIC_KEY_LEN))
4237 goto error; 4237 goto error;
4238 4238
4239 if (wg->wg_listen_port != 0) { 4239 if (wg->wg_listen_port != 0) {
4240 if (!prop_dictionary_set_uint16(prop_dict, "listen_port", 4240 if (!prop_dictionary_set_uint16(prop_dict, "listen_port",
4241 wg->wg_listen_port)) 4241 wg->wg_listen_port))
4242 goto error; 4242 goto error;
4243 } 4243 }
4244 4244
4245 if (wg->wg_npeers == 0) 4245 if (wg->wg_npeers == 0)
4246 goto skip_peers; 4246 goto skip_peers;
4247 4247
4248 peers = prop_array_create(); 4248 peers = prop_array_create();
4249 if (peers == NULL) 4249 if (peers == NULL)
4250 goto error; 4250 goto error;
4251 4251
4252 s = pserialize_read_enter(); 4252 s = pserialize_read_enter();
4253 i = 0; 4253 i = 0;
4254 WG_PEER_READER_FOREACH(wgp, wg) { 4254 WG_PEER_READER_FOREACH(wgp, wg) {
4255 struct wg_sockaddr *wgsa; 4255 struct wg_sockaddr *wgsa;
4256 struct psref wgp_psref, wgsa_psref; 4256 struct psref wgp_psref, wgsa_psref;
4257 prop_dictionary_t prop_peer; 4257 prop_dictionary_t prop_peer;
4258 4258
4259 wg_get_peer(wgp, &wgp_psref); 4259 wg_get_peer(wgp, &wgp_psref);
4260 pserialize_read_exit(s); 4260 pserialize_read_exit(s);
4261 4261
4262 prop_peer = prop_dictionary_create(); 4262 prop_peer = prop_dictionary_create();
4263 if (prop_peer == NULL) 4263 if (prop_peer == NULL)
4264 goto next; 4264 goto next;
4265 4265
4266 if (strlen(wgp->wgp_name) > 0) { 4266 if (strlen(wgp->wgp_name) > 0) {
4267 if (!prop_dictionary_set_string(prop_peer, "name", 4267 if (!prop_dictionary_set_string(prop_peer, "name",
4268 wgp->wgp_name)) 4268 wgp->wgp_name))
4269 goto next; 4269 goto next;
4270 } 4270 }
4271 4271
4272 if (!prop_dictionary_set_data(prop_peer, "public_key", 4272 if (!prop_dictionary_set_data(prop_peer, "public_key",
4273 wgp->wgp_pubkey, sizeof(wgp->wgp_pubkey))) 4273 wgp->wgp_pubkey, sizeof(wgp->wgp_pubkey)))
4274 goto next; 4274 goto next;
4275 4275
4276 uint8_t psk_zero[WG_PRESHARED_KEY_LEN] = {0}; 4276 uint8_t psk_zero[WG_PRESHARED_KEY_LEN] = {0};
4277 if (!consttime_memequal(wgp->wgp_psk, psk_zero, 4277 if (!consttime_memequal(wgp->wgp_psk, psk_zero,
4278 sizeof(wgp->wgp_psk))) { 4278 sizeof(wgp->wgp_psk))) {
4279 if (!prop_dictionary_set_data(prop_peer, 4279 if (!prop_dictionary_set_data(prop_peer,
4280 "preshared_key", 4280 "preshared_key",
4281 wgp->wgp_psk, sizeof(wgp->wgp_psk))) 4281 wgp->wgp_psk, sizeof(wgp->wgp_psk)))
4282 goto next; 4282 goto next;
4283 } 4283 }
4284 4284
4285 wgsa = wg_get_endpoint_sa(wgp, &wgsa_psref); 4285 wgsa = wg_get_endpoint_sa(wgp, &wgsa_psref);
4286 CTASSERT(AF_UNSPEC == 0); 4286 CTASSERT(AF_UNSPEC == 0);
4287 if (wgsa_family(wgsa) != 0 /*AF_UNSPEC*/ && 4287 if (wgsa_family(wgsa) != 0 /*AF_UNSPEC*/ &&
4288 !prop_dictionary_set_data(prop_peer, "endpoint", 4288 !prop_dictionary_set_data(prop_peer, "endpoint",
4289 wgsatoss(wgsa), 4289 wgsatoss(wgsa),
4290 sockaddr_getsize_by_family(wgsa_family(wgsa)))) { 4290 sockaddr_getsize_by_family(wgsa_family(wgsa)))) {
4291 wg_put_sa(wgp, wgsa, &wgsa_psref); 4291 wg_put_sa(wgp, wgsa, &wgsa_psref);
4292 goto next; 4292 goto next;
4293 } 4293 }
4294 wg_put_sa(wgp, wgsa, &wgsa_psref); 4294 wg_put_sa(wgp, wgsa, &wgsa_psref);
4295 4295
4296 const struct timespec *t = &wgp->wgp_last_handshake_time; 4296 const struct timespec *t = &wgp->wgp_last_handshake_time;
4297 4297
4298 if (!prop_dictionary_set_uint64(prop_peer, 4298 if (!prop_dictionary_set_uint64(prop_peer,
4299 "last_handshake_time_sec", t->tv_sec)) 4299 "last_handshake_time_sec", t->tv_sec))
4300 goto next; 4300 goto next;
4301 if (!prop_dictionary_set_uint32(prop_peer, 4301 if (!prop_dictionary_set_uint32(prop_peer,
4302 "last_handshake_time_nsec", t->tv_nsec)) 4302 "last_handshake_time_nsec", t->tv_nsec))
4303 goto next; 4303 goto next;
4304 4304
4305 if (wgp->wgp_n_allowedips == 0) 4305 if (wgp->wgp_n_allowedips == 0)
4306 goto skip_allowedips; 4306 goto skip_allowedips;
4307 4307
4308 prop_array_t allowedips = prop_array_create(); 4308 prop_array_t allowedips = prop_array_create();
4309 if (allowedips == NULL) 4309 if (allowedips == NULL)
4310 goto next; 4310 goto next;
4311 for (int j = 0; j < wgp->wgp_n_allowedips; j++) { 4311 for (int j = 0; j < wgp->wgp_n_allowedips; j++) {
4312 struct wg_allowedip *wga = &wgp->wgp_allowedips[j]; 4312 struct wg_allowedip *wga = &wgp->wgp_allowedips[j];
4313 prop_dictionary_t prop_allowedip; 4313 prop_dictionary_t prop_allowedip;
4314 4314
4315 prop_allowedip = prop_dictionary_create(); 4315 prop_allowedip = prop_dictionary_create();
4316 if (prop_allowedip == NULL) 4316 if (prop_allowedip == NULL)
4317 break; 4317 break;
4318 4318
4319 if (!prop_dictionary_set_int(prop_allowedip, "family", 4319 if (!prop_dictionary_set_int(prop_allowedip, "family",
4320 wga->wga_family)) 4320 wga->wga_family))
4321 goto _next; 4321 goto _next;
4322 if (!prop_dictionary_set_uint8(prop_allowedip, "cidr", 4322 if (!prop_dictionary_set_uint8(prop_allowedip, "cidr",
4323 wga->wga_cidr)) 4323 wga->wga_cidr))
4324 goto _next; 4324 goto _next;
4325 4325
4326 switch (wga->wga_family) { 4326 switch (wga->wga_family) {
4327 case AF_INET: 4327 case AF_INET:
4328 if (!prop_dictionary_set_data(prop_allowedip, 4328 if (!prop_dictionary_set_data(prop_allowedip,
4329 "ip", &wga->wga_addr4, 4329 "ip", &wga->wga_addr4,
4330 sizeof(wga->wga_addr4))) 4330 sizeof(wga->wga_addr4)))
4331 goto _next; 4331 goto _next;
4332 break; 4332 break;
4333#ifdef INET6 4333#ifdef INET6
4334 case AF_INET6: 4334 case AF_INET6:
4335 if (!prop_dictionary_set_data(prop_allowedip, 4335 if (!prop_dictionary_set_data(prop_allowedip,
4336 "ip", &wga->wga_addr6, 4336 "ip", &wga->wga_addr6,
4337 sizeof(wga->wga_addr6))) 4337 sizeof(wga->wga_addr6)))
4338 goto _next; 4338 goto _next;
4339 break; 4339 break;
4340#endif 4340#endif
4341 default: 4341 default:
4342 break; 4342 break;
4343 } 4343 }
4344 prop_array_set(allowedips, j, prop_allowedip); 4344 prop_array_set(allowedips, j, prop_allowedip);
4345 _next: 4345 _next:
4346 prop_object_release(prop_allowedip); 4346 prop_object_release(prop_allowedip);
4347 } 4347 }
4348 prop_dictionary_set(prop_peer, "allowedips", allowedips); 4348 prop_dictionary_set(prop_peer, "allowedips", allowedips);
4349 prop_object_release(allowedips); 4349 prop_object_release(allowedips);
4350 4350
4351 skip_allowedips: 4351 skip_allowedips:
4352 4352
4353 prop_array_set(peers, i, prop_peer); 4353 prop_array_set(peers, i, prop_peer);
4354 next: 4354 next:
4355 if (prop_peer) 4355 if (prop_peer)
4356 prop_object_release(prop_peer); 4356 prop_object_release(prop_peer);
4357 i++; 4357 i++;
4358 4358
4359 s = pserialize_read_enter(); 4359 s = pserialize_read_enter();
4360 wg_put_peer(wgp, &wgp_psref); 4360 wg_put_peer(wgp, &wgp_psref);
4361 } 4361 }
4362 pserialize_read_exit(s); 4362 pserialize_read_exit(s);
4363 4363
4364 prop_dictionary_set(prop_dict, "peers", peers); 4364 prop_dictionary_set(prop_dict, "peers", peers);
4365 prop_object_release(peers); 4365 prop_object_release(peers);
4366 peers = NULL; 4366 peers = NULL;
4367 4367
4368skip_peers: 4368skip_peers:
4369 buf = prop_dictionary_externalize(prop_dict); 4369 buf = prop_dictionary_externalize(prop_dict);
4370 if (buf == NULL) 4370 if (buf == NULL)
4371 goto error; 4371 goto error;
4372 if (ifd->ifd_len < (strlen(buf) + 1)) { 4372 if (ifd->ifd_len < (strlen(buf) + 1)) {
4373 error = EINVAL; 4373 error = EINVAL;
4374 goto error; 4374 goto error;
4375 } 4375 }
4376 error = copyout(buf, ifd->ifd_data, strlen(buf) + 1); 4376 error = copyout(buf, ifd->ifd_data, strlen(buf) + 1);
4377 4377
4378 free(buf, 0); 4378 free(buf, 0);
4379error: 4379error:
4380 if (peers != NULL) 4380 if (peers != NULL)
4381 prop_object_release(peers); 4381 prop_object_release(peers);
4382 if (prop_dict != NULL) 4382 if (prop_dict != NULL)
4383 prop_object_release(prop_dict); 4383 prop_object_release(prop_dict);
4384 4384
4385 return error; 4385 return error;
4386} 4386}
4387 4387
4388static int 4388static int
4389wg_ioctl(struct ifnet *ifp, u_long cmd, void *data) 4389wg_ioctl(struct ifnet *ifp, u_long cmd, void *data)
4390{ 4390{
4391 struct wg_softc *wg = ifp->if_softc; 4391 struct wg_softc *wg = ifp->if_softc;
4392 struct ifreq *ifr = data; 4392 struct ifreq *ifr = data;
4393 struct ifaddr *ifa = data; 4393 struct ifaddr *ifa = data;
4394 struct ifdrv *ifd = data; 4394 struct ifdrv *ifd = data;
4395 int error = 0; 4395 int error = 0;
4396 4396
4397 switch (cmd) { 4397 switch (cmd) {
4398 case SIOCINITIFADDR: 4398 case SIOCINITIFADDR:
4399 if (ifa->ifa_addr->sa_family != AF_LINK && 4399 if (ifa->ifa_addr->sa_family != AF_LINK &&
4400 (ifp->if_flags & (IFF_UP | IFF_RUNNING)) != 4400 (ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
4401 (IFF_UP | IFF_RUNNING)) { 4401 (IFF_UP | IFF_RUNNING)) {
4402 ifp->if_flags |= IFF_UP; 4402 ifp->if_flags |= IFF_UP;
4403 error = ifp->if_init(ifp); 4403 error = ifp->if_init(ifp);
4404 } 4404 }
4405 return error; 4405 return error;
4406 case SIOCADDMULTI: 4406 case SIOCADDMULTI:
4407 case SIOCDELMULTI: 4407 case SIOCDELMULTI:
4408 switch (ifr->ifr_addr.sa_family) { 4408 switch (ifr->ifr_addr.sa_family) {
4409 case AF_INET: /* IP supports Multicast */ 4409 case AF_INET: /* IP supports Multicast */
4410 break; 4410 break;
4411#ifdef INET6 4411#ifdef INET6
4412 case AF_INET6: /* IP6 supports Multicast */ 4412 case AF_INET6: /* IP6 supports Multicast */
4413 break; 4413 break;
4414#endif 4414#endif
4415 default: /* Other protocols doesn't support Multicast */ 4415 default: /* Other protocols doesn't support Multicast */
4416 error = EAFNOSUPPORT; 4416 error = EAFNOSUPPORT;
4417 break; 4417 break;
4418 } 4418 }
4419 return error; 4419 return error;
4420 case SIOCSDRVSPEC: 4420 case SIOCSDRVSPEC:
4421 switch (ifd->ifd_cmd) { 4421 switch (ifd->ifd_cmd) {
4422 case WG_IOCTL_SET_PRIVATE_KEY: 4422 case WG_IOCTL_SET_PRIVATE_KEY:
4423 error = wg_ioctl_set_private_key(wg, ifd); 4423 error = wg_ioctl_set_private_key(wg, ifd);
4424 break; 4424 break;
4425 case WG_IOCTL_SET_LISTEN_PORT: 4425 case WG_IOCTL_SET_LISTEN_PORT:
4426 error = wg_ioctl_set_listen_port(wg, ifd); 4426 error = wg_ioctl_set_listen_port(wg, ifd);
4427 break; 4427 break;
4428 case WG_IOCTL_ADD_PEER: 4428 case WG_IOCTL_ADD_PEER:
4429 error = wg_ioctl_add_peer(wg, ifd); 4429 error = wg_ioctl_add_peer(wg, ifd);
4430 break; 4430 break;
4431 case WG_IOCTL_DELETE_PEER: 4431 case WG_IOCTL_DELETE_PEER:
4432 error = wg_ioctl_delete_peer(wg, ifd); 4432 error = wg_ioctl_delete_peer(wg, ifd);
4433 break; 4433 break;
4434 default: 4434 default:
4435 error = EINVAL; 4435 error = EINVAL;
4436 break; 4436 break;
4437 } 4437 }
4438 return error; 4438 return error;
4439 case SIOCGDRVSPEC: 4439 case SIOCGDRVSPEC:
4440 return wg_ioctl_get(wg, ifd); 4440 return wg_ioctl_get(wg, ifd);
4441 case SIOCSIFFLAGS: 4441 case SIOCSIFFLAGS:
4442 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 4442 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
4443 break; 4443 break;
4444 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 4444 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
4445 case IFF_RUNNING: 4445 case IFF_RUNNING:
4446 /* 4446 /*
4447 * If interface is marked down and it is running, 4447 * If interface is marked down and it is running,
4448 * then stop and disable it. 4448 * then stop and disable it.
4449 */ 4449 */
4450 (*ifp->if_stop)(ifp, 1); 4450 (*ifp->if_stop)(ifp, 1);
4451 break; 4451 break;
4452 case IFF_UP: 4452 case IFF_UP:
4453 /* 4453 /*
4454 * If interface is marked up and it is stopped, then 4454 * If interface is marked up and it is stopped, then
4455 * start it. 4455 * start it.
4456 */ 4456 */
4457 error = (*ifp->if_init)(ifp); 4457 error = (*ifp->if_init)(ifp);
4458 break; 4458 break;
4459 default: 4459 default:
4460 break; 4460 break;
4461 } 4461 }
4462 return error; 4462 return error;
4463#ifdef WG_RUMPKERNEL 4463#ifdef WG_RUMPKERNEL
4464 case SIOCSLINKSTR: 4464 case SIOCSLINKSTR:
4465 error = wg_ioctl_linkstr(wg, ifd); 4465 error = wg_ioctl_linkstr(wg, ifd);
4466 if (error == 0) 4466 if (error == 0)
4467 wg->wg_ops = &wg_ops_rumpuser; 4467 wg->wg_ops = &wg_ops_rumpuser;
4468 return error; 4468 return error;
4469#endif 4469#endif
4470 default: 4470 default:
4471 break; 4471 break;
4472 } 4472 }
4473 4473
4474 error = ifioctl_common(ifp, cmd, data); 4474 error = ifioctl_common(ifp, cmd, data);
4475 4475
4476#ifdef WG_RUMPKERNEL 4476#ifdef WG_RUMPKERNEL
4477 if (!wg_user_mode(wg)) 4477 if (!wg_user_mode(wg))
4478 return error; 4478 return error;
4479 4479
4480 /* Do the same to the corresponding tun device on the host */ 4480 /* Do the same to the corresponding tun device on the host */
4481 /* 4481 /*
4482 * XXX Actually the command has not been handled yet. It 4482 * XXX Actually the command has not been handled yet. It
4483 * will be handled via pr_ioctl form doifioctl later. 4483 * will be handled via pr_ioctl form doifioctl later.
4484 */ 4484 */
4485 switch (cmd) { 4485 switch (cmd) {
4486 case SIOCAIFADDR: 4486 case SIOCAIFADDR:
4487 case SIOCDIFADDR: { 4487 case SIOCDIFADDR: {
4488 struct in_aliasreq _ifra = *(const struct in_aliasreq *)data; 4488 struct in_aliasreq _ifra = *(const struct in_aliasreq *)data;
4489 struct in_aliasreq *ifra = &_ifra; 4489 struct in_aliasreq *ifra = &_ifra;
4490 KASSERT(error == ENOTTY); 4490 KASSERT(error == ENOTTY);
4491 strncpy(ifra->ifra_name, rumpuser_wg_get_tunname(wg->wg_user), 4491 strncpy(ifra->ifra_name, rumpuser_wg_get_tunname(wg->wg_user),
4492 IFNAMSIZ); 4492 IFNAMSIZ);
4493 error = rumpuser_wg_ioctl(wg->wg_user, cmd, ifra, AF_INET); 4493 error = rumpuser_wg_ioctl(wg->wg_user, cmd, ifra, AF_INET);
4494 if (error == 0) 4494 if (error == 0)
4495 error = ENOTTY; 4495 error = ENOTTY;
4496 break; 4496 break;
4497 } 4497 }
4498#ifdef INET6 4498#ifdef INET6
4499 case SIOCAIFADDR_IN6: 4499 case SIOCAIFADDR_IN6:
4500 case SIOCDIFADDR_IN6: { 4500 case SIOCDIFADDR_IN6: {
4501 struct in6_aliasreq _ifra = *(const struct in6_aliasreq *)data; 4501 struct in6_aliasreq _ifra = *(const struct in6_aliasreq *)data;
4502 struct in6_aliasreq *ifra = &_ifra; 4502 struct in6_aliasreq *ifra = &_ifra;
4503 KASSERT(error == ENOTTY); 4503 KASSERT(error == ENOTTY);
4504 strncpy(ifra->ifra_name, rumpuser_wg_get_tunname(wg->wg_user), 4504 strncpy(ifra->ifra_name, rumpuser_wg_get_tunname(wg->wg_user),
4505 IFNAMSIZ); 4505 IFNAMSIZ);
4506 error = rumpuser_wg_ioctl(wg->wg_user, cmd, ifra, AF_INET6); 4506 error = rumpuser_wg_ioctl(wg->wg_user, cmd, ifra, AF_INET6);
4507 if (error == 0) 4507 if (error == 0)
4508 error = ENOTTY; 4508 error = ENOTTY;
4509 break; 4509 break;
4510 } 4510 }
4511#endif 4511#endif
4512 } 4512 }
4513#endif /* WG_RUMPKERNEL */ 4513#endif /* WG_RUMPKERNEL */
4514 4514
4515 return error; 4515 return error;
4516} 4516}
4517 4517
4518static int 4518static int
4519wg_init(struct ifnet *ifp) 4519wg_init(struct ifnet *ifp)
4520{ 4520{
4521 4521
4522 ifp->if_flags |= IFF_RUNNING; 4522 ifp->if_flags |= IFF_RUNNING;
4523 4523
4524 /* TODO flush pending packets. */ 4524 /* TODO flush pending packets. */
4525 return 0; 4525 return 0;
4526} 4526}
4527 4527
4528static void 4528static void
4529wg_stop(struct ifnet *ifp, int disable) 4529wg_stop(struct ifnet *ifp, int disable)
4530{ 4530{
4531 4531
4532 KASSERT((ifp->if_flags & IFF_RUNNING) != 0); 4532 KASSERT((ifp->if_flags & IFF_RUNNING) != 0);
4533 ifp->if_flags &= ~IFF_RUNNING; 4533 ifp->if_flags &= ~IFF_RUNNING;
4534 4534
4535 /* Need to do something? */ 4535 /* Need to do something? */
4536} 4536}
4537 4537
4538#ifdef WG_DEBUG_PARAMS 4538#ifdef WG_DEBUG_PARAMS
4539SYSCTL_SETUP(sysctl_net_wg_setup, "sysctl net.wg setup") 4539SYSCTL_SETUP(sysctl_net_wg_setup, "sysctl net.wg setup")
4540{ 4540{
4541 const struct sysctlnode *node = NULL; 4541 const struct sysctlnode *node = NULL;
4542 4542
4543 sysctl_createv(clog, 0, NULL, &node, 4543 sysctl_createv(clog, 0, NULL, &node,
4544 CTLFLAG_PERMANENT, 4544 CTLFLAG_PERMANENT,
4545 CTLTYPE_NODE, "wg", 4545 CTLTYPE_NODE, "wg",
4546 SYSCTL_DESCR("wg(4)"), 4546 SYSCTL_DESCR("wg(4)"),
4547 NULL, 0, NULL, 0, 4547 NULL, 0, NULL, 0,
4548 CTL_NET, CTL_CREATE, CTL_EOL); 4548 CTL_NET, CTL_CREATE, CTL_EOL);
4549 sysctl_createv(clog, 0, &node, NULL, 4549 sysctl_createv(clog, 0, &node, NULL,
4550 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 4550 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4551 CTLTYPE_QUAD, "rekey_after_messages", 4551 CTLTYPE_QUAD, "rekey_after_messages",
4552 SYSCTL_DESCR("session liftime by messages"), 4552 SYSCTL_DESCR("session liftime by messages"),
4553 NULL, 0, &wg_rekey_after_messages, 0, CTL_CREATE, CTL_EOL); 4553 NULL, 0, &wg_rekey_after_messages, 0, CTL_CREATE, CTL_EOL);
4554 sysctl_createv(clog, 0, &node, NULL, 4554 sysctl_createv(clog, 0, &node, NULL,
4555 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 4555 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4556 CTLTYPE_INT, "rekey_after_time", 4556 CTLTYPE_INT, "rekey_after_time",
4557 SYSCTL_DESCR("session liftime"), 4557 SYSCTL_DESCR("session liftime"),
4558 NULL, 0, &wg_rekey_after_time, 0, CTL_CREATE, CTL_EOL); 4558 NULL, 0, &wg_rekey_after_time, 0, CTL_CREATE, CTL_EOL);
4559 sysctl_createv(clog, 0, &node, NULL, 4559 sysctl_createv(clog, 0, &node, NULL,
4560 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 4560 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4561 CTLTYPE_INT, "rekey_timeout", 4561 CTLTYPE_INT, "rekey_timeout",
4562 SYSCTL_DESCR("session handshake retry time"), 4562 SYSCTL_DESCR("session handshake retry time"),
4563 NULL, 0, &wg_rekey_timeout, 0, CTL_CREATE, CTL_EOL); 4563 NULL, 0, &wg_rekey_timeout, 0, CTL_CREATE, CTL_EOL);
4564 sysctl_createv(clog, 0, &node, NULL, 4564 sysctl_createv(clog, 0, &node, NULL,
4565 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 4565 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4566 CTLTYPE_INT, "rekey_attempt_time", 4566 CTLTYPE_INT, "rekey_attempt_time",
4567 SYSCTL_DESCR("session handshake timeout"), 4567 SYSCTL_DESCR("session handshake timeout"),
4568 NULL, 0, &wg_rekey_attempt_time, 0, CTL_CREATE, CTL_EOL); 4568 NULL, 0, &wg_rekey_attempt_time, 0, CTL_CREATE, CTL_EOL);
4569 sysctl_createv(clog, 0, &node, NULL, 4569 sysctl_createv(clog, 0, &node, NULL,
4570 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 4570 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4571 CTLTYPE_INT, "keepalive_timeout", 4571 CTLTYPE_INT, "keepalive_timeout",
4572 SYSCTL_DESCR("keepalive timeout"), 4572 SYSCTL_DESCR("keepalive timeout"),
4573 NULL, 0, &wg_keepalive_timeout, 0, CTL_CREATE, CTL_EOL); 4573 NULL, 0, &wg_keepalive_timeout, 0, CTL_CREATE, CTL_EOL);
4574 sysctl_createv(clog, 0, &node, NULL, 4574 sysctl_createv(clog, 0, &node, NULL,
4575 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 4575 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4576 CTLTYPE_BOOL, "force_underload", 4576 CTLTYPE_BOOL, "force_underload",
4577 SYSCTL_DESCR("force to detemine under load"), 4577 SYSCTL_DESCR("force to detemine under load"),
4578 NULL, 0, &wg_force_underload, 0, CTL_CREATE, CTL_EOL); 4578 NULL, 0, &wg_force_underload, 0, CTL_CREATE, CTL_EOL);
4579} 4579}
4580#endif 4580#endif
4581 4581
4582#ifdef WG_RUMPKERNEL 4582#ifdef WG_RUMPKERNEL
4583static bool 4583static bool
4584wg_user_mode(struct wg_softc *wg) 4584wg_user_mode(struct wg_softc *wg)
4585{ 4585{
4586 4586
4587 return wg->wg_user != NULL; 4587 return wg->wg_user != NULL;
4588} 4588}
4589 4589
4590static int 4590static int
4591wg_ioctl_linkstr(struct wg_softc *wg, struct ifdrv *ifd) 4591wg_ioctl_linkstr(struct wg_softc *wg, struct ifdrv *ifd)
4592{ 4592{
4593 struct ifnet *ifp = &wg->wg_if; 4593 struct ifnet *ifp = &wg->wg_if;
4594 int error; 4594 int error;
4595 4595
4596 if (ifp->if_flags & IFF_UP) 4596 if (ifp->if_flags & IFF_UP)
4597 return EBUSY; 4597 return EBUSY;
4598 4598
4599 if (ifd->ifd_cmd == IFLINKSTR_UNSET) { 4599 if (ifd->ifd_cmd == IFLINKSTR_UNSET) {
4600 /* XXX do nothing */ 4600 /* XXX do nothing */
4601 return 0; 4601 return 0;
4602 } else if (ifd->ifd_cmd != 0) { 4602 } else if (ifd->ifd_cmd != 0) {
4603 return EINVAL; 4603 return EINVAL;
4604 } else if (wg->wg_user != NULL) { 4604 } else if (wg->wg_user != NULL) {
4605 return EBUSY; 4605 return EBUSY;
4606 } 4606 }
4607 4607
4608 /* Assume \0 included */ 4608 /* Assume \0 included */
4609 if (ifd->ifd_len > IFNAMSIZ) { 4609 if (ifd->ifd_len > IFNAMSIZ) {
4610 return E2BIG; 4610 return E2BIG;
4611 } else if (ifd->ifd_len < 1) { 4611 } else if (ifd->ifd_len < 1) {
4612 return EINVAL; 4612 return EINVAL;
4613 } 4613 }
4614 4614
4615 char tun_name[IFNAMSIZ]; 4615 char tun_name[IFNAMSIZ];
4616 error = copyinstr(ifd->ifd_data, tun_name, ifd->ifd_len, NULL); 4616 error = copyinstr(ifd->ifd_data, tun_name, ifd->ifd_len, NULL);
4617 if (error != 0) 4617 if (error != 0)
4618 return error; 4618 return error;
4619 4619
4620 if (strncmp(tun_name, "tun", 3) != 0) 4620 if (strncmp(tun_name, "tun", 3) != 0)
4621 return EINVAL; 4621 return EINVAL;
4622 4622
4623 error = rumpuser_wg_create(tun_name, wg, &wg->wg_user); 4623 error = rumpuser_wg_create(tun_name, wg, &wg->wg_user);
4624 4624
4625 return error; 4625 return error;
4626} 4626}
4627 4627
4628static int 4628static int
4629wg_send_user(struct wg_peer *wgp, struct mbuf *m) 4629wg_send_user(struct wg_peer *wgp, struct mbuf *m)
4630{ 4630{
4631 int error; 4631 int error;
4632 struct psref psref; 4632 struct psref psref;
4633 struct wg_sockaddr *wgsa; 4633 struct wg_sockaddr *wgsa;
4634 struct wg_softc *wg = wgp->wgp_sc; 4634 struct wg_softc *wg = wgp->wgp_sc;
4635 struct iovec iov[1]; 4635 struct iovec iov[1];
4636 4636
4637 wgsa = wg_get_endpoint_sa(wgp, &psref); 4637 wgsa = wg_get_endpoint_sa(wgp, &psref);
4638 4638
4639 iov[0].iov_base = mtod(m, void *); 4639 iov[0].iov_base = mtod(m, void *);
4640 iov[0].iov_len = m->m_len; 4640 iov[0].iov_len = m->m_len;
4641 4641
4642 /* Send messages to a peer via an ordinary socket. */ 4642 /* Send messages to a peer via an ordinary socket. */
4643 error = rumpuser_wg_send_peer(wg->wg_user, wgsatosa(wgsa), iov, 1); 4643 error = rumpuser_wg_send_peer(wg->wg_user, wgsatosa(wgsa), iov, 1);
4644 4644
4645 wg_put_sa(wgp, wgsa, &psref); 4645 wg_put_sa(wgp, wgsa, &psref);
4646 4646
4647 m_freem(m); 4647 m_freem(m);
4648 4648
4649 return error; 4649 return error;
4650} 4650}
4651 4651
4652static void 4652static void
4653wg_input_user(struct ifnet *ifp, struct mbuf *m, const int af) 4653wg_input_user(struct ifnet *ifp, struct mbuf *m, const int af)
4654{ 4654{
4655 struct wg_softc *wg = ifp->if_softc; 4655 struct wg_softc *wg = ifp->if_softc;
4656 struct iovec iov[2]; 4656 struct iovec iov[2];
4657 struct sockaddr_storage ss; 4657 struct sockaddr_storage ss;
4658 4658
4659 KASSERT(af == AF_INET || af == AF_INET6); 4659 KASSERT(af == AF_INET || af == AF_INET6);
4660 4660
4661 WG_TRACE(""); 4661 WG_TRACE("");
4662 4662
4663 if (af == AF_INET) { 4663 if (af == AF_INET) {
4664 struct sockaddr_in *sin = (struct sockaddr_in *)&ss; 4664 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
4665 struct ip *ip; 4665 struct ip *ip;
4666 4666
4667 KASSERT(m->m_len >= sizeof(struct ip)); 4667 KASSERT(m->m_len >= sizeof(struct ip));
4668 ip = mtod(m, struct ip *); 4668 ip = mtod(m, struct ip *);
4669 sockaddr_in_init(sin, &ip->ip_dst, 0); 4669 sockaddr_in_init(sin, &ip->ip_dst, 0);
4670 } else { 4670 } else {
4671 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; 4671 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
4672 struct ip6_hdr *ip6; 4672 struct ip6_hdr *ip6;
4673 4673
4674 KASSERT(m->m_len >= sizeof(struct ip6_hdr)); 4674 KASSERT(m->m_len >= sizeof(struct ip6_hdr));
4675 ip6 = mtod(m, struct ip6_hdr *); 4675 ip6 = mtod(m, struct ip6_hdr *);
4676 sockaddr_in6_init(sin6, &ip6->ip6_dst, 0, 0, 0); 4676 sockaddr_in6_init(sin6, &ip6->ip6_dst, 0, 0, 0);
4677 } 4677 }
4678 4678
4679 iov[0].iov_base = &ss; 4679 iov[0].iov_base = &ss;
4680 iov[0].iov_len = ss.ss_len; 4680 iov[0].iov_len = ss.ss_len;
4681 iov[1].iov_base = mtod(m, void *); 4681 iov[1].iov_base = mtod(m, void *);
4682 iov[1].iov_len = m->m_len; 4682 iov[1].iov_len = m->m_len;
4683 4683
4684 WG_DUMP_BUF(iov[1].iov_base, iov[1].iov_len); 4684 WG_DUMP_BUF(iov[1].iov_base, iov[1].iov_len);
4685 4685
4686 /* Send decrypted packets to users via a tun. */ 4686 /* Send decrypted packets to users via a tun. */
4687 rumpuser_wg_send_user(wg->wg_user, iov, 2); 4687 rumpuser_wg_send_user(wg->wg_user, iov, 2);
4688 4688
4689 m_freem(m); 4689 m_freem(m);
4690} 4690}
4691 4691
4692static int 4692static int
4693wg_bind_port_user(struct wg_softc *wg, const uint16_t port) 4693wg_bind_port_user(struct wg_softc *wg, const uint16_t port)
4694{ 4694{
4695 int error; 4695 int error;
4696 uint16_t old_port = wg->wg_listen_port; 4696 uint16_t old_port = wg->wg_listen_port;
4697 4697
4698 if (port != 0 && old_port == port) 4698 if (port != 0 && old_port == port)
4699 return 0; 4699 return 0;
4700 4700
4701 error = rumpuser_wg_sock_bind(wg->wg_user, port); 4701 error = rumpuser_wg_sock_bind(wg->wg_user, port);
4702 if (error == 0) 4702 if (error == 0)
4703 wg->wg_listen_port = port; 4703 wg->wg_listen_port = port;
4704 return error; 4704 return error;
4705} 4705}
4706 4706
4707/* 4707/*
4708 * Receive user packets. 4708 * Receive user packets.
4709 */ 4709 */
4710void 4710void
4711rumpkern_wg_recv_user(struct wg_softc *wg, struct iovec *iov, size_t iovlen) 4711rumpkern_wg_recv_user(struct wg_softc *wg, struct iovec *iov, size_t iovlen)
4712{ 4712{
4713 struct ifnet *ifp = &wg->wg_if; 4713 struct ifnet *ifp = &wg->wg_if;
4714 struct mbuf *m; 4714 struct mbuf *m;
4715 const struct sockaddr *dst; 4715 const struct sockaddr *dst;
4716 4716
4717 WG_TRACE(""); 4717 WG_TRACE("");
4718 4718
4719 dst = iov[0].iov_base; 4719 dst = iov[0].iov_base;
4720 4720
4721 m = m_gethdr(M_NOWAIT, MT_DATA); 4721 m = m_gethdr(M_DONTWAIT, MT_DATA);
4722 if (m == NULL) 4722 if (m == NULL)
4723 return; 4723 return;
4724 m->m_len = m->m_pkthdr.len = 0; 4724 m->m_len = m->m_pkthdr.len = 0;
4725 m_copyback(m, 0, iov[1].iov_len, iov[1].iov_base); 4725 m_copyback(m, 0, iov[1].iov_len, iov[1].iov_base);
4726 4726
4727 WG_DLOG("iov_len=%lu\n", iov[1].iov_len); 4727 WG_DLOG("iov_len=%lu\n", iov[1].iov_len);
4728 WG_DUMP_BUF(iov[1].iov_base, iov[1].iov_len); 4728 WG_DUMP_BUF(iov[1].iov_base, iov[1].iov_len);
4729 4729
4730 (void)wg_output(ifp, m, dst, NULL); 4730 (void)wg_output(ifp, m, dst, NULL);
4731} 4731}
4732 4732
4733/* 4733/*
4734 * Receive packets from a peer. 4734 * Receive packets from a peer.
4735 */ 4735 */
4736void 4736void
4737rumpkern_wg_recv_peer(struct wg_softc *wg, struct iovec *iov, size_t iovlen) 4737rumpkern_wg_recv_peer(struct wg_softc *wg, struct iovec *iov, size_t iovlen)
4738{ 4738{
4739 struct mbuf *m; 4739 struct mbuf *m;
4740 const struct sockaddr *src; 4740 const struct sockaddr *src;
4741 4741
4742 WG_TRACE(""); 4742 WG_TRACE("");
4743 4743
4744 src = iov[0].iov_base; 4744 src = iov[0].iov_base;
4745 4745
4746 m = m_gethdr(M_NOWAIT, MT_DATA); 4746 m = m_gethdr(M_DONTWAIT, MT_DATA);
4747 if (m == NULL) 4747 if (m == NULL)
4748 return; 4748 return;
4749 m->m_len = m->m_pkthdr.len = 0; 4749 m->m_len = m->m_pkthdr.len = 0;
4750 m_copyback(m, 0, iov[1].iov_len, iov[1].iov_base); 4750 m_copyback(m, 0, iov[1].iov_len, iov[1].iov_base);
4751 4751
4752 WG_DLOG("iov_len=%lu\n", iov[1].iov_len); 4752 WG_DLOG("iov_len=%lu\n", iov[1].iov_len);
4753 WG_DUMP_BUF(iov[1].iov_base, iov[1].iov_len); 4753 WG_DUMP_BUF(iov[1].iov_base, iov[1].iov_len);
4754 4754
4755 wg_handle_packet(wg, m, src); 4755 wg_handle_packet(wg, m, src);
4756} 4756}
4757#endif /* WG_RUMPKERNEL */ 4757#endif /* WG_RUMPKERNEL */
4758 4758
4759/* 4759/*
4760 * Module infrastructure 4760 * Module infrastructure
4761 */ 4761 */
4762#include "if_module.h" 4762#include "if_module.h"
4763 4763
4764IF_MODULE(MODULE_CLASS_DRIVER, wg, "") 4764IF_MODULE(MODULE_CLASS_DRIVER, wg, "")