Thu Aug 27 19:21:14 2020 UTC ()
Summary: let wg interfaces carry multicast traffic

Once a wg interface is up and running, it is useful to be able to run
a routing protocol over it.  Marking the interface multicast capable
enables this.  (One must also use the wgconfig --allowed-ips option to
explicitly permit the group one needs, e.g. 224.0.0.5/32 for OSPF.)


(tih)
diff -r1.30 -r1.31 src/sys/net/if_wg.c

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

--- src/sys/net/if_wg.c 2020/08/27 13:44:41 1.30
+++ src/sys/net/if_wg.c 2020/08/27 19:21:14 1.31
@@ -1,1043 +1,1043 @@ @@ -1,1043 +1,1043 @@
1/* $NetBSD: if_wg.c,v 1.30 2020/08/27 13:44:41 riastradh Exp $ */ 1/* $NetBSD: if_wg.c,v 1.31 2020/08/27 19:21:14 tih 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.30 2020/08/27 13:44:41 riastradh Exp $"); 44__KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.31 2020/08/27 19:21:14 tih 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/systm.h> 51#include <sys/systm.h>
52#include <sys/kernel.h> 52#include <sys/kernel.h>
53#include <sys/mbuf.h> 53#include <sys/mbuf.h>
54#include <sys/socket.h> 54#include <sys/socket.h>
55#include <sys/sockio.h> 55#include <sys/sockio.h>
56#include <sys/errno.h> 56#include <sys/errno.h>
57#include <sys/ioctl.h> 57#include <sys/ioctl.h>
58#include <sys/time.h> 58#include <sys/time.h>
59#include <sys/timespec.h> 59#include <sys/timespec.h>
60#include <sys/socketvar.h> 60#include <sys/socketvar.h>
61#include <sys/syslog.h> 61#include <sys/syslog.h>
62#include <sys/cpu.h> 62#include <sys/cpu.h>
63#include <sys/intr.h> 63#include <sys/intr.h>
64#include <sys/kmem.h> 64#include <sys/kmem.h>
65#include <sys/device.h> 65#include <sys/device.h>
66#include <sys/module.h> 66#include <sys/module.h>
67#include <sys/mutex.h> 67#include <sys/mutex.h>
68#include <sys/rwlock.h> 68#include <sys/rwlock.h>
69#include <sys/pserialize.h> 69#include <sys/pserialize.h>
70#include <sys/psref.h> 70#include <sys/psref.h>
71#include <sys/kthread.h> 71#include <sys/kthread.h>
72#include <sys/cprng.h> 72#include <sys/cprng.h>
73#include <sys/atomic.h> 73#include <sys/atomic.h>
74#include <sys/sysctl.h> 74#include <sys/sysctl.h>
75#include <sys/domain.h> 75#include <sys/domain.h>
76#include <sys/pcq.h> 76#include <sys/pcq.h>
77#include <sys/queue.h> 77#include <sys/queue.h>
78#include <sys/percpu.h> 78#include <sys/percpu.h>
79#include <sys/callout.h> 79#include <sys/callout.h>
80 80
81#include <net/bpf.h> 81#include <net/bpf.h>
82#include <net/if.h> 82#include <net/if.h>
83#include <net/if_types.h> 83#include <net/if_types.h>
84#include <net/route.h> 84#include <net/route.h>
85 85
86#include <netinet/in.h> 86#include <netinet/in.h>
87#include <netinet/ip.h> 87#include <netinet/ip.h>
88#include <netinet/ip_var.h> 88#include <netinet/ip_var.h>
89#include <netinet/udp.h> 89#include <netinet/udp.h>
90#include <netinet/udp_var.h> 90#include <netinet/udp_var.h>
91#include <netinet/in_var.h> 91#include <netinet/in_var.h>
92#include <netinet/in_pcb.h> 92#include <netinet/in_pcb.h>
93 93
94#ifdef INET6 94#ifdef INET6
95#include <netinet6/in6_var.h> 95#include <netinet6/in6_var.h>
96#include <netinet/ip6.h> 96#include <netinet/ip6.h>
97#include <netinet6/ip6_var.h> 97#include <netinet6/ip6_var.h>
98#include <netinet6/in6_pcb.h> 98#include <netinet6/in6_pcb.h>
99#include <netinet6/udp6_var.h> 99#include <netinet6/udp6_var.h>
100#endif /* INET6 */ 100#endif /* INET6 */
101 101
102#include <net/if_wg.h> 102#include <net/if_wg.h>
103 103
104#include <prop/proplib.h> 104#include <prop/proplib.h>
105 105
106#include <crypto/blake2/blake2s.h> 106#include <crypto/blake2/blake2s.h>
107#include <crypto/sodium/crypto_scalarmult.h> 107#include <crypto/sodium/crypto_scalarmult.h>
108#include <crypto/sodium/crypto_aead_chacha20poly1305.h> 108#include <crypto/sodium/crypto_aead_chacha20poly1305.h>
109#include <crypto/sodium/crypto_aead_xchacha20poly1305.h> 109#include <crypto/sodium/crypto_aead_xchacha20poly1305.h>
110 110
111#include "ioconf.h" 111#include "ioconf.h"
112 112
113#ifdef WG_RUMPKERNEL 113#ifdef WG_RUMPKERNEL
114#include "wg_user.h" 114#include "wg_user.h"
115#endif 115#endif
116 116
117/* 117/*
118 * Data structures 118 * Data structures
119 * - struct wg_softc is an instance of wg interfaces 119 * - struct wg_softc is an instance of wg interfaces
120 * - It has a list of peers (struct wg_peer) 120 * - It has a list of peers (struct wg_peer)
121 * - It has a kthread that sends/receives handshake messages and 121 * - It has a kthread that sends/receives handshake messages and
122 * runs event handlers 122 * runs event handlers
123 * - It has its own two routing tables: one is for IPv4 and the other IPv6 123 * - It has its own two routing tables: one is for IPv4 and the other IPv6
124 * - struct wg_peer is a representative of a peer 124 * - struct wg_peer is a representative of a peer
125 * - It has a softint that is used to send packets over an wg interface 125 * - It has a softint that is used to send packets over an wg interface
126 * to a peer 126 * to a peer
127 * - It has a pair of session instances (struct wg_session) 127 * - It has a pair of session instances (struct wg_session)
128 * - It has a pair of endpoint instances (struct wg_sockaddr) 128 * - It has a pair of endpoint instances (struct wg_sockaddr)
129 * - Normally one endpoint is used and the second one is used only on 129 * - Normally one endpoint is used and the second one is used only on
130 * a peer migration (a change of peer's IP address) 130 * a peer migration (a change of peer's IP address)
131 * - It has a list of IP addresses and sub networks called allowedips 131 * - It has a list of IP addresses and sub networks called allowedips
132 * (struct wg_allowedip) 132 * (struct wg_allowedip)
133 * - A packets sent over a session is allowed if its destination matches 133 * - A packets sent over a session is allowed if its destination matches
134 * any IP addresses or sub networks of the list 134 * any IP addresses or sub networks of the list
135 * - struct wg_session represents a session of a secure tunnel with a peer 135 * - struct wg_session represents a session of a secure tunnel with a peer
136 * - Two instances of sessions belong to a peer; a stable session and a 136 * - Two instances of sessions belong to a peer; a stable session and a
137 * unstable session 137 * unstable session
138 * - A handshake process of a session always starts with a unstable instace 138 * - A handshake process of a session always starts with a unstable instace
139 * - Once a session is established, its instance becomes stable and the 139 * - Once a session is established, its instance becomes stable and the
140 * other becomes unstable instead 140 * other becomes unstable instead
141 * - Data messages are always sent via a stable session 141 * - Data messages are always sent via a stable session
142 * 142 *
143 * Locking notes: 143 * Locking notes:
144 * - wg interfaces (struct wg_softc, wg) is listed in wg_softcs.list and 144 * - wg interfaces (struct wg_softc, wg) is listed in wg_softcs.list and
145 * protected by wg_softcs.lock 145 * protected by wg_softcs.lock
146 * - Each wg has a mutex(9) and a rwlock(9) 146 * - Each wg has a mutex(9) and a rwlock(9)
147 * - The mutex (wg_lock) protects its peer list (wg_peers) 147 * - The mutex (wg_lock) protects its peer list (wg_peers)
148 * - A peer on the list is also protected by pserialize(9) or psref(9) 148 * - A peer on the list is also protected by pserialize(9) or psref(9)
149 * - The rwlock (wg_rwlock) protects the routing tables (wg_rtable_ipv[46]) 149 * - The rwlock (wg_rwlock) protects the routing tables (wg_rtable_ipv[46])
150 * - Each peer (struct wg_peer, wgp) has a mutex 150 * - Each peer (struct wg_peer, wgp) has a mutex
151 * - The mutex (wgp_lock) protects wgp_session_unstable and wgp_state 151 * - The mutex (wgp_lock) protects wgp_session_unstable and wgp_state
152 * - Each session (struct wg_session, wgs) has a mutex 152 * - Each session (struct wg_session, wgs) has a mutex
153 * - The mutex (wgs_lock) protects its state (wgs_state) and its handshake 153 * - The mutex (wgs_lock) protects its state (wgs_state) and its handshake
154 * states 154 * states
155 * - wgs_state of a unstable session can be changed while it never be 155 * - wgs_state of a unstable session can be changed while it never be
156 * changed on a stable session, so once get a session instace via 156 * changed on a stable session, so once get a session instace via
157 * wgp_session_stable we can safely access wgs_state without 157 * wgp_session_stable we can safely access wgs_state without
158 * holding wgs_lock 158 * holding wgs_lock
159 * - A session is protected by pserialize or psref like wgp 159 * - A session is protected by pserialize or psref like wgp
160 * - On a session swap, we must wait for all readers to release a 160 * - On a session swap, we must wait for all readers to release a
161 * reference to a stable session before changing wgs_state and 161 * reference to a stable session before changing wgs_state and
162 * session states 162 * session states
163 */ 163 */
164 164
165 165
166#define WGLOG(level, fmt, args...) \ 166#define WGLOG(level, fmt, args...) \
167 log(level, "%s: " fmt, __func__, ##args) 167 log(level, "%s: " fmt, __func__, ##args)
168 168
169/* Debug options */ 169/* Debug options */
170#ifdef WG_DEBUG 170#ifdef WG_DEBUG
171/* Output debug logs */ 171/* Output debug logs */
172#ifndef WG_DEBUG_LOG 172#ifndef WG_DEBUG_LOG
173#define WG_DEBUG_LOG 173#define WG_DEBUG_LOG
174#endif 174#endif
175/* Output trace logs */ 175/* Output trace logs */
176#ifndef WG_DEBUG_TRACE 176#ifndef WG_DEBUG_TRACE
177#define WG_DEBUG_TRACE 177#define WG_DEBUG_TRACE
178#endif 178#endif
179/* Output hash values, etc. */ 179/* Output hash values, etc. */
180#ifndef WG_DEBUG_DUMP 180#ifndef WG_DEBUG_DUMP
181#define WG_DEBUG_DUMP 181#define WG_DEBUG_DUMP
182#endif 182#endif
183/* Make some internal parameters configurable for testing and debugging */ 183/* Make some internal parameters configurable for testing and debugging */
184#ifndef WG_DEBUG_PARAMS 184#ifndef WG_DEBUG_PARAMS
185#define WG_DEBUG_PARAMS 185#define WG_DEBUG_PARAMS
186#endif 186#endif
187#endif 187#endif
188 188
189#ifdef WG_DEBUG_TRACE 189#ifdef WG_DEBUG_TRACE
190#define WG_TRACE(msg) \ 190#define WG_TRACE(msg) \
191 log(LOG_DEBUG, "%s:%d: %s\n", __func__, __LINE__, (msg)) 191 log(LOG_DEBUG, "%s:%d: %s\n", __func__, __LINE__, (msg))
192#else 192#else
193#define WG_TRACE(msg) __nothing 193#define WG_TRACE(msg) __nothing
194#endif 194#endif
195 195
196#ifdef WG_DEBUG_LOG 196#ifdef WG_DEBUG_LOG
197#define WG_DLOG(fmt, args...) log(LOG_DEBUG, "%s: " fmt, __func__, ##args) 197#define WG_DLOG(fmt, args...) log(LOG_DEBUG, "%s: " fmt, __func__, ##args)
198#else 198#else
199#define WG_DLOG(fmt, args...) __nothing 199#define WG_DLOG(fmt, args...) __nothing
200#endif 200#endif
201 201
202#define WG_LOG_RATECHECK(wgprc, level, fmt, args...) do { \ 202#define WG_LOG_RATECHECK(wgprc, level, fmt, args...) do { \
203 if (ppsratecheck(&(wgprc)->wgprc_lasttime, \ 203 if (ppsratecheck(&(wgprc)->wgprc_lasttime, \
204 &(wgprc)->wgprc_curpps, 1)) { \ 204 &(wgprc)->wgprc_curpps, 1)) { \
205 log(level, fmt, ##args); \ 205 log(level, fmt, ##args); \
206 } \ 206 } \
207} while (0) 207} while (0)
208 208
209#ifdef WG_DEBUG_PARAMS 209#ifdef WG_DEBUG_PARAMS
210static bool wg_force_underload = false; 210static bool wg_force_underload = false;
211#endif 211#endif
212 212
213#ifdef WG_DEBUG_DUMP 213#ifdef WG_DEBUG_DUMP
214 214
215#ifdef WG_RUMPKERNEL 215#ifdef WG_RUMPKERNEL
216static void 216static void
217wg_dump_buf(const char *func, const char *buf, const size_t size) 217wg_dump_buf(const char *func, const char *buf, const size_t size)
218{ 218{
219 219
220 log(LOG_DEBUG, "%s: ", func); 220 log(LOG_DEBUG, "%s: ", func);
221 for (int i = 0; i < size; i++) 221 for (int i = 0; i < size; i++)
222 log(LOG_DEBUG, "%02x ", (int)(0xff & buf[i])); 222 log(LOG_DEBUG, "%02x ", (int)(0xff & buf[i]));
223 log(LOG_DEBUG, "\n"); 223 log(LOG_DEBUG, "\n");
224} 224}
225#endif 225#endif
226 226
227static void 227static void
228wg_dump_hash(const uint8_t *func, const uint8_t *name, const uint8_t *hash, 228wg_dump_hash(const uint8_t *func, const uint8_t *name, const uint8_t *hash,
229 const size_t size) 229 const size_t size)
230{ 230{
231 231
232 log(LOG_DEBUG, "%s: %s: ", func, name); 232 log(LOG_DEBUG, "%s: %s: ", func, name);
233 for (int i = 0; i < size; i++) 233 for (int i = 0; i < size; i++)
234 log(LOG_DEBUG, "%02x ", (int)(0xff & hash[i])); 234 log(LOG_DEBUG, "%02x ", (int)(0xff & hash[i]));
235 log(LOG_DEBUG, "\n"); 235 log(LOG_DEBUG, "\n");
236} 236}
237 237
238#define WG_DUMP_HASH(name, hash) \ 238#define WG_DUMP_HASH(name, hash) \
239 wg_dump_hash(__func__, name, hash, WG_HASH_LEN) 239 wg_dump_hash(__func__, name, hash, WG_HASH_LEN)
240#define WG_DUMP_HASH48(name, hash) \ 240#define WG_DUMP_HASH48(name, hash) \
241 wg_dump_hash(__func__, name, hash, 48) 241 wg_dump_hash(__func__, name, hash, 48)
242#define WG_DUMP_BUF(buf, size) \ 242#define WG_DUMP_BUF(buf, size) \
243 wg_dump_buf(__func__, buf, size) 243 wg_dump_buf(__func__, buf, size)
244#else 244#else
245#define WG_DUMP_HASH(name, hash) __nothing 245#define WG_DUMP_HASH(name, hash) __nothing
246#define WG_DUMP_HASH48(name, hash) __nothing 246#define WG_DUMP_HASH48(name, hash) __nothing
247#define WG_DUMP_BUF(buf, size) __nothing 247#define WG_DUMP_BUF(buf, size) __nothing
248#endif /* WG_DEBUG_DUMP */ 248#endif /* WG_DEBUG_DUMP */
249 249
250#define WG_MTU 1420 250#define WG_MTU 1420
251#define WG_ALLOWEDIPS 16 251#define WG_ALLOWEDIPS 16
252 252
253#define CURVE25519_KEY_LEN 32 253#define CURVE25519_KEY_LEN 32
254#define TAI64N_LEN sizeof(uint32_t) * 3 254#define TAI64N_LEN sizeof(uint32_t) * 3
255#define POLY1305_AUTHTAG_LEN 16 255#define POLY1305_AUTHTAG_LEN 16
256#define HMAC_BLOCK_LEN 64 256#define HMAC_BLOCK_LEN 64
257 257
258/* [N] 4.1: "DHLEN must be 32 or greater." WireGuard chooses 32. */ 258/* [N] 4.1: "DHLEN must be 32 or greater." WireGuard chooses 32. */
259/* [N] 4.3: Hash functions */ 259/* [N] 4.3: Hash functions */
260#define NOISE_DHLEN 32 260#define NOISE_DHLEN 32
261/* [N] 4.3: "Must be 32 or 64." WireGuard chooses 32. */ 261/* [N] 4.3: "Must be 32 or 64." WireGuard chooses 32. */
262#define NOISE_HASHLEN 32 262#define NOISE_HASHLEN 32
263#define NOISE_BLOCKLEN 64 263#define NOISE_BLOCKLEN 64
264#define NOISE_HKDF_OUTPUT_LEN NOISE_HASHLEN 264#define NOISE_HKDF_OUTPUT_LEN NOISE_HASHLEN
265/* [N] 5.1: "k" */ 265/* [N] 5.1: "k" */
266#define NOISE_CIPHER_KEY_LEN 32 266#define NOISE_CIPHER_KEY_LEN 32
267/* 267/*
268 * [N] 9.2: "psk" 268 * [N] 9.2: "psk"
269 * "... psk is a 32-byte secret value provided by the application." 269 * "... psk is a 32-byte secret value provided by the application."
270 */ 270 */
271#define NOISE_PRESHARED_KEY_LEN 32 271#define NOISE_PRESHARED_KEY_LEN 32
272 272
273#define WG_STATIC_KEY_LEN CURVE25519_KEY_LEN 273#define WG_STATIC_KEY_LEN CURVE25519_KEY_LEN
274#define WG_TIMESTAMP_LEN TAI64N_LEN 274#define WG_TIMESTAMP_LEN TAI64N_LEN
275 275
276#define WG_PRESHARED_KEY_LEN NOISE_PRESHARED_KEY_LEN 276#define WG_PRESHARED_KEY_LEN NOISE_PRESHARED_KEY_LEN
277 277
278#define WG_COOKIE_LEN 16 278#define WG_COOKIE_LEN 16
279#define WG_MAC_LEN 16 279#define WG_MAC_LEN 16
280#define WG_RANDVAL_LEN 24 280#define WG_RANDVAL_LEN 24
281 281
282#define WG_EPHEMERAL_KEY_LEN CURVE25519_KEY_LEN 282#define WG_EPHEMERAL_KEY_LEN CURVE25519_KEY_LEN
283/* [N] 5.2: "ck: A chaining key of HASHLEN bytes" */ 283/* [N] 5.2: "ck: A chaining key of HASHLEN bytes" */
284#define WG_CHAINING_KEY_LEN NOISE_HASHLEN 284#define WG_CHAINING_KEY_LEN NOISE_HASHLEN
285/* [N] 5.2: "h: A hash output of HASHLEN bytes" */ 285/* [N] 5.2: "h: A hash output of HASHLEN bytes" */
286#define WG_HASH_LEN NOISE_HASHLEN 286#define WG_HASH_LEN NOISE_HASHLEN
287#define WG_CIPHER_KEY_LEN NOISE_CIPHER_KEY_LEN 287#define WG_CIPHER_KEY_LEN NOISE_CIPHER_KEY_LEN
288#define WG_DH_OUTPUT_LEN NOISE_DHLEN 288#define WG_DH_OUTPUT_LEN NOISE_DHLEN
289#define WG_KDF_OUTPUT_LEN NOISE_HKDF_OUTPUT_LEN 289#define WG_KDF_OUTPUT_LEN NOISE_HKDF_OUTPUT_LEN
290#define WG_AUTHTAG_LEN POLY1305_AUTHTAG_LEN 290#define WG_AUTHTAG_LEN POLY1305_AUTHTAG_LEN
291#define WG_DATA_KEY_LEN 32 291#define WG_DATA_KEY_LEN 32
292#define WG_SALT_LEN 24 292#define WG_SALT_LEN 24
293 293
294/* 294/*
295 * The protocol messages 295 * The protocol messages
296 */ 296 */
297struct wg_msg { 297struct wg_msg {
298 uint32_t wgm_type; 298 uint32_t wgm_type;
299} __packed; 299} __packed;
300 300
301/* [W] 5.4.2 First Message: Initiator to Responder */ 301/* [W] 5.4.2 First Message: Initiator to Responder */
302struct wg_msg_init { 302struct wg_msg_init {
303 uint32_t wgmi_type; 303 uint32_t wgmi_type;
304 uint32_t wgmi_sender; 304 uint32_t wgmi_sender;
305 uint8_t wgmi_ephemeral[WG_EPHEMERAL_KEY_LEN]; 305 uint8_t wgmi_ephemeral[WG_EPHEMERAL_KEY_LEN];
306 uint8_t wgmi_static[WG_STATIC_KEY_LEN + WG_AUTHTAG_LEN]; 306 uint8_t wgmi_static[WG_STATIC_KEY_LEN + WG_AUTHTAG_LEN];
307 uint8_t wgmi_timestamp[WG_TIMESTAMP_LEN + WG_AUTHTAG_LEN]; 307 uint8_t wgmi_timestamp[WG_TIMESTAMP_LEN + WG_AUTHTAG_LEN];
308 uint8_t wgmi_mac1[WG_MAC_LEN]; 308 uint8_t wgmi_mac1[WG_MAC_LEN];
309 uint8_t wgmi_mac2[WG_MAC_LEN]; 309 uint8_t wgmi_mac2[WG_MAC_LEN];
310} __packed; 310} __packed;
311 311
312/* [W] 5.4.3 Second Message: Responder to Initiator */ 312/* [W] 5.4.3 Second Message: Responder to Initiator */
313struct wg_msg_resp { 313struct wg_msg_resp {
314 uint32_t wgmr_type; 314 uint32_t wgmr_type;
315 uint32_t wgmr_sender; 315 uint32_t wgmr_sender;
316 uint32_t wgmr_receiver; 316 uint32_t wgmr_receiver;
317 uint8_t wgmr_ephemeral[WG_EPHEMERAL_KEY_LEN]; 317 uint8_t wgmr_ephemeral[WG_EPHEMERAL_KEY_LEN];
318 uint8_t wgmr_empty[0 + WG_AUTHTAG_LEN]; 318 uint8_t wgmr_empty[0 + WG_AUTHTAG_LEN];
319 uint8_t wgmr_mac1[WG_MAC_LEN]; 319 uint8_t wgmr_mac1[WG_MAC_LEN];
320 uint8_t wgmr_mac2[WG_MAC_LEN]; 320 uint8_t wgmr_mac2[WG_MAC_LEN];
321} __packed; 321} __packed;
322 322
323/* [W] 5.4.6 Subsequent Messages: Transport Data Messages */ 323/* [W] 5.4.6 Subsequent Messages: Transport Data Messages */
324struct wg_msg_data { 324struct wg_msg_data {
325 uint32_t wgmd_type; 325 uint32_t wgmd_type;
326 uint32_t wgmd_receiver; 326 uint32_t wgmd_receiver;
327 uint64_t wgmd_counter; 327 uint64_t wgmd_counter;
328 uint32_t wgmd_packet[0]; 328 uint32_t wgmd_packet[0];
329} __packed; 329} __packed;
330 330
331/* [W] 5.4.7 Under Load: Cookie Reply Message */ 331/* [W] 5.4.7 Under Load: Cookie Reply Message */
332struct wg_msg_cookie { 332struct wg_msg_cookie {
333 uint32_t wgmc_type; 333 uint32_t wgmc_type;
334 uint32_t wgmc_receiver; 334 uint32_t wgmc_receiver;
335 uint8_t wgmc_salt[WG_SALT_LEN]; 335 uint8_t wgmc_salt[WG_SALT_LEN];
336 uint8_t wgmc_cookie[WG_COOKIE_LEN + WG_AUTHTAG_LEN]; 336 uint8_t wgmc_cookie[WG_COOKIE_LEN + WG_AUTHTAG_LEN];
337} __packed; 337} __packed;
338 338
339#define WG_MSG_TYPE_INIT 1 339#define WG_MSG_TYPE_INIT 1
340#define WG_MSG_TYPE_RESP 2 340#define WG_MSG_TYPE_RESP 2
341#define WG_MSG_TYPE_COOKIE 3 341#define WG_MSG_TYPE_COOKIE 3
342#define WG_MSG_TYPE_DATA 4 342#define WG_MSG_TYPE_DATA 4
343#define WG_MSG_TYPE_MAX WG_MSG_TYPE_DATA 343#define WG_MSG_TYPE_MAX WG_MSG_TYPE_DATA
344 344
345/* Sliding windows */ 345/* Sliding windows */
346 346
347#define SLIWIN_BITS 2048u 347#define SLIWIN_BITS 2048u
348#define SLIWIN_TYPE uint32_t 348#define SLIWIN_TYPE uint32_t
349#define SLIWIN_BPW NBBY*sizeof(SLIWIN_TYPE) 349#define SLIWIN_BPW NBBY*sizeof(SLIWIN_TYPE)
350#define SLIWIN_WORDS howmany(SLIWIN_BITS, SLIWIN_BPW) 350#define SLIWIN_WORDS howmany(SLIWIN_BITS, SLIWIN_BPW)
351#define SLIWIN_NPKT (SLIWIN_BITS - NBBY*sizeof(SLIWIN_TYPE)) 351#define SLIWIN_NPKT (SLIWIN_BITS - NBBY*sizeof(SLIWIN_TYPE))
352 352
353struct sliwin { 353struct sliwin {
354 SLIWIN_TYPE B[SLIWIN_WORDS]; 354 SLIWIN_TYPE B[SLIWIN_WORDS];
355 uint64_t T; 355 uint64_t T;
356}; 356};
357 357
358static void 358static void
359sliwin_reset(struct sliwin *W) 359sliwin_reset(struct sliwin *W)
360{ 360{
361 361
362 memset(W, 0, sizeof(*W)); 362 memset(W, 0, sizeof(*W));
363} 363}
364 364
365static int 365static int
366sliwin_check_fast(const volatile struct sliwin *W, uint64_t S) 366sliwin_check_fast(const volatile struct sliwin *W, uint64_t S)
367{ 367{
368 368
369 /* 369 /*
370 * If it's more than one window older than the highest sequence 370 * If it's more than one window older than the highest sequence
371 * number we've seen, reject. 371 * number we've seen, reject.
372 */ 372 */
373#ifdef __HAVE_ATOMIC64_LOADSTORE 373#ifdef __HAVE_ATOMIC64_LOADSTORE
374 if (S + SLIWIN_NPKT < atomic_load_relaxed(&W->T)) 374 if (S + SLIWIN_NPKT < atomic_load_relaxed(&W->T))
375 return EAUTH; 375 return EAUTH;
376#endif 376#endif
377 377
378 /* 378 /*
379 * Otherwise, we need to take the lock to decide, so don't 379 * Otherwise, we need to take the lock to decide, so don't
380 * reject just yet. Caller must serialize a call to 380 * reject just yet. Caller must serialize a call to
381 * sliwin_update in this case. 381 * sliwin_update in this case.
382 */ 382 */
383 return 0; 383 return 0;
384} 384}
385 385
386static int 386static int
387sliwin_update(struct sliwin *W, uint64_t S) 387sliwin_update(struct sliwin *W, uint64_t S)
388{ 388{
389 unsigned word, bit; 389 unsigned word, bit;
390 390
391 /* 391 /*
392 * If it's more than one window older than the highest sequence 392 * If it's more than one window older than the highest sequence
393 * number we've seen, reject. 393 * number we've seen, reject.
394 */ 394 */
395 if (S + SLIWIN_NPKT < W->T) 395 if (S + SLIWIN_NPKT < W->T)
396 return EAUTH; 396 return EAUTH;
397 397
398 /* 398 /*
399 * If it's higher than the highest sequence number we've seen, 399 * If it's higher than the highest sequence number we've seen,
400 * advance the window. 400 * advance the window.
401 */ 401 */
402 if (S > W->T) { 402 if (S > W->T) {
403 uint64_t i = W->T / SLIWIN_BPW; 403 uint64_t i = W->T / SLIWIN_BPW;
404 uint64_t j = S / SLIWIN_BPW; 404 uint64_t j = S / SLIWIN_BPW;
405 unsigned k; 405 unsigned k;
406 406
407 for (k = 0; k < MIN(j - i, SLIWIN_WORDS); k++) 407 for (k = 0; k < MIN(j - i, SLIWIN_WORDS); k++)
408 W->B[(i + k + 1) % SLIWIN_WORDS] = 0; 408 W->B[(i + k + 1) % SLIWIN_WORDS] = 0;
409#ifdef __HAVE_ATOMIC64_LOADSTORE 409#ifdef __HAVE_ATOMIC64_LOADSTORE
410 atomic_store_relaxed(&W->T, S); 410 atomic_store_relaxed(&W->T, S);
411#else 411#else
412 W->T = S; 412 W->T = S;
413#endif 413#endif
414 } 414 }
415 415
416 /* Test and set the bit -- if already set, reject. */ 416 /* Test and set the bit -- if already set, reject. */
417 word = (S / SLIWIN_BPW) % SLIWIN_WORDS; 417 word = (S / SLIWIN_BPW) % SLIWIN_WORDS;
418 bit = S % SLIWIN_BPW; 418 bit = S % SLIWIN_BPW;
419 if (W->B[word] & (1UL << bit)) 419 if (W->B[word] & (1UL << bit))
420 return EAUTH; 420 return EAUTH;
421 W->B[word] |= 1UL << bit; 421 W->B[word] |= 1UL << bit;
422 422
423 /* Accept! */ 423 /* Accept! */
424 return 0; 424 return 0;
425} 425}
426 426
427struct wg_worker { 427struct wg_worker {
428 kmutex_t wgw_lock; 428 kmutex_t wgw_lock;
429 kcondvar_t wgw_cv; 429 kcondvar_t wgw_cv;
430 bool wgw_todie; 430 bool wgw_todie;
431 struct socket *wgw_so4; 431 struct socket *wgw_so4;
432 struct socket *wgw_so6; 432 struct socket *wgw_so6;
433 int wgw_wakeup_reasons; 433 int wgw_wakeup_reasons;
434#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 __BIT(0) 434#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 __BIT(0)
435#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6 __BIT(1) 435#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6 __BIT(1)
436#define WG_WAKEUP_REASON_PEER __BIT(2) 436#define WG_WAKEUP_REASON_PEER __BIT(2)
437}; 437};
438 438
439struct wg_session { 439struct wg_session {
440 struct wg_peer *wgs_peer; 440 struct wg_peer *wgs_peer;
441 struct psref_target 441 struct psref_target
442 wgs_psref; 442 wgs_psref;
443 kmutex_t *wgs_lock; 443 kmutex_t *wgs_lock;
444 444
445 int wgs_state; 445 int wgs_state;
446#define WGS_STATE_UNKNOWN 0 446#define WGS_STATE_UNKNOWN 0
447#define WGS_STATE_INIT_ACTIVE 1 447#define WGS_STATE_INIT_ACTIVE 1
448#define WGS_STATE_INIT_PASSIVE 2 448#define WGS_STATE_INIT_PASSIVE 2
449#define WGS_STATE_ESTABLISHED 3 449#define WGS_STATE_ESTABLISHED 3
450#define WGS_STATE_DESTROYING 4 450#define WGS_STATE_DESTROYING 4
451 451
452 time_t wgs_time_established; 452 time_t wgs_time_established;
453 time_t wgs_time_last_data_sent; 453 time_t wgs_time_last_data_sent;
454 bool wgs_is_initiator; 454 bool wgs_is_initiator;
455 455
456 uint32_t wgs_sender_index; 456 uint32_t wgs_sender_index;
457 uint32_t wgs_receiver_index; 457 uint32_t wgs_receiver_index;
458#ifdef __HAVE_ATOMIC64_LOADSTORE 458#ifdef __HAVE_ATOMIC64_LOADSTORE
459 volatile uint64_t 459 volatile uint64_t
460 wgs_send_counter; 460 wgs_send_counter;
461#else 461#else
462 kmutex_t wgs_send_counter_lock; 462 kmutex_t wgs_send_counter_lock;
463 uint64_t wgs_send_counter; 463 uint64_t wgs_send_counter;
464#endif 464#endif
465 465
466 struct { 466 struct {
467 kmutex_t lock; 467 kmutex_t lock;
468 struct sliwin window; 468 struct sliwin window;
469 } *wgs_recvwin; 469 } *wgs_recvwin;
470 470
471 uint8_t wgs_handshake_hash[WG_HASH_LEN]; 471 uint8_t wgs_handshake_hash[WG_HASH_LEN];
472 uint8_t wgs_chaining_key[WG_CHAINING_KEY_LEN]; 472 uint8_t wgs_chaining_key[WG_CHAINING_KEY_LEN];
473 uint8_t wgs_ephemeral_key_pub[WG_EPHEMERAL_KEY_LEN]; 473 uint8_t wgs_ephemeral_key_pub[WG_EPHEMERAL_KEY_LEN];
474 uint8_t wgs_ephemeral_key_priv[WG_EPHEMERAL_KEY_LEN]; 474 uint8_t wgs_ephemeral_key_priv[WG_EPHEMERAL_KEY_LEN];
475 uint8_t wgs_ephemeral_key_peer[WG_EPHEMERAL_KEY_LEN]; 475 uint8_t wgs_ephemeral_key_peer[WG_EPHEMERAL_KEY_LEN];
476 uint8_t wgs_tkey_send[WG_DATA_KEY_LEN]; 476 uint8_t wgs_tkey_send[WG_DATA_KEY_LEN];
477 uint8_t wgs_tkey_recv[WG_DATA_KEY_LEN]; 477 uint8_t wgs_tkey_recv[WG_DATA_KEY_LEN];
478}; 478};
479 479
480struct wg_sockaddr { 480struct wg_sockaddr {
481 union { 481 union {
482 struct sockaddr_storage _ss; 482 struct sockaddr_storage _ss;
483 struct sockaddr _sa; 483 struct sockaddr _sa;
484 struct sockaddr_in _sin; 484 struct sockaddr_in _sin;
485 struct sockaddr_in6 _sin6; 485 struct sockaddr_in6 _sin6;
486 }; 486 };
487 struct psref_target wgsa_psref; 487 struct psref_target wgsa_psref;
488}; 488};
489 489
490#define wgsatosa(wgsa) (&(wgsa)->_sa) 490#define wgsatosa(wgsa) (&(wgsa)->_sa)
491#define wgsatosin(wgsa) (&(wgsa)->_sin) 491#define wgsatosin(wgsa) (&(wgsa)->_sin)
492#define wgsatosin6(wgsa) (&(wgsa)->_sin6) 492#define wgsatosin6(wgsa) (&(wgsa)->_sin6)
493 493
494struct wg_peer; 494struct wg_peer;
495struct wg_allowedip { 495struct wg_allowedip {
496 struct radix_node wga_nodes[2]; 496 struct radix_node wga_nodes[2];
497 struct wg_sockaddr _wga_sa_addr; 497 struct wg_sockaddr _wga_sa_addr;
498 struct wg_sockaddr _wga_sa_mask; 498 struct wg_sockaddr _wga_sa_mask;
499#define wga_sa_addr _wga_sa_addr._sa 499#define wga_sa_addr _wga_sa_addr._sa
500#define wga_sa_mask _wga_sa_mask._sa 500#define wga_sa_mask _wga_sa_mask._sa
501 501
502 int wga_family; 502 int wga_family;
503 uint8_t wga_cidr; 503 uint8_t wga_cidr;
504 union { 504 union {
505 struct in_addr _ip4; 505 struct in_addr _ip4;
506 struct in6_addr _ip6; 506 struct in6_addr _ip6;
507 } wga_addr; 507 } wga_addr;
508#define wga_addr4 wga_addr._ip4 508#define wga_addr4 wga_addr._ip4
509#define wga_addr6 wga_addr._ip6 509#define wga_addr6 wga_addr._ip6
510 510
511 struct wg_peer *wga_peer; 511 struct wg_peer *wga_peer;
512}; 512};
513 513
514typedef uint8_t wg_timestamp_t[WG_TIMESTAMP_LEN]; 514typedef uint8_t wg_timestamp_t[WG_TIMESTAMP_LEN];
515 515
516struct wg_ppsratecheck { 516struct wg_ppsratecheck {
517 struct timeval wgprc_lasttime; 517 struct timeval wgprc_lasttime;
518 int wgprc_curpps; 518 int wgprc_curpps;
519}; 519};
520 520
521struct wg_softc; 521struct wg_softc;
522struct wg_peer { 522struct wg_peer {
523 struct wg_softc *wgp_sc; 523 struct wg_softc *wgp_sc;
524 char wgp_name[WG_PEER_NAME_MAXLEN + 1]; 524 char wgp_name[WG_PEER_NAME_MAXLEN + 1];
525 struct pslist_entry wgp_peerlist_entry; 525 struct pslist_entry wgp_peerlist_entry;
526 pserialize_t wgp_psz; 526 pserialize_t wgp_psz;
527 struct psref_target wgp_psref; 527 struct psref_target wgp_psref;
528 kmutex_t *wgp_lock; 528 kmutex_t *wgp_lock;
529 529
530 uint8_t wgp_pubkey[WG_STATIC_KEY_LEN]; 530 uint8_t wgp_pubkey[WG_STATIC_KEY_LEN];
531 struct wg_sockaddr *wgp_endpoint; 531 struct wg_sockaddr *wgp_endpoint;
532#define wgp_ss wgp_endpoint->_ss 532#define wgp_ss wgp_endpoint->_ss
533#define wgp_sa wgp_endpoint->_sa 533#define wgp_sa wgp_endpoint->_sa
534#define wgp_sin wgp_endpoint->_sin 534#define wgp_sin wgp_endpoint->_sin
535#define wgp_sin6 wgp_endpoint->_sin6 535#define wgp_sin6 wgp_endpoint->_sin6
536 struct wg_sockaddr *wgp_endpoint0; 536 struct wg_sockaddr *wgp_endpoint0;
537 bool wgp_endpoint_changing; 537 bool wgp_endpoint_changing;
538 bool wgp_endpoint_available; 538 bool wgp_endpoint_available;
539 539
540 /* The preshared key (optional) */ 540 /* The preshared key (optional) */
541 uint8_t wgp_psk[WG_PRESHARED_KEY_LEN]; 541 uint8_t wgp_psk[WG_PRESHARED_KEY_LEN];
542 542
543 int wgp_state; 543 int wgp_state;
544#define WGP_STATE_INIT 0 544#define WGP_STATE_INIT 0
545#define WGP_STATE_ESTABLISHED 1 545#define WGP_STATE_ESTABLISHED 1
546#define WGP_STATE_GIVEUP 2 546#define WGP_STATE_GIVEUP 2
547#define WGP_STATE_DESTROYING 3 547#define WGP_STATE_DESTROYING 3
548 548
549 void *wgp_si; 549 void *wgp_si;
550 pcq_t *wgp_q; 550 pcq_t *wgp_q;
551 551
552 struct wg_session *wgp_session_stable; 552 struct wg_session *wgp_session_stable;
553 struct wg_session *wgp_session_unstable; 553 struct wg_session *wgp_session_unstable;
554 554
555 /* timestamp in big-endian */ 555 /* timestamp in big-endian */
556 wg_timestamp_t wgp_timestamp_latest_init; 556 wg_timestamp_t wgp_timestamp_latest_init;
557 557
558 struct timespec wgp_last_handshake_time; 558 struct timespec wgp_last_handshake_time;
559 559
560 callout_t wgp_rekey_timer; 560 callout_t wgp_rekey_timer;
561 callout_t wgp_handshake_timeout_timer; 561 callout_t wgp_handshake_timeout_timer;
562 callout_t wgp_session_dtor_timer; 562 callout_t wgp_session_dtor_timer;
563 563
564 time_t wgp_handshake_start_time; 564 time_t wgp_handshake_start_time;
565 565
566 int wgp_n_allowedips; 566 int wgp_n_allowedips;
567 struct wg_allowedip wgp_allowedips[WG_ALLOWEDIPS]; 567 struct wg_allowedip wgp_allowedips[WG_ALLOWEDIPS];
568 568
569 time_t wgp_latest_cookie_time; 569 time_t wgp_latest_cookie_time;
570 uint8_t wgp_latest_cookie[WG_COOKIE_LEN]; 570 uint8_t wgp_latest_cookie[WG_COOKIE_LEN];
571 uint8_t wgp_last_sent_mac1[WG_MAC_LEN]; 571 uint8_t wgp_last_sent_mac1[WG_MAC_LEN];
572 bool wgp_last_sent_mac1_valid; 572 bool wgp_last_sent_mac1_valid;
573 uint8_t wgp_last_sent_cookie[WG_COOKIE_LEN]; 573 uint8_t wgp_last_sent_cookie[WG_COOKIE_LEN];
574 bool wgp_last_sent_cookie_valid; 574 bool wgp_last_sent_cookie_valid;
575 575
576 time_t wgp_last_msg_received_time[WG_MSG_TYPE_MAX]; 576 time_t wgp_last_msg_received_time[WG_MSG_TYPE_MAX];
577 577
578 time_t wgp_last_genrandval_time; 578 time_t wgp_last_genrandval_time;
579 uint32_t wgp_randval; 579 uint32_t wgp_randval;
580 580
581 struct wg_ppsratecheck wgp_ppsratecheck; 581 struct wg_ppsratecheck wgp_ppsratecheck;
582 582
583 volatile unsigned int wgp_tasks; 583 volatile unsigned int wgp_tasks;
584#define WGP_TASK_SEND_INIT_MESSAGE __BIT(0) 584#define WGP_TASK_SEND_INIT_MESSAGE __BIT(0)
585#define WGP_TASK_ENDPOINT_CHANGED __BIT(1) 585#define WGP_TASK_ENDPOINT_CHANGED __BIT(1)
586#define WGP_TASK_SEND_KEEPALIVE_MESSAGE __BIT(2) 586#define WGP_TASK_SEND_KEEPALIVE_MESSAGE __BIT(2)
587#define WGP_TASK_DESTROY_PREV_SESSION __BIT(3) 587#define WGP_TASK_DESTROY_PREV_SESSION __BIT(3)
588}; 588};
589 589
590struct wg_ops; 590struct wg_ops;
591 591
592struct wg_softc { 592struct wg_softc {
593 struct ifnet wg_if; 593 struct ifnet wg_if;
594 LIST_ENTRY(wg_softc) wg_list; 594 LIST_ENTRY(wg_softc) wg_list;
595 kmutex_t *wg_lock; 595 kmutex_t *wg_lock;
596 krwlock_t *wg_rwlock; 596 krwlock_t *wg_rwlock;
597 597
598 uint8_t wg_privkey[WG_STATIC_KEY_LEN]; 598 uint8_t wg_privkey[WG_STATIC_KEY_LEN];
599 uint8_t wg_pubkey[WG_STATIC_KEY_LEN]; 599 uint8_t wg_pubkey[WG_STATIC_KEY_LEN];
600 600
601 int wg_npeers; 601 int wg_npeers;
602 struct pslist_head wg_peers; 602 struct pslist_head wg_peers;
603 uint16_t wg_listen_port; 603 uint16_t wg_listen_port;
604 604
605 struct wg_worker *wg_worker; 605 struct wg_worker *wg_worker;
606 lwp_t *wg_worker_lwp; 606 lwp_t *wg_worker_lwp;
607 607
608 struct radix_node_head *wg_rtable_ipv4; 608 struct radix_node_head *wg_rtable_ipv4;
609 struct radix_node_head *wg_rtable_ipv6; 609 struct radix_node_head *wg_rtable_ipv6;
610 610
611 struct wg_ppsratecheck wg_ppsratecheck; 611 struct wg_ppsratecheck wg_ppsratecheck;
612 612
613 struct wg_ops *wg_ops; 613 struct wg_ops *wg_ops;
614 614
615#ifdef WG_RUMPKERNEL 615#ifdef WG_RUMPKERNEL
616 struct wg_user *wg_user; 616 struct wg_user *wg_user;
617#endif 617#endif
618}; 618};
619 619
620/* [W] 6.1 Preliminaries */ 620/* [W] 6.1 Preliminaries */
621#define WG_REKEY_AFTER_MESSAGES (1ULL << 60) 621#define WG_REKEY_AFTER_MESSAGES (1ULL << 60)
622#define WG_REJECT_AFTER_MESSAGES (UINT64_MAX - (1 << 13)) 622#define WG_REJECT_AFTER_MESSAGES (UINT64_MAX - (1 << 13))
623#define WG_REKEY_AFTER_TIME 120 623#define WG_REKEY_AFTER_TIME 120
624#define WG_REJECT_AFTER_TIME 180 624#define WG_REJECT_AFTER_TIME 180
625#define WG_REKEY_ATTEMPT_TIME 90 625#define WG_REKEY_ATTEMPT_TIME 90
626#define WG_REKEY_TIMEOUT 5 626#define WG_REKEY_TIMEOUT 5
627#define WG_KEEPALIVE_TIMEOUT 10 627#define WG_KEEPALIVE_TIMEOUT 10
628 628
629#define WG_COOKIE_TIME 120 629#define WG_COOKIE_TIME 120
630#define WG_RANDVAL_TIME (2 * 60) 630#define WG_RANDVAL_TIME (2 * 60)
631 631
632static uint64_t wg_rekey_after_messages = WG_REKEY_AFTER_MESSAGES; 632static uint64_t wg_rekey_after_messages = WG_REKEY_AFTER_MESSAGES;
633static uint64_t wg_reject_after_messages = WG_REJECT_AFTER_MESSAGES; 633static uint64_t wg_reject_after_messages = WG_REJECT_AFTER_MESSAGES;
634static unsigned wg_rekey_after_time = WG_REKEY_AFTER_TIME; 634static unsigned wg_rekey_after_time = WG_REKEY_AFTER_TIME;
635static unsigned wg_reject_after_time = WG_REJECT_AFTER_TIME; 635static unsigned wg_reject_after_time = WG_REJECT_AFTER_TIME;
636static unsigned wg_rekey_attempt_time = WG_REKEY_ATTEMPT_TIME; 636static unsigned wg_rekey_attempt_time = WG_REKEY_ATTEMPT_TIME;
637static unsigned wg_rekey_timeout = WG_REKEY_TIMEOUT; 637static unsigned wg_rekey_timeout = WG_REKEY_TIMEOUT;
638static unsigned wg_keepalive_timeout = WG_KEEPALIVE_TIMEOUT; 638static unsigned wg_keepalive_timeout = WG_KEEPALIVE_TIMEOUT;
639 639
640static struct mbuf * 640static struct mbuf *
641 wg_get_mbuf(size_t, size_t); 641 wg_get_mbuf(size_t, size_t);
642 642
643static void wg_wakeup_worker(struct wg_worker *, int); 643static void wg_wakeup_worker(struct wg_worker *, int);
644 644
645static int wg_send_data_msg(struct wg_peer *, struct wg_session *, 645static int wg_send_data_msg(struct wg_peer *, struct wg_session *,
646 struct mbuf *); 646 struct mbuf *);
647static int wg_send_cookie_msg(struct wg_softc *, struct wg_peer *, 647static int wg_send_cookie_msg(struct wg_softc *, struct wg_peer *,
648 const uint32_t, const uint8_t [], const struct sockaddr *); 648 const uint32_t, const uint8_t [], const struct sockaddr *);
649static int wg_send_handshake_msg_resp(struct wg_softc *, 649static int wg_send_handshake_msg_resp(struct wg_softc *,
650 struct wg_peer *, const struct wg_msg_init *); 650 struct wg_peer *, const struct wg_msg_init *);
651static void wg_send_keepalive_msg(struct wg_peer *, struct wg_session *); 651static void wg_send_keepalive_msg(struct wg_peer *, struct wg_session *);
652 652
653static struct wg_peer * 653static struct wg_peer *
654 wg_pick_peer_by_sa(struct wg_softc *, const struct sockaddr *, 654 wg_pick_peer_by_sa(struct wg_softc *, const struct sockaddr *,
655 struct psref *); 655 struct psref *);
656static struct wg_peer * 656static struct wg_peer *
657 wg_lookup_peer_by_pubkey(struct wg_softc *, 657 wg_lookup_peer_by_pubkey(struct wg_softc *,
658 const uint8_t [], struct psref *); 658 const uint8_t [], struct psref *);
659 659
660static struct wg_session * 660static struct wg_session *
661 wg_lookup_session_by_index(struct wg_softc *, 661 wg_lookup_session_by_index(struct wg_softc *,
662 const uint32_t, struct psref *); 662 const uint32_t, struct psref *);
663 663
664static void wg_update_endpoint_if_necessary(struct wg_peer *, 664static void wg_update_endpoint_if_necessary(struct wg_peer *,
665 const struct sockaddr *); 665 const struct sockaddr *);
666 666
667static void wg_schedule_rekey_timer(struct wg_peer *); 667static void wg_schedule_rekey_timer(struct wg_peer *);
668static void wg_schedule_session_dtor_timer(struct wg_peer *); 668static void wg_schedule_session_dtor_timer(struct wg_peer *);
669static void wg_stop_session_dtor_timer(struct wg_peer *); 669static void wg_stop_session_dtor_timer(struct wg_peer *);
670 670
671static bool wg_is_underload(struct wg_softc *, struct wg_peer *, int); 671static bool wg_is_underload(struct wg_softc *, struct wg_peer *, int);
672static void wg_calculate_keys(struct wg_session *, const bool); 672static void wg_calculate_keys(struct wg_session *, const bool);
673 673
674static void wg_clear_states(struct wg_session *); 674static void wg_clear_states(struct wg_session *);
675 675
676static void wg_get_peer(struct wg_peer *, struct psref *); 676static void wg_get_peer(struct wg_peer *, struct psref *);
677static void wg_put_peer(struct wg_peer *, struct psref *); 677static void wg_put_peer(struct wg_peer *, struct psref *);
678 678
679static int wg_send_so(struct wg_peer *, struct mbuf *); 679static int wg_send_so(struct wg_peer *, struct mbuf *);
680static int wg_send_udp(struct wg_peer *, struct mbuf *); 680static int wg_send_udp(struct wg_peer *, struct mbuf *);
681static int wg_output(struct ifnet *, struct mbuf *, 681static int wg_output(struct ifnet *, struct mbuf *,
682 const struct sockaddr *, const struct rtentry *); 682 const struct sockaddr *, const struct rtentry *);
683static void wg_input(struct ifnet *, struct mbuf *, const int); 683static void wg_input(struct ifnet *, struct mbuf *, const int);
684static int wg_ioctl(struct ifnet *, u_long, void *); 684static int wg_ioctl(struct ifnet *, u_long, void *);
685static int wg_bind_port(struct wg_softc *, const uint16_t); 685static int wg_bind_port(struct wg_softc *, const uint16_t);
686static int wg_init(struct ifnet *); 686static int wg_init(struct ifnet *);
687static void wg_stop(struct ifnet *, int); 687static void wg_stop(struct ifnet *, int);
688 688
689static int wg_clone_create(struct if_clone *, int); 689static int wg_clone_create(struct if_clone *, int);
690static int wg_clone_destroy(struct ifnet *); 690static int wg_clone_destroy(struct ifnet *);
691 691
692struct wg_ops { 692struct wg_ops {
693 int (*send_hs_msg)(struct wg_peer *, struct mbuf *); 693 int (*send_hs_msg)(struct wg_peer *, struct mbuf *);
694 int (*send_data_msg)(struct wg_peer *, struct mbuf *); 694 int (*send_data_msg)(struct wg_peer *, struct mbuf *);
695 void (*input)(struct ifnet *, struct mbuf *, const int); 695 void (*input)(struct ifnet *, struct mbuf *, const int);
696 int (*bind_port)(struct wg_softc *, const uint16_t); 696 int (*bind_port)(struct wg_softc *, const uint16_t);
697}; 697};
698 698
699struct wg_ops wg_ops_rumpkernel = { 699struct wg_ops wg_ops_rumpkernel = {
700 .send_hs_msg = wg_send_so, 700 .send_hs_msg = wg_send_so,
701 .send_data_msg = wg_send_udp, 701 .send_data_msg = wg_send_udp,
702 .input = wg_input, 702 .input = wg_input,
703 .bind_port = wg_bind_port, 703 .bind_port = wg_bind_port,
704}; 704};
705 705
706#ifdef WG_RUMPKERNEL 706#ifdef WG_RUMPKERNEL
707static bool wg_user_mode(struct wg_softc *); 707static bool wg_user_mode(struct wg_softc *);
708static int wg_ioctl_linkstr(struct wg_softc *, struct ifdrv *); 708static int wg_ioctl_linkstr(struct wg_softc *, struct ifdrv *);
709 709
710static int wg_send_user(struct wg_peer *, struct mbuf *); 710static int wg_send_user(struct wg_peer *, struct mbuf *);
711static void wg_input_user(struct ifnet *, struct mbuf *, const int); 711static void wg_input_user(struct ifnet *, struct mbuf *, const int);
712static int wg_bind_port_user(struct wg_softc *, const uint16_t); 712static int wg_bind_port_user(struct wg_softc *, const uint16_t);
713 713
714struct wg_ops wg_ops_rumpuser = { 714struct wg_ops wg_ops_rumpuser = {
715 .send_hs_msg = wg_send_user, 715 .send_hs_msg = wg_send_user,
716 .send_data_msg = wg_send_user, 716 .send_data_msg = wg_send_user,
717 .input = wg_input_user, 717 .input = wg_input_user,
718 .bind_port = wg_bind_port_user, 718 .bind_port = wg_bind_port_user,
719}; 719};
720#endif 720#endif
721 721
722#define WG_PEER_READER_FOREACH(wgp, wg) \ 722#define WG_PEER_READER_FOREACH(wgp, wg) \
723 PSLIST_READER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \ 723 PSLIST_READER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \
724 wgp_peerlist_entry) 724 wgp_peerlist_entry)
725#define WG_PEER_WRITER_FOREACH(wgp, wg) \ 725#define WG_PEER_WRITER_FOREACH(wgp, wg) \
726 PSLIST_WRITER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \ 726 PSLIST_WRITER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \
727 wgp_peerlist_entry) 727 wgp_peerlist_entry)
728#define WG_PEER_WRITER_INSERT_HEAD(wgp, wg) \ 728#define WG_PEER_WRITER_INSERT_HEAD(wgp, wg) \
729 PSLIST_WRITER_INSERT_HEAD(&(wg)->wg_peers, (wgp), wgp_peerlist_entry) 729 PSLIST_WRITER_INSERT_HEAD(&(wg)->wg_peers, (wgp), wgp_peerlist_entry)
730#define WG_PEER_WRITER_REMOVE(wgp) \ 730#define WG_PEER_WRITER_REMOVE(wgp) \
731 PSLIST_WRITER_REMOVE((wgp), wgp_peerlist_entry) 731 PSLIST_WRITER_REMOVE((wgp), wgp_peerlist_entry)
732 732
733struct wg_route { 733struct wg_route {
734 struct radix_node wgr_nodes[2]; 734 struct radix_node wgr_nodes[2];
735 struct wg_peer *wgr_peer; 735 struct wg_peer *wgr_peer;
736}; 736};
737 737
738static struct radix_node_head * 738static struct radix_node_head *
739wg_rnh(struct wg_softc *wg, const int family) 739wg_rnh(struct wg_softc *wg, const int family)
740{ 740{
741 741
742 switch (family) { 742 switch (family) {
743 case AF_INET: 743 case AF_INET:
744 return wg->wg_rtable_ipv4; 744 return wg->wg_rtable_ipv4;
745#ifdef INET6 745#ifdef INET6
746 case AF_INET6: 746 case AF_INET6:
747 return wg->wg_rtable_ipv6; 747 return wg->wg_rtable_ipv6;
748#endif 748#endif
749 default: 749 default:
750 return NULL; 750 return NULL;
751 } 751 }
752} 752}
753 753
754 754
755/* 755/*
756 * Global variables 756 * Global variables
757 */ 757 */
758LIST_HEAD(wg_sclist, wg_softc); 758LIST_HEAD(wg_sclist, wg_softc);
759static struct { 759static struct {
760 struct wg_sclist list; 760 struct wg_sclist list;
761 kmutex_t lock; 761 kmutex_t lock;
762} wg_softcs __cacheline_aligned; 762} wg_softcs __cacheline_aligned;
763 763
764struct psref_class *wg_psref_class __read_mostly; 764struct psref_class *wg_psref_class __read_mostly;
765 765
766static struct if_clone wg_cloner = 766static struct if_clone wg_cloner =
767 IF_CLONE_INITIALIZER("wg", wg_clone_create, wg_clone_destroy); 767 IF_CLONE_INITIALIZER("wg", wg_clone_create, wg_clone_destroy);
768 768
769 769
770void wgattach(int); 770void wgattach(int);
771/* ARGSUSED */ 771/* ARGSUSED */
772void 772void
773wgattach(int count) 773wgattach(int count)
774{ 774{
775 /* 775 /*
776 * Nothing to do here, initialization is handled by the 776 * Nothing to do here, initialization is handled by the
777 * module initialization code in wginit() below). 777 * module initialization code in wginit() below).
778 */ 778 */
779} 779}
780 780
781static void 781static void
782wginit(void) 782wginit(void)
783{ 783{
784 784
785 wg_psref_class = psref_class_create("wg", IPL_SOFTNET); 785 wg_psref_class = psref_class_create("wg", IPL_SOFTNET);
786 786
787 mutex_init(&wg_softcs.lock, MUTEX_DEFAULT, IPL_NONE); 787 mutex_init(&wg_softcs.lock, MUTEX_DEFAULT, IPL_NONE);
788 LIST_INIT(&wg_softcs.list); 788 LIST_INIT(&wg_softcs.list);
789 if_clone_attach(&wg_cloner); 789 if_clone_attach(&wg_cloner);
790} 790}
791 791
792static int 792static int
793wgdetach(void) 793wgdetach(void)
794{ 794{
795 int error = 0; 795 int error = 0;
796 796
797 mutex_enter(&wg_softcs.lock); 797 mutex_enter(&wg_softcs.lock);
798 if (!LIST_EMPTY(&wg_softcs.list)) { 798 if (!LIST_EMPTY(&wg_softcs.list)) {
799 mutex_exit(&wg_softcs.lock); 799 mutex_exit(&wg_softcs.lock);
800 error = EBUSY; 800 error = EBUSY;
801 } 801 }
802 802
803 if (error == 0) { 803 if (error == 0) {
804 psref_class_destroy(wg_psref_class); 804 psref_class_destroy(wg_psref_class);
805 805
806 if_clone_detach(&wg_cloner); 806 if_clone_detach(&wg_cloner);
807 } 807 }
808 808
809 return error; 809 return error;
810} 810}
811 811
812static void 812static void
813wg_init_key_and_hash(uint8_t ckey[WG_CHAINING_KEY_LEN], 813wg_init_key_and_hash(uint8_t ckey[WG_CHAINING_KEY_LEN],
814 uint8_t hash[WG_HASH_LEN]) 814 uint8_t hash[WG_HASH_LEN])
815{ 815{
816 /* [W] 5.4: CONSTRUCTION */ 816 /* [W] 5.4: CONSTRUCTION */
817 const char *signature = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; 817 const char *signature = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s";
818 /* [W] 5.4: IDENTIFIER */ 818 /* [W] 5.4: IDENTIFIER */
819 const char *id = "WireGuard v1 zx2c4 Jason@zx2c4.com"; 819 const char *id = "WireGuard v1 zx2c4 Jason@zx2c4.com";
820 struct blake2s state; 820 struct blake2s state;
821 821
822 blake2s(ckey, WG_CHAINING_KEY_LEN, NULL, 0, 822 blake2s(ckey, WG_CHAINING_KEY_LEN, NULL, 0,
823 signature, strlen(signature)); 823 signature, strlen(signature));
824 824
825 CTASSERT(WG_HASH_LEN == WG_CHAINING_KEY_LEN); 825 CTASSERT(WG_HASH_LEN == WG_CHAINING_KEY_LEN);
826 memcpy(hash, ckey, WG_CHAINING_KEY_LEN); 826 memcpy(hash, ckey, WG_CHAINING_KEY_LEN);
827 827
828 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 828 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
829 blake2s_update(&state, ckey, WG_CHAINING_KEY_LEN); 829 blake2s_update(&state, ckey, WG_CHAINING_KEY_LEN);
830 blake2s_update(&state, id, strlen(id)); 830 blake2s_update(&state, id, strlen(id));
831 blake2s_final(&state, hash); 831 blake2s_final(&state, hash);
832 832
833 WG_DUMP_HASH("ckey", ckey); 833 WG_DUMP_HASH("ckey", ckey);
834 WG_DUMP_HASH("hash", hash); 834 WG_DUMP_HASH("hash", hash);
835} 835}
836 836
837static void 837static void
838wg_algo_hash(uint8_t hash[WG_HASH_LEN], const uint8_t input[], 838wg_algo_hash(uint8_t hash[WG_HASH_LEN], const uint8_t input[],
839 const size_t inputsize) 839 const size_t inputsize)
840{ 840{
841 struct blake2s state; 841 struct blake2s state;
842 842
843 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 843 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
844 blake2s_update(&state, hash, WG_HASH_LEN); 844 blake2s_update(&state, hash, WG_HASH_LEN);
845 blake2s_update(&state, input, inputsize); 845 blake2s_update(&state, input, inputsize);
846 blake2s_final(&state, hash); 846 blake2s_final(&state, hash);
847} 847}
848 848
849static void 849static void
850wg_algo_mac(uint8_t out[], const size_t outsize, 850wg_algo_mac(uint8_t out[], const size_t outsize,
851 const uint8_t key[], const size_t keylen, 851 const uint8_t key[], const size_t keylen,
852 const uint8_t input1[], const size_t input1len, 852 const uint8_t input1[], const size_t input1len,
853 const uint8_t input2[], const size_t input2len) 853 const uint8_t input2[], const size_t input2len)
854{ 854{
855 struct blake2s state; 855 struct blake2s state;
856 856
857 blake2s_init(&state, outsize, key, keylen); 857 blake2s_init(&state, outsize, key, keylen);
858 858
859 blake2s_update(&state, input1, input1len); 859 blake2s_update(&state, input1, input1len);
860 if (input2 != NULL) 860 if (input2 != NULL)
861 blake2s_update(&state, input2, input2len); 861 blake2s_update(&state, input2, input2len);
862 blake2s_final(&state, out); 862 blake2s_final(&state, out);
863} 863}
864 864
865static void 865static void
866wg_algo_mac_mac1(uint8_t out[], const size_t outsize, 866wg_algo_mac_mac1(uint8_t out[], const size_t outsize,
867 const uint8_t input1[], const size_t input1len, 867 const uint8_t input1[], const size_t input1len,
868 const uint8_t input2[], const size_t input2len) 868 const uint8_t input2[], const size_t input2len)
869{ 869{
870 struct blake2s state; 870 struct blake2s state;
871 /* [W] 5.4: LABEL-MAC1 */ 871 /* [W] 5.4: LABEL-MAC1 */
872 const char *label = "mac1----"; 872 const char *label = "mac1----";
873 uint8_t key[WG_HASH_LEN]; 873 uint8_t key[WG_HASH_LEN];
874 874
875 blake2s_init(&state, sizeof(key), NULL, 0); 875 blake2s_init(&state, sizeof(key), NULL, 0);
876 blake2s_update(&state, label, strlen(label)); 876 blake2s_update(&state, label, strlen(label));
877 blake2s_update(&state, input1, input1len); 877 blake2s_update(&state, input1, input1len);
878 blake2s_final(&state, key); 878 blake2s_final(&state, key);
879 879
880 blake2s_init(&state, outsize, key, sizeof(key)); 880 blake2s_init(&state, outsize, key, sizeof(key));
881 if (input2 != NULL) 881 if (input2 != NULL)
882 blake2s_update(&state, input2, input2len); 882 blake2s_update(&state, input2, input2len);
883 blake2s_final(&state, out); 883 blake2s_final(&state, out);
884} 884}
885 885
886static void 886static void
887wg_algo_mac_cookie(uint8_t out[], const size_t outsize, 887wg_algo_mac_cookie(uint8_t out[], const size_t outsize,
888 const uint8_t input1[], const size_t input1len) 888 const uint8_t input1[], const size_t input1len)
889{ 889{
890 struct blake2s state; 890 struct blake2s state;
891 /* [W] 5.4: LABEL-COOKIE */ 891 /* [W] 5.4: LABEL-COOKIE */
892 const char *label = "cookie--"; 892 const char *label = "cookie--";
893 893
894 blake2s_init(&state, outsize, NULL, 0); 894 blake2s_init(&state, outsize, NULL, 0);
895 blake2s_update(&state, label, strlen(label)); 895 blake2s_update(&state, label, strlen(label));
896 blake2s_update(&state, input1, input1len); 896 blake2s_update(&state, input1, input1len);
897 blake2s_final(&state, out); 897 blake2s_final(&state, out);
898} 898}
899 899
900static void 900static void
901wg_algo_generate_keypair(uint8_t pubkey[WG_EPHEMERAL_KEY_LEN], 901wg_algo_generate_keypair(uint8_t pubkey[WG_EPHEMERAL_KEY_LEN],
902 uint8_t privkey[WG_EPHEMERAL_KEY_LEN]) 902 uint8_t privkey[WG_EPHEMERAL_KEY_LEN])
903{ 903{
904 904
905 CTASSERT(WG_EPHEMERAL_KEY_LEN == crypto_scalarmult_curve25519_BYTES); 905 CTASSERT(WG_EPHEMERAL_KEY_LEN == crypto_scalarmult_curve25519_BYTES);
906 906
907 cprng_strong(kern_cprng, privkey, WG_EPHEMERAL_KEY_LEN, 0); 907 cprng_strong(kern_cprng, privkey, WG_EPHEMERAL_KEY_LEN, 0);
908 crypto_scalarmult_base(pubkey, privkey); 908 crypto_scalarmult_base(pubkey, privkey);
909} 909}
910 910
911static void 911static void
912wg_algo_dh(uint8_t out[WG_DH_OUTPUT_LEN], 912wg_algo_dh(uint8_t out[WG_DH_OUTPUT_LEN],
913 const uint8_t privkey[WG_STATIC_KEY_LEN], 913 const uint8_t privkey[WG_STATIC_KEY_LEN],
914 const uint8_t pubkey[WG_STATIC_KEY_LEN]) 914 const uint8_t pubkey[WG_STATIC_KEY_LEN])
915{ 915{
916 916
917 CTASSERT(WG_STATIC_KEY_LEN == crypto_scalarmult_curve25519_BYTES); 917 CTASSERT(WG_STATIC_KEY_LEN == crypto_scalarmult_curve25519_BYTES);
918 918
919 int ret __diagused = crypto_scalarmult(out, privkey, pubkey); 919 int ret __diagused = crypto_scalarmult(out, privkey, pubkey);
920 KASSERT(ret == 0); 920 KASSERT(ret == 0);
921} 921}
922 922
923static void 923static void
924wg_algo_hmac(uint8_t out[], const size_t outlen, 924wg_algo_hmac(uint8_t out[], const size_t outlen,
925 const uint8_t key[], const size_t keylen, 925 const uint8_t key[], const size_t keylen,
926 const uint8_t in[], const size_t inlen) 926 const uint8_t in[], const size_t inlen)
927{ 927{
928#define IPAD 0x36 928#define IPAD 0x36
929#define OPAD 0x5c 929#define OPAD 0x5c
930 uint8_t hmackey[HMAC_BLOCK_LEN] = {0}; 930 uint8_t hmackey[HMAC_BLOCK_LEN] = {0};
931 uint8_t ipad[HMAC_BLOCK_LEN]; 931 uint8_t ipad[HMAC_BLOCK_LEN];
932 uint8_t opad[HMAC_BLOCK_LEN]; 932 uint8_t opad[HMAC_BLOCK_LEN];
933 int i; 933 int i;
934 struct blake2s state; 934 struct blake2s state;
935 935
936 KASSERT(outlen == WG_HASH_LEN); 936 KASSERT(outlen == WG_HASH_LEN);
937 KASSERT(keylen <= HMAC_BLOCK_LEN); 937 KASSERT(keylen <= HMAC_BLOCK_LEN);
938 938
939 memcpy(hmackey, key, keylen); 939 memcpy(hmackey, key, keylen);
940 940
941 for (i = 0; i < sizeof(hmackey); i++) { 941 for (i = 0; i < sizeof(hmackey); i++) {
942 ipad[i] = hmackey[i] ^ IPAD; 942 ipad[i] = hmackey[i] ^ IPAD;
943 opad[i] = hmackey[i] ^ OPAD; 943 opad[i] = hmackey[i] ^ OPAD;
944 } 944 }
945 945
946 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 946 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
947 blake2s_update(&state, ipad, sizeof(ipad)); 947 blake2s_update(&state, ipad, sizeof(ipad));
948 blake2s_update(&state, in, inlen); 948 blake2s_update(&state, in, inlen);
949 blake2s_final(&state, out); 949 blake2s_final(&state, out);
950 950
951 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 951 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
952 blake2s_update(&state, opad, sizeof(opad)); 952 blake2s_update(&state, opad, sizeof(opad));
953 blake2s_update(&state, out, WG_HASH_LEN); 953 blake2s_update(&state, out, WG_HASH_LEN);
954 blake2s_final(&state, out); 954 blake2s_final(&state, out);
955#undef IPAD 955#undef IPAD
956#undef OPAD 956#undef OPAD
957} 957}
958 958
959static void 959static void
960wg_algo_kdf(uint8_t out1[WG_KDF_OUTPUT_LEN], uint8_t out2[WG_KDF_OUTPUT_LEN], 960wg_algo_kdf(uint8_t out1[WG_KDF_OUTPUT_LEN], uint8_t out2[WG_KDF_OUTPUT_LEN],
961 uint8_t out3[WG_KDF_OUTPUT_LEN], const uint8_t ckey[WG_CHAINING_KEY_LEN], 961 uint8_t out3[WG_KDF_OUTPUT_LEN], const uint8_t ckey[WG_CHAINING_KEY_LEN],
962 const uint8_t input[], const size_t inputlen) 962 const uint8_t input[], const size_t inputlen)
963{ 963{
964 uint8_t tmp1[WG_KDF_OUTPUT_LEN], tmp2[WG_KDF_OUTPUT_LEN + 1]; 964 uint8_t tmp1[WG_KDF_OUTPUT_LEN], tmp2[WG_KDF_OUTPUT_LEN + 1];
965 uint8_t one[1]; 965 uint8_t one[1];
966 966
967 /* 967 /*
968 * [N] 4.3: "an input_key_material byte sequence with length 968 * [N] 4.3: "an input_key_material byte sequence with length
969 * either zero bytes, 32 bytes, or DHLEN bytes." 969 * either zero bytes, 32 bytes, or DHLEN bytes."
970 */ 970 */
971 KASSERT(inputlen == 0 || inputlen == 32 || inputlen == NOISE_DHLEN); 971 KASSERT(inputlen == 0 || inputlen == 32 || inputlen == NOISE_DHLEN);
972 972
973 WG_DUMP_HASH("ckey", ckey); 973 WG_DUMP_HASH("ckey", ckey);
974 if (input != NULL) 974 if (input != NULL)
975 WG_DUMP_HASH("input", input); 975 WG_DUMP_HASH("input", input);
976 wg_algo_hmac(tmp1, sizeof(tmp1), ckey, WG_CHAINING_KEY_LEN, 976 wg_algo_hmac(tmp1, sizeof(tmp1), ckey, WG_CHAINING_KEY_LEN,
977 input, inputlen); 977 input, inputlen);
978 WG_DUMP_HASH("tmp1", tmp1); 978 WG_DUMP_HASH("tmp1", tmp1);
979 one[0] = 1; 979 one[0] = 1;
980 wg_algo_hmac(out1, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1), 980 wg_algo_hmac(out1, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1),
981 one, sizeof(one)); 981 one, sizeof(one));
982 WG_DUMP_HASH("out1", out1); 982 WG_DUMP_HASH("out1", out1);
983 if (out2 == NULL) 983 if (out2 == NULL)
984 return; 984 return;
985 memcpy(tmp2, out1, WG_KDF_OUTPUT_LEN); 985 memcpy(tmp2, out1, WG_KDF_OUTPUT_LEN);
986 tmp2[WG_KDF_OUTPUT_LEN] = 2; 986 tmp2[WG_KDF_OUTPUT_LEN] = 2;
987 wg_algo_hmac(out2, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1), 987 wg_algo_hmac(out2, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1),
988 tmp2, sizeof(tmp2)); 988 tmp2, sizeof(tmp2));
989 WG_DUMP_HASH("out2", out2); 989 WG_DUMP_HASH("out2", out2);
990 if (out3 == NULL) 990 if (out3 == NULL)
991 return; 991 return;
992 memcpy(tmp2, out2, WG_KDF_OUTPUT_LEN); 992 memcpy(tmp2, out2, WG_KDF_OUTPUT_LEN);
993 tmp2[WG_KDF_OUTPUT_LEN] = 3; 993 tmp2[WG_KDF_OUTPUT_LEN] = 3;
994 wg_algo_hmac(out3, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1), 994 wg_algo_hmac(out3, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1),
995 tmp2, sizeof(tmp2)); 995 tmp2, sizeof(tmp2));
996 WG_DUMP_HASH("out3", out3); 996 WG_DUMP_HASH("out3", out3);
997} 997}
998 998
999static void 999static void
1000wg_algo_dh_kdf(uint8_t ckey[WG_CHAINING_KEY_LEN], 1000wg_algo_dh_kdf(uint8_t ckey[WG_CHAINING_KEY_LEN],
1001 uint8_t cipher_key[WG_CIPHER_KEY_LEN], 1001 uint8_t cipher_key[WG_CIPHER_KEY_LEN],
1002 const uint8_t local_key[WG_STATIC_KEY_LEN], 1002 const uint8_t local_key[WG_STATIC_KEY_LEN],
1003 const uint8_t remote_key[WG_STATIC_KEY_LEN]) 1003 const uint8_t remote_key[WG_STATIC_KEY_LEN])
1004{ 1004{
1005 uint8_t dhout[WG_DH_OUTPUT_LEN]; 1005 uint8_t dhout[WG_DH_OUTPUT_LEN];
1006 1006
1007 wg_algo_dh(dhout, local_key, remote_key); 1007 wg_algo_dh(dhout, local_key, remote_key);
1008 wg_algo_kdf(ckey, cipher_key, NULL, ckey, dhout, sizeof(dhout)); 1008 wg_algo_kdf(ckey, cipher_key, NULL, ckey, dhout, sizeof(dhout));
1009 1009
1010 WG_DUMP_HASH("dhout", dhout); 1010 WG_DUMP_HASH("dhout", dhout);
1011 WG_DUMP_HASH("ckey", ckey); 1011 WG_DUMP_HASH("ckey", ckey);
1012 if (cipher_key != NULL) 1012 if (cipher_key != NULL)
1013 WG_DUMP_HASH("cipher_key", cipher_key); 1013 WG_DUMP_HASH("cipher_key", cipher_key);
1014} 1014}
1015 1015
1016static void 1016static void
1017wg_algo_aead_enc(uint8_t out[], size_t expected_outsize, const uint8_t key[], 1017wg_algo_aead_enc(uint8_t out[], size_t expected_outsize, const uint8_t key[],
1018 const uint64_t counter, const uint8_t plain[], const size_t plainsize, 1018 const uint64_t counter, const uint8_t plain[], const size_t plainsize,
1019 const uint8_t auth[], size_t authlen) 1019 const uint8_t auth[], size_t authlen)
1020{ 1020{
1021 uint8_t nonce[(32 + 64) / 8] = {0}; 1021 uint8_t nonce[(32 + 64) / 8] = {0};
1022 long long unsigned int outsize; 1022 long long unsigned int outsize;
1023 int error __diagused; 1023 int error __diagused;
1024 1024
1025 memcpy(&nonce[4], &counter, sizeof(counter)); 1025 memcpy(&nonce[4], &counter, sizeof(counter));
1026 1026
1027 error = crypto_aead_chacha20poly1305_ietf_encrypt(out, &outsize, plain, 1027 error = crypto_aead_chacha20poly1305_ietf_encrypt(out, &outsize, plain,
1028 plainsize, auth, authlen, NULL, nonce, key); 1028 plainsize, auth, authlen, NULL, nonce, key);
1029 KASSERT(error == 0); 1029 KASSERT(error == 0);
1030 KASSERT(outsize == expected_outsize); 1030 KASSERT(outsize == expected_outsize);
1031} 1031}
1032 1032
1033static int 1033static int
1034wg_algo_aead_dec(uint8_t out[], size_t expected_outsize, const uint8_t key[], 1034wg_algo_aead_dec(uint8_t out[], size_t expected_outsize, const uint8_t key[],
1035 const uint64_t counter, const uint8_t encrypted[], 1035 const uint64_t counter, const uint8_t encrypted[],
1036 const size_t encryptedsize, const uint8_t auth[], size_t authlen) 1036 const size_t encryptedsize, const uint8_t auth[], size_t authlen)
1037{ 1037{
1038 uint8_t nonce[(32 + 64) / 8] = {0}; 1038 uint8_t nonce[(32 + 64) / 8] = {0};
1039 long long unsigned int outsize; 1039 long long unsigned int outsize;
1040 int error; 1040 int error;
1041 1041
1042 memcpy(&nonce[4], &counter, sizeof(counter)); 1042 memcpy(&nonce[4], &counter, sizeof(counter));
1043 1043
@@ -2385,1999 +2385,1999 @@ wg_handle_msg_data(struct wg_softc *wg,  @@ -2385,1999 +2385,1999 @@ wg_handle_msg_data(struct wg_softc *wg,
2385 m_copydata(m, sizeof(*wgmd), encrypted_len, encrypted_buf); 2385 m_copydata(m, sizeof(*wgmd), encrypted_len, encrypted_buf);
2386 free_encrypted_buf = true; 2386 free_encrypted_buf = true;
2387 } 2387 }
2388 /* m_ensure_contig may change m regardless of its result */ 2388 /* m_ensure_contig may change m regardless of its result */
2389 KASSERT(m->m_len >= sizeof(*wgmd)); 2389 KASSERT(m->m_len >= sizeof(*wgmd));
2390 wgmd = mtod(m, struct wg_msg_data *); 2390 wgmd = mtod(m, struct wg_msg_data *);
2391 2391
2392 decrypted_len = encrypted_len - WG_AUTHTAG_LEN; 2392 decrypted_len = encrypted_len - WG_AUTHTAG_LEN;
2393 if (decrypted_len > MCLBYTES) { 2393 if (decrypted_len > MCLBYTES) {
2394 /* FIXME handle larger data than MCLBYTES */ 2394 /* FIXME handle larger data than MCLBYTES */
2395 WG_DLOG("couldn't handle larger data than MCLBYTES\n"); 2395 WG_DLOG("couldn't handle larger data than MCLBYTES\n");
2396 goto out; 2396 goto out;
2397 } 2397 }
2398 2398
2399 /* To avoid zero length */ 2399 /* To avoid zero length */
2400 n = wg_get_mbuf(0, decrypted_len + WG_AUTHTAG_LEN); 2400 n = wg_get_mbuf(0, decrypted_len + WG_AUTHTAG_LEN);
2401 if (n == NULL) { 2401 if (n == NULL) {
2402 WG_DLOG("wg_get_mbuf failed\n"); 2402 WG_DLOG("wg_get_mbuf failed\n");
2403 goto out; 2403 goto out;
2404 } 2404 }
2405 decrypted_buf = mtod(n, char *); 2405 decrypted_buf = mtod(n, char *);
2406 2406
2407 WG_DLOG("mlen=%lu, encrypted_len=%lu\n", mlen, encrypted_len); 2407 WG_DLOG("mlen=%lu, encrypted_len=%lu\n", mlen, encrypted_len);
2408 error = wg_algo_aead_dec(decrypted_buf, 2408 error = wg_algo_aead_dec(decrypted_buf,
2409 encrypted_len - WG_AUTHTAG_LEN /* can be 0 */, 2409 encrypted_len - WG_AUTHTAG_LEN /* can be 0 */,
2410 wgs->wgs_tkey_recv, wgmd->wgmd_counter, encrypted_buf, 2410 wgs->wgs_tkey_recv, wgmd->wgmd_counter, encrypted_buf,
2411 encrypted_len, NULL, 0); 2411 encrypted_len, NULL, 0);
2412 if (error != 0) { 2412 if (error != 0) {
2413 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2413 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2414 "failed to wg_algo_aead_dec\n"); 2414 "failed to wg_algo_aead_dec\n");
2415 m_freem(n); 2415 m_freem(n);
2416 goto out; 2416 goto out;
2417 } 2417 }
2418 WG_DLOG("outsize=%u\n", (u_int)decrypted_len); 2418 WG_DLOG("outsize=%u\n", (u_int)decrypted_len);
2419 2419
2420 mutex_enter(&wgs->wgs_recvwin->lock); 2420 mutex_enter(&wgs->wgs_recvwin->lock);
2421 error = sliwin_update(&wgs->wgs_recvwin->window, 2421 error = sliwin_update(&wgs->wgs_recvwin->window,
2422 wgmd->wgmd_counter); 2422 wgmd->wgmd_counter);
2423 mutex_exit(&wgs->wgs_recvwin->lock); 2423 mutex_exit(&wgs->wgs_recvwin->lock);
2424 if (error) { 2424 if (error) {
2425 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2425 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2426 "replay or out-of-window packet: %"PRIu64"\n", 2426 "replay or out-of-window packet: %"PRIu64"\n",
2427 wgmd->wgmd_counter); 2427 wgmd->wgmd_counter);
2428 m_freem(n); 2428 m_freem(n);
2429 goto out; 2429 goto out;
2430 } 2430 }
2431 2431
2432 m_freem(m); 2432 m_freem(m);
2433 m = NULL; 2433 m = NULL;
2434 wgmd = NULL; 2434 wgmd = NULL;
2435 2435
2436 ok = wg_validate_inner_packet(decrypted_buf, decrypted_len, &af); 2436 ok = wg_validate_inner_packet(decrypted_buf, decrypted_len, &af);
2437 if (!ok) { 2437 if (!ok) {
2438 /* something wrong... */ 2438 /* something wrong... */
2439 m_freem(n); 2439 m_freem(n);
2440 goto out; 2440 goto out;
2441 } 2441 }
2442 2442
2443 wg_update_endpoint_if_necessary(wgp, src); 2443 wg_update_endpoint_if_necessary(wgp, src);
2444 2444
2445 ok = wg_validate_route(wg, wgp, af, decrypted_buf); 2445 ok = wg_validate_route(wg, wgp, af, decrypted_buf);
2446 if (ok) { 2446 if (ok) {
2447 wg->wg_ops->input(&wg->wg_if, n, af); 2447 wg->wg_ops->input(&wg->wg_if, n, af);
2448 } else { 2448 } else {
2449 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2449 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2450 "invalid source address\n"); 2450 "invalid source address\n");
2451 m_freem(n); 2451 m_freem(n);
2452 /* 2452 /*
2453 * The inner address is invalid however the session is valid 2453 * The inner address is invalid however the session is valid
2454 * so continue the session processing below. 2454 * so continue the session processing below.
2455 */ 2455 */
2456 } 2456 }
2457 n = NULL; 2457 n = NULL;
2458 2458
2459 if (wgs->wgs_state == WGS_STATE_INIT_PASSIVE) { 2459 if (wgs->wgs_state == WGS_STATE_INIT_PASSIVE) {
2460 struct wg_session *wgs_prev; 2460 struct wg_session *wgs_prev;
2461 2461
2462 KASSERT(wgs == wgp->wgp_session_unstable); 2462 KASSERT(wgs == wgp->wgp_session_unstable);
2463 wgs->wgs_state = WGS_STATE_ESTABLISHED; 2463 wgs->wgs_state = WGS_STATE_ESTABLISHED;
2464 wgs->wgs_time_established = time_uptime; 2464 wgs->wgs_time_established = time_uptime;
2465 wgs->wgs_time_last_data_sent = 0; 2465 wgs->wgs_time_last_data_sent = 0;
2466 wgs->wgs_is_initiator = false; 2466 wgs->wgs_is_initiator = false;
2467 WG_TRACE("WGS_STATE_ESTABLISHED"); 2467 WG_TRACE("WGS_STATE_ESTABLISHED");
2468 2468
2469 mutex_enter(wgp->wgp_lock); 2469 mutex_enter(wgp->wgp_lock);
2470 wg_swap_sessions(wgp); 2470 wg_swap_sessions(wgp);
2471 wgs_prev = wgp->wgp_session_unstable; 2471 wgs_prev = wgp->wgp_session_unstable;
2472 mutex_enter(wgs_prev->wgs_lock); 2472 mutex_enter(wgs_prev->wgs_lock);
2473 getnanotime(&wgp->wgp_last_handshake_time); 2473 getnanotime(&wgp->wgp_last_handshake_time);
2474 wgp->wgp_handshake_start_time = 0; 2474 wgp->wgp_handshake_start_time = 0;
2475 wgp->wgp_last_sent_mac1_valid = false; 2475 wgp->wgp_last_sent_mac1_valid = false;
2476 wgp->wgp_last_sent_cookie_valid = false; 2476 wgp->wgp_last_sent_cookie_valid = false;
2477 mutex_exit(wgp->wgp_lock); 2477 mutex_exit(wgp->wgp_lock);
2478 2478
2479 if (wgs_prev->wgs_state == WGS_STATE_ESTABLISHED) { 2479 if (wgs_prev->wgs_state == WGS_STATE_ESTABLISHED) {
2480 wgs_prev->wgs_state = WGS_STATE_DESTROYING; 2480 wgs_prev->wgs_state = WGS_STATE_DESTROYING;
2481 /* We can't destroy the old session immediately */ 2481 /* We can't destroy the old session immediately */
2482 wg_schedule_session_dtor_timer(wgp); 2482 wg_schedule_session_dtor_timer(wgp);
2483 } else { 2483 } else {
2484 wg_clear_states(wgs_prev); 2484 wg_clear_states(wgs_prev);
2485 wgs_prev->wgs_state = WGS_STATE_UNKNOWN; 2485 wgs_prev->wgs_state = WGS_STATE_UNKNOWN;
2486 } 2486 }
2487 mutex_exit(wgs_prev->wgs_lock); 2487 mutex_exit(wgs_prev->wgs_lock);
2488 2488
2489 /* Anyway run a softint to flush pending packets */ 2489 /* Anyway run a softint to flush pending packets */
2490 kpreempt_disable(); 2490 kpreempt_disable();
2491 softint_schedule(wgp->wgp_si); 2491 softint_schedule(wgp->wgp_si);
2492 kpreempt_enable(); 2492 kpreempt_enable();
2493 } else { 2493 } else {
2494 if (__predict_false(wg_need_to_send_init_message(wgs))) { 2494 if (__predict_false(wg_need_to_send_init_message(wgs))) {
2495 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 2495 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
2496 } 2496 }
2497 /* 2497 /*
2498 * [W] 6.5 Passive Keepalive 2498 * [W] 6.5 Passive Keepalive
2499 * "If a peer has received a validly-authenticated transport 2499 * "If a peer has received a validly-authenticated transport
2500 * data message (section 5.4.6), but does not have any packets 2500 * data message (section 5.4.6), but does not have any packets
2501 * itself to send back for KEEPALIVE-TIMEOUT seconds, it sends 2501 * itself to send back for KEEPALIVE-TIMEOUT seconds, it sends
2502 * a keepalive message." 2502 * a keepalive message."
2503 */ 2503 */
2504 WG_DLOG("time_uptime=%lu wgs_time_last_data_sent=%lu\n", 2504 WG_DLOG("time_uptime=%lu wgs_time_last_data_sent=%lu\n",
2505 time_uptime, wgs->wgs_time_last_data_sent); 2505 time_uptime, wgs->wgs_time_last_data_sent);
2506 if ((time_uptime - wgs->wgs_time_last_data_sent) >= 2506 if ((time_uptime - wgs->wgs_time_last_data_sent) >=
2507 wg_keepalive_timeout) { 2507 wg_keepalive_timeout) {
2508 WG_TRACE("Schedule sending keepalive message"); 2508 WG_TRACE("Schedule sending keepalive message");
2509 /* 2509 /*
2510 * We can't send a keepalive message here to avoid 2510 * We can't send a keepalive message here to avoid
2511 * a deadlock; we already hold the solock of a socket 2511 * a deadlock; we already hold the solock of a socket
2512 * that is used to send the message. 2512 * that is used to send the message.
2513 */ 2513 */
2514 wg_schedule_peer_task(wgp, 2514 wg_schedule_peer_task(wgp,
2515 WGP_TASK_SEND_KEEPALIVE_MESSAGE); 2515 WGP_TASK_SEND_KEEPALIVE_MESSAGE);
2516 } 2516 }
2517 } 2517 }
2518out: 2518out:
2519 wg_put_session(wgs, &psref); 2519 wg_put_session(wgs, &psref);
2520 if (m != NULL) 2520 if (m != NULL)
2521 m_freem(m); 2521 m_freem(m);
2522 if (free_encrypted_buf) 2522 if (free_encrypted_buf)
2523 kmem_intr_free(encrypted_buf, encrypted_len); 2523 kmem_intr_free(encrypted_buf, encrypted_len);
2524} 2524}
2525 2525
2526static void 2526static void
2527wg_handle_msg_cookie(struct wg_softc *wg, const struct wg_msg_cookie *wgmc) 2527wg_handle_msg_cookie(struct wg_softc *wg, const struct wg_msg_cookie *wgmc)
2528{ 2528{
2529 struct wg_session *wgs; 2529 struct wg_session *wgs;
2530 struct wg_peer *wgp; 2530 struct wg_peer *wgp;
2531 struct psref psref; 2531 struct psref psref;
2532 int error; 2532 int error;
2533 uint8_t key[WG_HASH_LEN]; 2533 uint8_t key[WG_HASH_LEN];
2534 uint8_t cookie[WG_COOKIE_LEN]; 2534 uint8_t cookie[WG_COOKIE_LEN];
2535 2535
2536 WG_TRACE("cookie msg received"); 2536 WG_TRACE("cookie msg received");
2537 wgs = wg_lookup_session_by_index(wg, wgmc->wgmc_receiver, &psref); 2537 wgs = wg_lookup_session_by_index(wg, wgmc->wgmc_receiver, &psref);
2538 if (wgs == NULL) { 2538 if (wgs == NULL) {
2539 WG_TRACE("No session found"); 2539 WG_TRACE("No session found");
2540 return; 2540 return;
2541 } 2541 }
2542 wgp = wgs->wgs_peer; 2542 wgp = wgs->wgs_peer;
2543 2543
2544 if (!wgp->wgp_last_sent_mac1_valid) { 2544 if (!wgp->wgp_last_sent_mac1_valid) {
2545 WG_TRACE("No valid mac1 sent (or expired)"); 2545 WG_TRACE("No valid mac1 sent (or expired)");
2546 goto out; 2546 goto out;
2547 } 2547 }
2548 2548
2549 wg_algo_mac_cookie(key, sizeof(key), wgp->wgp_pubkey, 2549 wg_algo_mac_cookie(key, sizeof(key), wgp->wgp_pubkey,
2550 sizeof(wgp->wgp_pubkey)); 2550 sizeof(wgp->wgp_pubkey));
2551 error = wg_algo_xaead_dec(cookie, sizeof(cookie), key, 0, 2551 error = wg_algo_xaead_dec(cookie, sizeof(cookie), key, 0,
2552 wgmc->wgmc_cookie, sizeof(wgmc->wgmc_cookie), 2552 wgmc->wgmc_cookie, sizeof(wgmc->wgmc_cookie),
2553 wgp->wgp_last_sent_mac1, sizeof(wgp->wgp_last_sent_mac1), 2553 wgp->wgp_last_sent_mac1, sizeof(wgp->wgp_last_sent_mac1),
2554 wgmc->wgmc_salt); 2554 wgmc->wgmc_salt);
2555 if (error != 0) { 2555 if (error != 0) {
2556 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2556 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2557 "wg_algo_aead_dec for cookie failed: error=%d\n", error); 2557 "wg_algo_aead_dec for cookie failed: error=%d\n", error);
2558 goto out; 2558 goto out;
2559 } 2559 }
2560 /* 2560 /*
2561 * [W] 6.6: Interaction with Cookie Reply System 2561 * [W] 6.6: Interaction with Cookie Reply System
2562 * "it should simply store the decrypted cookie value from the cookie 2562 * "it should simply store the decrypted cookie value from the cookie
2563 * reply message, and wait for the expiration of the REKEY-TIMEOUT 2563 * reply message, and wait for the expiration of the REKEY-TIMEOUT
2564 * timer for retrying a handshake initiation message." 2564 * timer for retrying a handshake initiation message."
2565 */ 2565 */
2566 wgp->wgp_latest_cookie_time = time_uptime; 2566 wgp->wgp_latest_cookie_time = time_uptime;
2567 memcpy(wgp->wgp_latest_cookie, cookie, sizeof(wgp->wgp_latest_cookie)); 2567 memcpy(wgp->wgp_latest_cookie, cookie, sizeof(wgp->wgp_latest_cookie));
2568out: 2568out:
2569 wg_put_session(wgs, &psref); 2569 wg_put_session(wgs, &psref);
2570} 2570}
2571 2571
2572static struct mbuf * 2572static struct mbuf *
2573wg_validate_msg_header(struct wg_softc *wg, struct mbuf *m) 2573wg_validate_msg_header(struct wg_softc *wg, struct mbuf *m)
2574{ 2574{
2575 struct wg_msg wgm; 2575 struct wg_msg wgm;
2576 size_t mbuflen; 2576 size_t mbuflen;
2577 size_t msglen; 2577 size_t msglen;
2578 2578
2579 /* 2579 /*
2580 * Get the mbuf chain length. It is already guaranteed, by 2580 * Get the mbuf chain length. It is already guaranteed, by
2581 * wg_overudp_cb, to be large enough for a struct wg_msg. 2581 * wg_overudp_cb, to be large enough for a struct wg_msg.
2582 */ 2582 */
2583 mbuflen = m_length(m); 2583 mbuflen = m_length(m);
2584 KASSERT(mbuflen >= sizeof(struct wg_msg)); 2584 KASSERT(mbuflen >= sizeof(struct wg_msg));
2585 2585
2586 /* 2586 /*
2587 * Copy the message header (32-bit message type) out -- we'll 2587 * Copy the message header (32-bit message type) out -- we'll
2588 * worry about contiguity and alignment later. 2588 * worry about contiguity and alignment later.
2589 */ 2589 */
2590 m_copydata(m, 0, sizeof(wgm), &wgm); 2590 m_copydata(m, 0, sizeof(wgm), &wgm);
2591 switch (wgm.wgm_type) { 2591 switch (wgm.wgm_type) {
2592 case WG_MSG_TYPE_INIT: 2592 case WG_MSG_TYPE_INIT:
2593 msglen = sizeof(struct wg_msg_init); 2593 msglen = sizeof(struct wg_msg_init);
2594 break; 2594 break;
2595 case WG_MSG_TYPE_RESP: 2595 case WG_MSG_TYPE_RESP:
2596 msglen = sizeof(struct wg_msg_resp); 2596 msglen = sizeof(struct wg_msg_resp);
2597 break; 2597 break;
2598 case WG_MSG_TYPE_COOKIE: 2598 case WG_MSG_TYPE_COOKIE:
2599 msglen = sizeof(struct wg_msg_cookie); 2599 msglen = sizeof(struct wg_msg_cookie);
2600 break; 2600 break;
2601 case WG_MSG_TYPE_DATA: 2601 case WG_MSG_TYPE_DATA:
2602 msglen = sizeof(struct wg_msg_data); 2602 msglen = sizeof(struct wg_msg_data);
2603 break; 2603 break;
2604 default: 2604 default:
2605 WG_LOG_RATECHECK(&wg->wg_ppsratecheck, LOG_DEBUG, 2605 WG_LOG_RATECHECK(&wg->wg_ppsratecheck, LOG_DEBUG,
2606 "Unexpected msg type: %u\n", wgm.wgm_type); 2606 "Unexpected msg type: %u\n", wgm.wgm_type);
2607 goto error; 2607 goto error;
2608 } 2608 }
2609 2609
2610 /* Verify the mbuf chain is long enough for this type of message. */ 2610 /* Verify the mbuf chain is long enough for this type of message. */
2611 if (__predict_false(mbuflen < msglen)) { 2611 if (__predict_false(mbuflen < msglen)) {
2612 WG_DLOG("Invalid msg size: mbuflen=%lu type=%u\n", mbuflen, 2612 WG_DLOG("Invalid msg size: mbuflen=%lu type=%u\n", mbuflen,
2613 wgm.wgm_type); 2613 wgm.wgm_type);
2614 goto error; 2614 goto error;
2615 } 2615 }
2616 2616
2617 /* Make the message header contiguous if necessary. */ 2617 /* Make the message header contiguous if necessary. */
2618 if (__predict_false(m->m_len < msglen)) { 2618 if (__predict_false(m->m_len < msglen)) {
2619 m = m_pullup(m, msglen); 2619 m = m_pullup(m, msglen);
2620 if (m == NULL) 2620 if (m == NULL)
2621 return NULL; 2621 return NULL;
2622 } 2622 }
2623 2623
2624 return m; 2624 return m;
2625 2625
2626error: 2626error:
2627 m_freem(m); 2627 m_freem(m);
2628 return NULL; 2628 return NULL;
2629} 2629}
2630 2630
2631static void 2631static void
2632wg_handle_packet(struct wg_softc *wg, struct mbuf *m, 2632wg_handle_packet(struct wg_softc *wg, struct mbuf *m,
2633 const struct sockaddr *src) 2633 const struct sockaddr *src)
2634{ 2634{
2635 struct wg_msg *wgm; 2635 struct wg_msg *wgm;
2636 2636
2637 m = wg_validate_msg_header(wg, m); 2637 m = wg_validate_msg_header(wg, m);
2638 if (__predict_false(m == NULL)) 2638 if (__predict_false(m == NULL))
2639 return; 2639 return;
2640 2640
2641 KASSERT(m->m_len >= sizeof(struct wg_msg)); 2641 KASSERT(m->m_len >= sizeof(struct wg_msg));
2642 wgm = mtod(m, struct wg_msg *); 2642 wgm = mtod(m, struct wg_msg *);
2643 switch (wgm->wgm_type) { 2643 switch (wgm->wgm_type) {
2644 case WG_MSG_TYPE_INIT: 2644 case WG_MSG_TYPE_INIT:
2645 wg_handle_msg_init(wg, (struct wg_msg_init *)wgm, src); 2645 wg_handle_msg_init(wg, (struct wg_msg_init *)wgm, src);
2646 break; 2646 break;
2647 case WG_MSG_TYPE_RESP: 2647 case WG_MSG_TYPE_RESP:
2648 wg_handle_msg_resp(wg, (struct wg_msg_resp *)wgm, src); 2648 wg_handle_msg_resp(wg, (struct wg_msg_resp *)wgm, src);
2649 break; 2649 break;
2650 case WG_MSG_TYPE_COOKIE: 2650 case WG_MSG_TYPE_COOKIE:
2651 wg_handle_msg_cookie(wg, (struct wg_msg_cookie *)wgm); 2651 wg_handle_msg_cookie(wg, (struct wg_msg_cookie *)wgm);
2652 break; 2652 break;
2653 case WG_MSG_TYPE_DATA: 2653 case WG_MSG_TYPE_DATA:
2654 wg_handle_msg_data(wg, m, src); 2654 wg_handle_msg_data(wg, m, src);
2655 break; 2655 break;
2656 default: 2656 default:
2657 /* wg_validate_msg_header should already reject this case */ 2657 /* wg_validate_msg_header should already reject this case */
2658 break; 2658 break;
2659 } 2659 }
2660} 2660}
2661 2661
2662static void 2662static void
2663wg_receive_packets(struct wg_softc *wg, const int af) 2663wg_receive_packets(struct wg_softc *wg, const int af)
2664{ 2664{
2665 2665
2666 for (;;) { 2666 for (;;) {
2667 int error, flags; 2667 int error, flags;
2668 struct socket *so; 2668 struct socket *so;
2669 struct mbuf *m = NULL; 2669 struct mbuf *m = NULL;
2670 struct uio dummy_uio; 2670 struct uio dummy_uio;
2671 struct mbuf *paddr = NULL; 2671 struct mbuf *paddr = NULL;
2672 struct sockaddr *src; 2672 struct sockaddr *src;
2673 2673
2674 so = wg_get_so_by_af(wg->wg_worker, af); 2674 so = wg_get_so_by_af(wg->wg_worker, af);
2675 flags = MSG_DONTWAIT; 2675 flags = MSG_DONTWAIT;
2676 dummy_uio.uio_resid = 1000000000; 2676 dummy_uio.uio_resid = 1000000000;
2677 2677
2678 error = so->so_receive(so, &paddr, &dummy_uio, &m, NULL, 2678 error = so->so_receive(so, &paddr, &dummy_uio, &m, NULL,
2679 &flags); 2679 &flags);
2680 if (error || m == NULL) { 2680 if (error || m == NULL) {
2681 //if (error == EWOULDBLOCK) 2681 //if (error == EWOULDBLOCK)
2682 return; 2682 return;
2683 } 2683 }
2684 2684
2685 KASSERT(paddr != NULL); 2685 KASSERT(paddr != NULL);
2686 KASSERT(paddr->m_len >= sizeof(struct sockaddr)); 2686 KASSERT(paddr->m_len >= sizeof(struct sockaddr));
2687 src = mtod(paddr, struct sockaddr *); 2687 src = mtod(paddr, struct sockaddr *);
2688 2688
2689 wg_handle_packet(wg, m, src); 2689 wg_handle_packet(wg, m, src);
2690 } 2690 }
2691} 2691}
2692 2692
2693static void 2693static void
2694wg_get_peer(struct wg_peer *wgp, struct psref *psref) 2694wg_get_peer(struct wg_peer *wgp, struct psref *psref)
2695{ 2695{
2696 2696
2697 psref_acquire(psref, &wgp->wgp_psref, wg_psref_class); 2697 psref_acquire(psref, &wgp->wgp_psref, wg_psref_class);
2698} 2698}
2699 2699
2700static void 2700static void
2701wg_put_peer(struct wg_peer *wgp, struct psref *psref) 2701wg_put_peer(struct wg_peer *wgp, struct psref *psref)
2702{ 2702{
2703 2703
2704 psref_release(psref, &wgp->wgp_psref, wg_psref_class); 2704 psref_release(psref, &wgp->wgp_psref, wg_psref_class);
2705} 2705}
2706 2706
2707static void 2707static void
2708wg_task_send_init_message(struct wg_softc *wg, struct wg_peer *wgp) 2708wg_task_send_init_message(struct wg_softc *wg, struct wg_peer *wgp)
2709{ 2709{
2710 struct psref psref; 2710 struct psref psref;
2711 struct wg_session *wgs; 2711 struct wg_session *wgs;
2712 2712
2713 WG_TRACE("WGP_TASK_SEND_INIT_MESSAGE"); 2713 WG_TRACE("WGP_TASK_SEND_INIT_MESSAGE");
2714 2714
2715 if (!wgp->wgp_endpoint_available) { 2715 if (!wgp->wgp_endpoint_available) {
2716 WGLOG(LOG_DEBUG, "No endpoint available\n"); 2716 WGLOG(LOG_DEBUG, "No endpoint available\n");
2717 /* XXX should do something? */ 2717 /* XXX should do something? */
2718 return; 2718 return;
2719 } 2719 }
2720 2720
2721 wgs = wg_get_stable_session(wgp, &psref); 2721 wgs = wg_get_stable_session(wgp, &psref);
2722 if (wgs->wgs_state == WGS_STATE_UNKNOWN) { 2722 if (wgs->wgs_state == WGS_STATE_UNKNOWN) {
2723 wg_put_session(wgs, &psref); 2723 wg_put_session(wgs, &psref);
2724 wg_send_handshake_msg_init(wg, wgp); 2724 wg_send_handshake_msg_init(wg, wgp);
2725 } else { 2725 } else {
2726 wg_put_session(wgs, &psref); 2726 wg_put_session(wgs, &psref);
2727 /* rekey */ 2727 /* rekey */
2728 wgs = wg_get_unstable_session(wgp, &psref); 2728 wgs = wg_get_unstable_session(wgp, &psref);
2729 if (wgs->wgs_state != WGS_STATE_INIT_ACTIVE) 2729 if (wgs->wgs_state != WGS_STATE_INIT_ACTIVE)
2730 wg_send_handshake_msg_init(wg, wgp); 2730 wg_send_handshake_msg_init(wg, wgp);
2731 wg_put_session(wgs, &psref); 2731 wg_put_session(wgs, &psref);
2732 } 2732 }
2733} 2733}
2734 2734
2735static void 2735static void
2736wg_task_endpoint_changed(struct wg_softc *wg, struct wg_peer *wgp) 2736wg_task_endpoint_changed(struct wg_softc *wg, struct wg_peer *wgp)
2737{ 2737{
2738 2738
2739 WG_TRACE("WGP_TASK_ENDPOINT_CHANGED"); 2739 WG_TRACE("WGP_TASK_ENDPOINT_CHANGED");
2740 2740
2741 mutex_enter(wgp->wgp_lock); 2741 mutex_enter(wgp->wgp_lock);
2742 if (wgp->wgp_endpoint_changing) { 2742 if (wgp->wgp_endpoint_changing) {
2743 pserialize_perform(wgp->wgp_psz); 2743 pserialize_perform(wgp->wgp_psz);
2744 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref, 2744 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref,
2745 wg_psref_class); 2745 wg_psref_class);
2746 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref, 2746 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref,
2747 wg_psref_class); 2747 wg_psref_class);
2748 wgp->wgp_endpoint_changing = false; 2748 wgp->wgp_endpoint_changing = false;
2749 } 2749 }
2750 mutex_exit(wgp->wgp_lock); 2750 mutex_exit(wgp->wgp_lock);
2751} 2751}
2752 2752
2753static void 2753static void
2754wg_task_send_keepalive_message(struct wg_softc *wg, struct wg_peer *wgp) 2754wg_task_send_keepalive_message(struct wg_softc *wg, struct wg_peer *wgp)
2755{ 2755{
2756 struct psref psref; 2756 struct psref psref;
2757 struct wg_session *wgs; 2757 struct wg_session *wgs;
2758 2758
2759 WG_TRACE("WGP_TASK_SEND_KEEPALIVE_MESSAGE"); 2759 WG_TRACE("WGP_TASK_SEND_KEEPALIVE_MESSAGE");
2760 2760
2761 wgs = wg_get_stable_session(wgp, &psref); 2761 wgs = wg_get_stable_session(wgp, &psref);
2762 wg_send_keepalive_msg(wgp, wgs); 2762 wg_send_keepalive_msg(wgp, wgs);
2763 wg_put_session(wgs, &psref); 2763 wg_put_session(wgs, &psref);
2764} 2764}
2765 2765
2766static void 2766static void
2767wg_task_destroy_prev_session(struct wg_softc *wg, struct wg_peer *wgp) 2767wg_task_destroy_prev_session(struct wg_softc *wg, struct wg_peer *wgp)
2768{ 2768{
2769 struct wg_session *wgs; 2769 struct wg_session *wgs;
2770 2770
2771 WG_TRACE("WGP_TASK_DESTROY_PREV_SESSION"); 2771 WG_TRACE("WGP_TASK_DESTROY_PREV_SESSION");
2772 2772
2773 mutex_enter(wgp->wgp_lock); 2773 mutex_enter(wgp->wgp_lock);
2774 wgs = wgp->wgp_session_unstable; 2774 wgs = wgp->wgp_session_unstable;
2775 mutex_enter(wgs->wgs_lock); 2775 mutex_enter(wgs->wgs_lock);
2776 if (wgs->wgs_state == WGS_STATE_DESTROYING) { 2776 if (wgs->wgs_state == WGS_STATE_DESTROYING) {
2777 pserialize_perform(wgp->wgp_psz); 2777 pserialize_perform(wgp->wgp_psz);
2778 psref_target_destroy(&wgs->wgs_psref, wg_psref_class); 2778 psref_target_destroy(&wgs->wgs_psref, wg_psref_class);
2779 psref_target_init(&wgs->wgs_psref, wg_psref_class); 2779 psref_target_init(&wgs->wgs_psref, wg_psref_class);
2780 wg_clear_states(wgs); 2780 wg_clear_states(wgs);
2781 wgs->wgs_state = WGS_STATE_UNKNOWN; 2781 wgs->wgs_state = WGS_STATE_UNKNOWN;
2782 } 2782 }
2783 mutex_exit(wgs->wgs_lock); 2783 mutex_exit(wgs->wgs_lock);
2784 mutex_exit(wgp->wgp_lock); 2784 mutex_exit(wgp->wgp_lock);
2785} 2785}
2786 2786
2787static void 2787static void
2788wg_process_peer_tasks(struct wg_softc *wg) 2788wg_process_peer_tasks(struct wg_softc *wg)
2789{ 2789{
2790 struct wg_peer *wgp; 2790 struct wg_peer *wgp;
2791 int s; 2791 int s;
2792 2792
2793 /* XXX should avoid checking all peers */ 2793 /* XXX should avoid checking all peers */
2794 s = pserialize_read_enter(); 2794 s = pserialize_read_enter();
2795 WG_PEER_READER_FOREACH(wgp, wg) { 2795 WG_PEER_READER_FOREACH(wgp, wg) {
2796 struct psref psref; 2796 struct psref psref;
2797 unsigned int tasks; 2797 unsigned int tasks;
2798 2798
2799 if (wgp->wgp_tasks == 0) 2799 if (wgp->wgp_tasks == 0)
2800 continue; 2800 continue;
2801 2801
2802 wg_get_peer(wgp, &psref); 2802 wg_get_peer(wgp, &psref);
2803 pserialize_read_exit(s); 2803 pserialize_read_exit(s);
2804 2804
2805 restart: 2805 restart:
2806 tasks = atomic_swap_uint(&wgp->wgp_tasks, 0); 2806 tasks = atomic_swap_uint(&wgp->wgp_tasks, 0);
2807 KASSERT(tasks != 0); 2807 KASSERT(tasks != 0);
2808 2808
2809 WG_DLOG("tasks=%x\n", tasks); 2809 WG_DLOG("tasks=%x\n", tasks);
2810 2810
2811 if (ISSET(tasks, WGP_TASK_SEND_INIT_MESSAGE)) 2811 if (ISSET(tasks, WGP_TASK_SEND_INIT_MESSAGE))
2812 wg_task_send_init_message(wg, wgp); 2812 wg_task_send_init_message(wg, wgp);
2813 if (ISSET(tasks, WGP_TASK_ENDPOINT_CHANGED)) 2813 if (ISSET(tasks, WGP_TASK_ENDPOINT_CHANGED))
2814 wg_task_endpoint_changed(wg, wgp); 2814 wg_task_endpoint_changed(wg, wgp);
2815 if (ISSET(tasks, WGP_TASK_SEND_KEEPALIVE_MESSAGE)) 2815 if (ISSET(tasks, WGP_TASK_SEND_KEEPALIVE_MESSAGE))
2816 wg_task_send_keepalive_message(wg, wgp); 2816 wg_task_send_keepalive_message(wg, wgp);
2817 if (ISSET(tasks, WGP_TASK_DESTROY_PREV_SESSION)) 2817 if (ISSET(tasks, WGP_TASK_DESTROY_PREV_SESSION))
2818 wg_task_destroy_prev_session(wg, wgp); 2818 wg_task_destroy_prev_session(wg, wgp);
2819 2819
2820 /* New tasks may be scheduled during processing tasks */ 2820 /* New tasks may be scheduled during processing tasks */
2821 WG_DLOG("wgp_tasks=%d\n", wgp->wgp_tasks); 2821 WG_DLOG("wgp_tasks=%d\n", wgp->wgp_tasks);
2822 if (wgp->wgp_tasks != 0) 2822 if (wgp->wgp_tasks != 0)
2823 goto restart; 2823 goto restart;
2824 2824
2825 s = pserialize_read_enter(); 2825 s = pserialize_read_enter();
2826 wg_put_peer(wgp, &psref); 2826 wg_put_peer(wgp, &psref);
2827 } 2827 }
2828 pserialize_read_exit(s); 2828 pserialize_read_exit(s);
2829} 2829}
2830 2830
2831static void 2831static void
2832wg_worker(void *arg) 2832wg_worker(void *arg)
2833{ 2833{
2834 struct wg_softc *wg = arg; 2834 struct wg_softc *wg = arg;
2835 struct wg_worker *wgw = wg->wg_worker; 2835 struct wg_worker *wgw = wg->wg_worker;
2836 bool todie = false; 2836 bool todie = false;
2837 2837
2838 KASSERT(wg != NULL); 2838 KASSERT(wg != NULL);
2839 KASSERT(wgw != NULL); 2839 KASSERT(wgw != NULL);
2840 2840
2841 while (!todie) { 2841 while (!todie) {
2842 int reasons; 2842 int reasons;
2843 int bound; 2843 int bound;
2844 2844
2845 mutex_enter(&wgw->wgw_lock); 2845 mutex_enter(&wgw->wgw_lock);
2846 /* New tasks may come during task handling */ 2846 /* New tasks may come during task handling */
2847 while ((reasons = wgw->wgw_wakeup_reasons) == 0 && 2847 while ((reasons = wgw->wgw_wakeup_reasons) == 0 &&
2848 !(todie = wgw->wgw_todie)) 2848 !(todie = wgw->wgw_todie))
2849 cv_wait(&wgw->wgw_cv, &wgw->wgw_lock); 2849 cv_wait(&wgw->wgw_cv, &wgw->wgw_lock);
2850 wgw->wgw_wakeup_reasons = 0; 2850 wgw->wgw_wakeup_reasons = 0;
2851 mutex_exit(&wgw->wgw_lock); 2851 mutex_exit(&wgw->wgw_lock);
2852 2852
2853 bound = curlwp_bind(); 2853 bound = curlwp_bind();
2854 if (ISSET(reasons, WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4)) 2854 if (ISSET(reasons, WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4))
2855 wg_receive_packets(wg, AF_INET); 2855 wg_receive_packets(wg, AF_INET);
2856 if (ISSET(reasons, WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6)) 2856 if (ISSET(reasons, WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6))
2857 wg_receive_packets(wg, AF_INET6); 2857 wg_receive_packets(wg, AF_INET6);
2858 if (ISSET(reasons, WG_WAKEUP_REASON_PEER)) 2858 if (ISSET(reasons, WG_WAKEUP_REASON_PEER))
2859 wg_process_peer_tasks(wg); 2859 wg_process_peer_tasks(wg);
2860 curlwp_bindx(bound); 2860 curlwp_bindx(bound);
2861 } 2861 }
2862 kthread_exit(0); 2862 kthread_exit(0);
2863} 2863}
2864 2864
2865static void 2865static void
2866wg_wakeup_worker(struct wg_worker *wgw, const int reason) 2866wg_wakeup_worker(struct wg_worker *wgw, const int reason)
2867{ 2867{
2868 2868
2869 mutex_enter(&wgw->wgw_lock); 2869 mutex_enter(&wgw->wgw_lock);
2870 wgw->wgw_wakeup_reasons |= reason; 2870 wgw->wgw_wakeup_reasons |= reason;
2871 cv_broadcast(&wgw->wgw_cv); 2871 cv_broadcast(&wgw->wgw_cv);
2872 mutex_exit(&wgw->wgw_lock); 2872 mutex_exit(&wgw->wgw_lock);
2873} 2873}
2874 2874
2875static int 2875static int
2876wg_bind_port(struct wg_softc *wg, const uint16_t port) 2876wg_bind_port(struct wg_softc *wg, const uint16_t port)
2877{ 2877{
2878 int error; 2878 int error;
2879 struct wg_worker *wgw = wg->wg_worker; 2879 struct wg_worker *wgw = wg->wg_worker;
2880 uint16_t old_port = wg->wg_listen_port; 2880 uint16_t old_port = wg->wg_listen_port;
2881 2881
2882 if (port != 0 && old_port == port) 2882 if (port != 0 && old_port == port)
2883 return 0; 2883 return 0;
2884 2884
2885 struct sockaddr_in _sin, *sin = &_sin; 2885 struct sockaddr_in _sin, *sin = &_sin;
2886 sin->sin_len = sizeof(*sin); 2886 sin->sin_len = sizeof(*sin);
2887 sin->sin_family = AF_INET; 2887 sin->sin_family = AF_INET;
2888 sin->sin_addr.s_addr = INADDR_ANY; 2888 sin->sin_addr.s_addr = INADDR_ANY;
2889 sin->sin_port = htons(port); 2889 sin->sin_port = htons(port);
2890 2890
2891 error = sobind(wgw->wgw_so4, sintosa(sin), curlwp); 2891 error = sobind(wgw->wgw_so4, sintosa(sin), curlwp);
2892 if (error != 0) 2892 if (error != 0)
2893 return error; 2893 return error;
2894 2894
2895#ifdef INET6 2895#ifdef INET6
2896 struct sockaddr_in6 _sin6, *sin6 = &_sin6; 2896 struct sockaddr_in6 _sin6, *sin6 = &_sin6;
2897 sin6->sin6_len = sizeof(*sin6); 2897 sin6->sin6_len = sizeof(*sin6);
2898 sin6->sin6_family = AF_INET6; 2898 sin6->sin6_family = AF_INET6;
2899 sin6->sin6_addr = in6addr_any; 2899 sin6->sin6_addr = in6addr_any;
2900 sin6->sin6_port = htons(port); 2900 sin6->sin6_port = htons(port);
2901 2901
2902 error = sobind(wgw->wgw_so6, sin6tosa(sin6), curlwp); 2902 error = sobind(wgw->wgw_so6, sin6tosa(sin6), curlwp);
2903 if (error != 0) 2903 if (error != 0)
2904 return error; 2904 return error;
2905#endif 2905#endif
2906 2906
2907 wg->wg_listen_port = port; 2907 wg->wg_listen_port = port;
2908 2908
2909 return 0; 2909 return 0;
2910} 2910}
2911 2911
2912static void 2912static void
2913wg_so_upcall(struct socket *so, void *arg, int events, int waitflag) 2913wg_so_upcall(struct socket *so, void *arg, int events, int waitflag)
2914{ 2914{
2915 struct wg_worker *wgw = arg; 2915 struct wg_worker *wgw = arg;
2916 int reason; 2916 int reason;
2917 2917
2918 reason = (so->so_proto->pr_domain->dom_family == AF_INET) ? 2918 reason = (so->so_proto->pr_domain->dom_family == AF_INET) ?
2919 WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 : 2919 WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 :
2920 WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6; 2920 WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6;
2921 wg_wakeup_worker(wgw, reason); 2921 wg_wakeup_worker(wgw, reason);
2922} 2922}
2923 2923
2924static int 2924static int
2925wg_overudp_cb(struct mbuf **mp, int offset, struct socket *so, 2925wg_overudp_cb(struct mbuf **mp, int offset, struct socket *so,
2926 struct sockaddr *src, void *arg) 2926 struct sockaddr *src, void *arg)
2927{ 2927{
2928 struct wg_softc *wg = arg; 2928 struct wg_softc *wg = arg;
2929 struct wg_msg wgm; 2929 struct wg_msg wgm;
2930 struct mbuf *m = *mp; 2930 struct mbuf *m = *mp;
2931 2931
2932 WG_TRACE("enter"); 2932 WG_TRACE("enter");
2933 2933
2934 /* Verify the mbuf chain is long enough to have a wg msg header. */ 2934 /* Verify the mbuf chain is long enough to have a wg msg header. */
2935 KASSERT(offset <= m_length(m)); 2935 KASSERT(offset <= m_length(m));
2936 if (__predict_false(m_length(m) - offset < sizeof(struct wg_msg))) { 2936 if (__predict_false(m_length(m) - offset < sizeof(struct wg_msg))) {
2937 /* drop on the floor */ 2937 /* drop on the floor */
2938 m_freem(m); 2938 m_freem(m);
2939 return -1; 2939 return -1;
2940 } 2940 }
2941 2941
2942 /* 2942 /*
2943 * Copy the message header (32-bit message type) out -- we'll 2943 * Copy the message header (32-bit message type) out -- we'll
2944 * worry about contiguity and alignment later. 2944 * worry about contiguity and alignment later.
2945 */ 2945 */
2946 m_copydata(m, offset, sizeof(struct wg_msg), &wgm); 2946 m_copydata(m, offset, sizeof(struct wg_msg), &wgm);
2947 WG_DLOG("type=%d\n", wgm.wgm_type); 2947 WG_DLOG("type=%d\n", wgm.wgm_type);
2948 2948
2949 /* 2949 /*
2950 * Handle DATA packets promptly as they arrive. Other packets 2950 * Handle DATA packets promptly as they arrive. Other packets
2951 * may require expensive public-key crypto and are not as 2951 * may require expensive public-key crypto and are not as
2952 * sensitive to latency, so defer them to the worker thread. 2952 * sensitive to latency, so defer them to the worker thread.
2953 */ 2953 */
2954 switch (wgm.wgm_type) { 2954 switch (wgm.wgm_type) {
2955 case WG_MSG_TYPE_DATA: 2955 case WG_MSG_TYPE_DATA:
2956 /* handle immediately */ 2956 /* handle immediately */
2957 m_adj(m, offset); 2957 m_adj(m, offset);
2958 if (__predict_false(m->m_len < sizeof(struct wg_msg_data))) { 2958 if (__predict_false(m->m_len < sizeof(struct wg_msg_data))) {
2959 m = m_pullup(m, sizeof(struct wg_msg_data)); 2959 m = m_pullup(m, sizeof(struct wg_msg_data));
2960 if (m == NULL) 2960 if (m == NULL)
2961 return -1; 2961 return -1;
2962 } 2962 }
2963 wg_handle_msg_data(wg, m, src); 2963 wg_handle_msg_data(wg, m, src);
2964 *mp = NULL; 2964 *mp = NULL;
2965 return 1; 2965 return 1;
2966 case WG_MSG_TYPE_INIT: 2966 case WG_MSG_TYPE_INIT:
2967 case WG_MSG_TYPE_RESP: 2967 case WG_MSG_TYPE_RESP:
2968 case WG_MSG_TYPE_COOKIE: 2968 case WG_MSG_TYPE_COOKIE:
2969 /* pass through to so_receive in wg_receive_packets */ 2969 /* pass through to so_receive in wg_receive_packets */
2970 return 0; 2970 return 0;
2971 default: 2971 default:
2972 /* drop on the floor */ 2972 /* drop on the floor */
2973 m_freem(m); 2973 m_freem(m);
2974 return -1; 2974 return -1;
2975 } 2975 }
2976} 2976}
2977 2977
2978static int 2978static int
2979wg_worker_socreate(struct wg_softc *wg, struct wg_worker *wgw, const int af, 2979wg_worker_socreate(struct wg_softc *wg, struct wg_worker *wgw, const int af,
2980 struct socket **sop) 2980 struct socket **sop)
2981{ 2981{
2982 int error; 2982 int error;
2983 struct socket *so; 2983 struct socket *so;
2984 2984
2985 error = socreate(af, &so, SOCK_DGRAM, 0, curlwp, NULL); 2985 error = socreate(af, &so, SOCK_DGRAM, 0, curlwp, NULL);
2986 if (error != 0) 2986 if (error != 0)
2987 return error; 2987 return error;
2988 2988
2989 solock(so); 2989 solock(so);
2990 so->so_upcallarg = wgw; 2990 so->so_upcallarg = wgw;
2991 so->so_upcall = wg_so_upcall; 2991 so->so_upcall = wg_so_upcall;
2992 so->so_rcv.sb_flags |= SB_UPCALL; 2992 so->so_rcv.sb_flags |= SB_UPCALL;
2993 if (af == AF_INET) 2993 if (af == AF_INET)
2994 in_pcb_register_overudp_cb(sotoinpcb(so), wg_overudp_cb, wg); 2994 in_pcb_register_overudp_cb(sotoinpcb(so), wg_overudp_cb, wg);
2995#if INET6 2995#if INET6
2996 else 2996 else
2997 in6_pcb_register_overudp_cb(sotoin6pcb(so), wg_overudp_cb, wg); 2997 in6_pcb_register_overudp_cb(sotoin6pcb(so), wg_overudp_cb, wg);
2998#endif 2998#endif
2999 sounlock(so); 2999 sounlock(so);
3000 3000
3001 *sop = so; 3001 *sop = so;
3002 3002
3003 return 0; 3003 return 0;
3004} 3004}
3005 3005
3006static int 3006static int
3007wg_worker_init(struct wg_softc *wg) 3007wg_worker_init(struct wg_softc *wg)
3008{ 3008{
3009 int error; 3009 int error;
3010 struct wg_worker *wgw; 3010 struct wg_worker *wgw;
3011 const char *ifname = wg->wg_if.if_xname; 3011 const char *ifname = wg->wg_if.if_xname;
3012 struct socket *so; 3012 struct socket *so;
3013 3013
3014 wgw = kmem_zalloc(sizeof(struct wg_worker), KM_SLEEP); 3014 wgw = kmem_zalloc(sizeof(struct wg_worker), KM_SLEEP);
3015 3015
3016 mutex_init(&wgw->wgw_lock, MUTEX_DEFAULT, IPL_NONE); 3016 mutex_init(&wgw->wgw_lock, MUTEX_DEFAULT, IPL_NONE);
3017 cv_init(&wgw->wgw_cv, ifname); 3017 cv_init(&wgw->wgw_cv, ifname);
3018 wgw->wgw_todie = false; 3018 wgw->wgw_todie = false;
3019 wgw->wgw_wakeup_reasons = 0; 3019 wgw->wgw_wakeup_reasons = 0;
3020 3020
3021 error = wg_worker_socreate(wg, wgw, AF_INET, &so); 3021 error = wg_worker_socreate(wg, wgw, AF_INET, &so);
3022 if (error != 0) 3022 if (error != 0)
3023 goto error; 3023 goto error;
3024 wgw->wgw_so4 = so; 3024 wgw->wgw_so4 = so;
3025#ifdef INET6 3025#ifdef INET6
3026 error = wg_worker_socreate(wg, wgw, AF_INET6, &so); 3026 error = wg_worker_socreate(wg, wgw, AF_INET6, &so);
3027 if (error != 0) 3027 if (error != 0)
3028 goto error; 3028 goto error;
3029 wgw->wgw_so6 = so; 3029 wgw->wgw_so6 = so;
3030#endif 3030#endif
3031 3031
3032 wg->wg_worker = wgw; 3032 wg->wg_worker = wgw;
3033 3033
3034 error = kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, 3034 error = kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN,
3035 NULL, wg_worker, wg, &wg->wg_worker_lwp, "%s", ifname); 3035 NULL, wg_worker, wg, &wg->wg_worker_lwp, "%s", ifname);
3036 if (error != 0) 3036 if (error != 0)
3037 goto error; 3037 goto error;
3038 3038
3039 return 0; 3039 return 0;
3040 3040
3041error: 3041error:
3042#ifdef INET6 3042#ifdef INET6
3043 if (wgw->wgw_so6 != NULL) 3043 if (wgw->wgw_so6 != NULL)
3044 soclose(wgw->wgw_so6); 3044 soclose(wgw->wgw_so6);
3045#endif 3045#endif
3046 if (wgw->wgw_so4 != NULL) 3046 if (wgw->wgw_so4 != NULL)
3047 soclose(wgw->wgw_so4); 3047 soclose(wgw->wgw_so4);
3048 cv_destroy(&wgw->wgw_cv); 3048 cv_destroy(&wgw->wgw_cv);
3049 mutex_destroy(&wgw->wgw_lock); 3049 mutex_destroy(&wgw->wgw_lock);
3050 3050
3051 return error; 3051 return error;
3052} 3052}
3053 3053
3054static void 3054static void
3055wg_worker_destroy(struct wg_softc *wg) 3055wg_worker_destroy(struct wg_softc *wg)
3056{ 3056{
3057 struct wg_worker *wgw = wg->wg_worker; 3057 struct wg_worker *wgw = wg->wg_worker;
3058 3058
3059 mutex_enter(&wgw->wgw_lock); 3059 mutex_enter(&wgw->wgw_lock);
3060 wgw->wgw_todie = true; 3060 wgw->wgw_todie = true;
3061 wgw->wgw_wakeup_reasons = 0; 3061 wgw->wgw_wakeup_reasons = 0;
3062 cv_broadcast(&wgw->wgw_cv); 3062 cv_broadcast(&wgw->wgw_cv);
3063 mutex_exit(&wgw->wgw_lock); 3063 mutex_exit(&wgw->wgw_lock);
3064 3064
3065 kthread_join(wg->wg_worker_lwp); 3065 kthread_join(wg->wg_worker_lwp);
3066 3066
3067#ifdef INET6 3067#ifdef INET6
3068 soclose(wgw->wgw_so6); 3068 soclose(wgw->wgw_so6);
3069#endif 3069#endif
3070 soclose(wgw->wgw_so4); 3070 soclose(wgw->wgw_so4);
3071 cv_destroy(&wgw->wgw_cv); 3071 cv_destroy(&wgw->wgw_cv);
3072 mutex_destroy(&wgw->wgw_lock); 3072 mutex_destroy(&wgw->wgw_lock);
3073 kmem_free(wg->wg_worker, sizeof(struct wg_worker)); 3073 kmem_free(wg->wg_worker, sizeof(struct wg_worker));
3074 wg->wg_worker = NULL; 3074 wg->wg_worker = NULL;
3075} 3075}
3076 3076
3077static bool 3077static bool
3078wg_session_hit_limits(struct wg_session *wgs) 3078wg_session_hit_limits(struct wg_session *wgs)
3079{ 3079{
3080 3080
3081 /* 3081 /*
3082 * [W] 6.2: Transport Message Limits 3082 * [W] 6.2: Transport Message Limits
3083 * "After REJECT-AFTER-MESSAGES transport data messages or after the 3083 * "After REJECT-AFTER-MESSAGES transport data messages or after the
3084 * current secure session is REJECT-AFTER-TIME seconds old, whichever 3084 * current secure session is REJECT-AFTER-TIME seconds old, whichever
3085 * comes first, WireGuard will refuse to send any more transport data 3085 * comes first, WireGuard will refuse to send any more transport data
3086 * messages using the current secure session, ..." 3086 * messages using the current secure session, ..."
3087 */ 3087 */
3088 KASSERT(wgs->wgs_time_established != 0); 3088 KASSERT(wgs->wgs_time_established != 0);
3089 if ((time_uptime - wgs->wgs_time_established) > wg_reject_after_time) { 3089 if ((time_uptime - wgs->wgs_time_established) > wg_reject_after_time) {
3090 WG_DLOG("The session hits REJECT_AFTER_TIME\n"); 3090 WG_DLOG("The session hits REJECT_AFTER_TIME\n");
3091 return true; 3091 return true;
3092 } else if (wg_session_get_send_counter(wgs) > 3092 } else if (wg_session_get_send_counter(wgs) >
3093 wg_reject_after_messages) { 3093 wg_reject_after_messages) {
3094 WG_DLOG("The session hits REJECT_AFTER_MESSAGES\n"); 3094 WG_DLOG("The session hits REJECT_AFTER_MESSAGES\n");
3095 return true; 3095 return true;
3096 } 3096 }
3097 3097
3098 return false; 3098 return false;
3099} 3099}
3100 3100
3101static void 3101static void
3102wg_peer_softint(void *arg) 3102wg_peer_softint(void *arg)
3103{ 3103{
3104 struct wg_peer *wgp = arg; 3104 struct wg_peer *wgp = arg;
3105 struct wg_session *wgs; 3105 struct wg_session *wgs;
3106 struct mbuf *m; 3106 struct mbuf *m;
3107 struct psref psref; 3107 struct psref psref;
3108 3108
3109 wgs = wg_get_stable_session(wgp, &psref); 3109 wgs = wg_get_stable_session(wgp, &psref);
3110 if (wgs->wgs_state != WGS_STATE_ESTABLISHED) { 3110 if (wgs->wgs_state != WGS_STATE_ESTABLISHED) {
3111 /* XXX how to treat? */ 3111 /* XXX how to treat? */
3112 WG_TRACE("skipped"); 3112 WG_TRACE("skipped");
3113 goto out; 3113 goto out;
3114 } 3114 }
3115 if (wg_session_hit_limits(wgs)) { 3115 if (wg_session_hit_limits(wgs)) {
3116 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3116 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3117 goto out; 3117 goto out;
3118 } 3118 }
3119 WG_TRACE("running"); 3119 WG_TRACE("running");
3120 3120
3121 while ((m = pcq_get(wgp->wgp_q)) != NULL) { 3121 while ((m = pcq_get(wgp->wgp_q)) != NULL) {
3122 wg_send_data_msg(wgp, wgs, m); 3122 wg_send_data_msg(wgp, wgs, m);
3123 } 3123 }
3124out: 3124out:
3125 wg_put_session(wgs, &psref); 3125 wg_put_session(wgs, &psref);
3126} 3126}
3127 3127
3128static void 3128static void
3129wg_rekey_timer(void *arg) 3129wg_rekey_timer(void *arg)
3130{ 3130{
3131 struct wg_peer *wgp = arg; 3131 struct wg_peer *wgp = arg;
3132 3132
3133 mutex_enter(wgp->wgp_lock); 3133 mutex_enter(wgp->wgp_lock);
3134 if (__predict_true(wgp->wgp_state != WGP_STATE_DESTROYING)) { 3134 if (__predict_true(wgp->wgp_state != WGP_STATE_DESTROYING)) {
3135 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3135 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3136 } 3136 }
3137 mutex_exit(wgp->wgp_lock); 3137 mutex_exit(wgp->wgp_lock);
3138} 3138}
3139 3139
3140static void 3140static void
3141wg_purge_pending_packets(struct wg_peer *wgp) 3141wg_purge_pending_packets(struct wg_peer *wgp)
3142{ 3142{
3143 struct mbuf *m; 3143 struct mbuf *m;
3144 3144
3145 while ((m = pcq_get(wgp->wgp_q)) != NULL) { 3145 while ((m = pcq_get(wgp->wgp_q)) != NULL) {
3146 m_freem(m); 3146 m_freem(m);
3147 } 3147 }
3148} 3148}
3149 3149
3150static void 3150static void
3151wg_handshake_timeout_timer(void *arg) 3151wg_handshake_timeout_timer(void *arg)
3152{ 3152{
3153 struct wg_peer *wgp = arg; 3153 struct wg_peer *wgp = arg;
3154 struct wg_session *wgs; 3154 struct wg_session *wgs;
3155 struct psref psref; 3155 struct psref psref;
3156 3156
3157 WG_TRACE("enter"); 3157 WG_TRACE("enter");
3158 3158
3159 mutex_enter(wgp->wgp_lock); 3159 mutex_enter(wgp->wgp_lock);
3160 if (__predict_false(wgp->wgp_state == WGP_STATE_DESTROYING)) { 3160 if (__predict_false(wgp->wgp_state == WGP_STATE_DESTROYING)) {
3161 mutex_exit(wgp->wgp_lock); 3161 mutex_exit(wgp->wgp_lock);
3162 return; 3162 return;
3163 } 3163 }
3164 mutex_exit(wgp->wgp_lock); 3164 mutex_exit(wgp->wgp_lock);
3165 3165
3166 KASSERT(wgp->wgp_handshake_start_time != 0); 3166 KASSERT(wgp->wgp_handshake_start_time != 0);
3167 wgs = wg_get_unstable_session(wgp, &psref); 3167 wgs = wg_get_unstable_session(wgp, &psref);
3168 KASSERT(wgs->wgs_state == WGS_STATE_INIT_ACTIVE); 3168 KASSERT(wgs->wgs_state == WGS_STATE_INIT_ACTIVE);
3169 3169
3170 /* [W] 6.4 Handshake Initiation Retransmission */ 3170 /* [W] 6.4 Handshake Initiation Retransmission */
3171 if ((time_uptime - wgp->wgp_handshake_start_time) > 3171 if ((time_uptime - wgp->wgp_handshake_start_time) >
3172 wg_rekey_attempt_time) { 3172 wg_rekey_attempt_time) {
3173 /* Give up handshaking */ 3173 /* Give up handshaking */
3174 wgs->wgs_state = WGS_STATE_UNKNOWN; 3174 wgs->wgs_state = WGS_STATE_UNKNOWN;
3175 wg_clear_states(wgs); 3175 wg_clear_states(wgs);
3176 wgp->wgp_state = WGP_STATE_GIVEUP; 3176 wgp->wgp_state = WGP_STATE_GIVEUP;
3177 wgp->wgp_handshake_start_time = 0; 3177 wgp->wgp_handshake_start_time = 0;
3178 wg_put_session(wgs, &psref); 3178 wg_put_session(wgs, &psref);
3179 WG_TRACE("give up"); 3179 WG_TRACE("give up");
3180 /* 3180 /*
3181 * If a new data packet comes, handshaking will be retried 3181 * If a new data packet comes, handshaking will be retried
3182 * and a new session would be established at that time, 3182 * and a new session would be established at that time,
3183 * however we don't want to send pending packets then. 3183 * however we don't want to send pending packets then.
3184 */ 3184 */
3185 wg_purge_pending_packets(wgp); 3185 wg_purge_pending_packets(wgp);
3186 return; 3186 return;
3187 } 3187 }
3188 3188
3189 /* No response for an initiation message sent, retry handshaking */ 3189 /* No response for an initiation message sent, retry handshaking */
3190 wgs->wgs_state = WGS_STATE_UNKNOWN; 3190 wgs->wgs_state = WGS_STATE_UNKNOWN;
3191 wg_clear_states(wgs); 3191 wg_clear_states(wgs);
3192 wg_put_session(wgs, &psref); 3192 wg_put_session(wgs, &psref);
3193 3193
3194 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3194 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3195} 3195}
3196 3196
3197static struct wg_peer * 3197static struct wg_peer *
3198wg_alloc_peer(struct wg_softc *wg) 3198wg_alloc_peer(struct wg_softc *wg)
3199{ 3199{
3200 struct wg_peer *wgp; 3200 struct wg_peer *wgp;
3201 3201
3202 wgp = kmem_zalloc(sizeof(*wgp), KM_SLEEP); 3202 wgp = kmem_zalloc(sizeof(*wgp), KM_SLEEP);
3203 3203
3204 wgp->wgp_sc = wg; 3204 wgp->wgp_sc = wg;
3205 wgp->wgp_state = WGP_STATE_INIT; 3205 wgp->wgp_state = WGP_STATE_INIT;
3206 wgp->wgp_q = pcq_create(1024, KM_SLEEP); 3206 wgp->wgp_q = pcq_create(1024, KM_SLEEP);
3207 wgp->wgp_si = softint_establish(SOFTINT_NET, wg_peer_softint, wgp); 3207 wgp->wgp_si = softint_establish(SOFTINT_NET, wg_peer_softint, wgp);
3208 callout_init(&wgp->wgp_rekey_timer, CALLOUT_MPSAFE); 3208 callout_init(&wgp->wgp_rekey_timer, CALLOUT_MPSAFE);
3209 callout_setfunc(&wgp->wgp_rekey_timer, wg_rekey_timer, wgp); 3209 callout_setfunc(&wgp->wgp_rekey_timer, wg_rekey_timer, wgp);
3210 callout_init(&wgp->wgp_handshake_timeout_timer, CALLOUT_MPSAFE); 3210 callout_init(&wgp->wgp_handshake_timeout_timer, CALLOUT_MPSAFE);
3211 callout_setfunc(&wgp->wgp_handshake_timeout_timer, 3211 callout_setfunc(&wgp->wgp_handshake_timeout_timer,
3212 wg_handshake_timeout_timer, wgp); 3212 wg_handshake_timeout_timer, wgp);
3213 callout_init(&wgp->wgp_session_dtor_timer, CALLOUT_MPSAFE); 3213 callout_init(&wgp->wgp_session_dtor_timer, CALLOUT_MPSAFE);
3214 callout_setfunc(&wgp->wgp_session_dtor_timer, 3214 callout_setfunc(&wgp->wgp_session_dtor_timer,
3215 wg_session_dtor_timer, wgp); 3215 wg_session_dtor_timer, wgp);
3216 PSLIST_ENTRY_INIT(wgp, wgp_peerlist_entry); 3216 PSLIST_ENTRY_INIT(wgp, wgp_peerlist_entry);
3217 wgp->wgp_endpoint_changing = false; 3217 wgp->wgp_endpoint_changing = false;
3218 wgp->wgp_endpoint_available = false; 3218 wgp->wgp_endpoint_available = false;
3219 wgp->wgp_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 3219 wgp->wgp_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
3220 wgp->wgp_psz = pserialize_create(); 3220 wgp->wgp_psz = pserialize_create();
3221 psref_target_init(&wgp->wgp_psref, wg_psref_class); 3221 psref_target_init(&wgp->wgp_psref, wg_psref_class);
3222 3222
3223 wgp->wgp_endpoint = kmem_zalloc(sizeof(*wgp->wgp_endpoint), KM_SLEEP); 3223 wgp->wgp_endpoint = kmem_zalloc(sizeof(*wgp->wgp_endpoint), KM_SLEEP);
3224 wgp->wgp_endpoint0 = kmem_zalloc(sizeof(*wgp->wgp_endpoint0), KM_SLEEP); 3224 wgp->wgp_endpoint0 = kmem_zalloc(sizeof(*wgp->wgp_endpoint0), KM_SLEEP);
3225 psref_target_init(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class); 3225 psref_target_init(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class);
3226 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class); 3226 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class);
3227 3227
3228 struct wg_session *wgs; 3228 struct wg_session *wgs;
3229 wgp->wgp_session_stable = 3229 wgp->wgp_session_stable =
3230 kmem_zalloc(sizeof(*wgp->wgp_session_stable), KM_SLEEP); 3230 kmem_zalloc(sizeof(*wgp->wgp_session_stable), KM_SLEEP);
3231 wgp->wgp_session_unstable = 3231 wgp->wgp_session_unstable =
3232 kmem_zalloc(sizeof(*wgp->wgp_session_unstable), KM_SLEEP); 3232 kmem_zalloc(sizeof(*wgp->wgp_session_unstable), KM_SLEEP);
3233 wgs = wgp->wgp_session_stable; 3233 wgs = wgp->wgp_session_stable;
3234 wgs->wgs_peer = wgp; 3234 wgs->wgs_peer = wgp;
3235 wgs->wgs_state = WGS_STATE_UNKNOWN; 3235 wgs->wgs_state = WGS_STATE_UNKNOWN;
3236 psref_target_init(&wgs->wgs_psref, wg_psref_class); 3236 psref_target_init(&wgs->wgs_psref, wg_psref_class);
3237 wgs->wgs_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 3237 wgs->wgs_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
3238#ifndef __HAVE_ATOMIC64_LOADSTORE 3238#ifndef __HAVE_ATOMIC64_LOADSTORE
3239 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET); 3239 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET);
3240#endif 3240#endif
3241 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP); 3241 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP);
3242 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_NONE); 3242 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_NONE);
3243 3243
3244 wgs = wgp->wgp_session_unstable; 3244 wgs = wgp->wgp_session_unstable;
3245 wgs->wgs_peer = wgp; 3245 wgs->wgs_peer = wgp;
3246 wgs->wgs_state = WGS_STATE_UNKNOWN; 3246 wgs->wgs_state = WGS_STATE_UNKNOWN;
3247 psref_target_init(&wgs->wgs_psref, wg_psref_class); 3247 psref_target_init(&wgs->wgs_psref, wg_psref_class);
3248 wgs->wgs_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 3248 wgs->wgs_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
3249#ifndef __HAVE_ATOMIC64_LOADSTORE 3249#ifndef __HAVE_ATOMIC64_LOADSTORE
3250 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET); 3250 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET);
3251#endif 3251#endif
3252 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP); 3252 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP);
3253 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_NONE); 3253 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_NONE);
3254 3254
3255 return wgp; 3255 return wgp;
3256} 3256}
3257 3257
3258static void 3258static void
3259wg_destroy_peer(struct wg_peer *wgp) 3259wg_destroy_peer(struct wg_peer *wgp)
3260{ 3260{
3261 struct wg_session *wgs; 3261 struct wg_session *wgs;
3262 struct wg_softc *wg = wgp->wgp_sc; 3262 struct wg_softc *wg = wgp->wgp_sc;
3263 3263
3264 rw_enter(wg->wg_rwlock, RW_WRITER); 3264 rw_enter(wg->wg_rwlock, RW_WRITER);
3265 for (int i = 0; i < wgp->wgp_n_allowedips; i++) { 3265 for (int i = 0; i < wgp->wgp_n_allowedips; i++) {
3266 struct wg_allowedip *wga = &wgp->wgp_allowedips[i]; 3266 struct wg_allowedip *wga = &wgp->wgp_allowedips[i];
3267 struct radix_node_head *rnh = wg_rnh(wg, wga->wga_family); 3267 struct radix_node_head *rnh = wg_rnh(wg, wga->wga_family);
3268 struct radix_node *rn; 3268 struct radix_node *rn;
3269 3269
3270 KASSERT(rnh != NULL); 3270 KASSERT(rnh != NULL);
3271 rn = rnh->rnh_deladdr(&wga->wga_sa_addr, 3271 rn = rnh->rnh_deladdr(&wga->wga_sa_addr,
3272 &wga->wga_sa_mask, rnh); 3272 &wga->wga_sa_mask, rnh);
3273 if (rn == NULL) { 3273 if (rn == NULL) {
3274 char addrstr[128]; 3274 char addrstr[128];
3275 sockaddr_format(&wga->wga_sa_addr, addrstr, 3275 sockaddr_format(&wga->wga_sa_addr, addrstr,
3276 sizeof(addrstr)); 3276 sizeof(addrstr));
3277 WGLOG(LOG_WARNING, "Couldn't delete %s", addrstr); 3277 WGLOG(LOG_WARNING, "Couldn't delete %s", addrstr);
3278 } 3278 }
3279 } 3279 }
3280 rw_exit(wg->wg_rwlock); 3280 rw_exit(wg->wg_rwlock);
3281 3281
3282 softint_disestablish(wgp->wgp_si); 3282 softint_disestablish(wgp->wgp_si);
3283 callout_halt(&wgp->wgp_rekey_timer, NULL); 3283 callout_halt(&wgp->wgp_rekey_timer, NULL);
3284 callout_halt(&wgp->wgp_handshake_timeout_timer, NULL); 3284 callout_halt(&wgp->wgp_handshake_timeout_timer, NULL);
3285 callout_halt(&wgp->wgp_session_dtor_timer, NULL); 3285 callout_halt(&wgp->wgp_session_dtor_timer, NULL);
3286 3286
3287 wgs = wgp->wgp_session_unstable; 3287 wgs = wgp->wgp_session_unstable;
3288 psref_target_destroy(&wgs->wgs_psref, wg_psref_class); 3288 psref_target_destroy(&wgs->wgs_psref, wg_psref_class);
3289 mutex_obj_free(wgs->wgs_lock); 3289 mutex_obj_free(wgs->wgs_lock);
3290 mutex_destroy(&wgs->wgs_recvwin->lock); 3290 mutex_destroy(&wgs->wgs_recvwin->lock);
3291 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin)); 3291 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin));
3292#ifndef __HAVE_ATOMIC64_LOADSTORE 3292#ifndef __HAVE_ATOMIC64_LOADSTORE
3293 mutex_destroy(&wgs->wgs_send_counter_lock); 3293 mutex_destroy(&wgs->wgs_send_counter_lock);
3294#endif 3294#endif
3295 kmem_free(wgs, sizeof(*wgs)); 3295 kmem_free(wgs, sizeof(*wgs));
3296 wgs = wgp->wgp_session_stable; 3296 wgs = wgp->wgp_session_stable;
3297 psref_target_destroy(&wgs->wgs_psref, wg_psref_class); 3297 psref_target_destroy(&wgs->wgs_psref, wg_psref_class);
3298 mutex_obj_free(wgs->wgs_lock); 3298 mutex_obj_free(wgs->wgs_lock);
3299 mutex_destroy(&wgs->wgs_recvwin->lock); 3299 mutex_destroy(&wgs->wgs_recvwin->lock);
3300 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin)); 3300 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin));
3301#ifndef __HAVE_ATOMIC64_LOADSTORE 3301#ifndef __HAVE_ATOMIC64_LOADSTORE
3302 mutex_destroy(&wgs->wgs_send_counter_lock); 3302 mutex_destroy(&wgs->wgs_send_counter_lock);
3303#endif 3303#endif
3304 kmem_free(wgs, sizeof(*wgs)); 3304 kmem_free(wgs, sizeof(*wgs));
3305 3305
3306 psref_target_destroy(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class); 3306 psref_target_destroy(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class);
3307 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class); 3307 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class);
3308 kmem_free(wgp->wgp_endpoint, sizeof(*wgp->wgp_endpoint)); 3308 kmem_free(wgp->wgp_endpoint, sizeof(*wgp->wgp_endpoint));
3309 kmem_free(wgp->wgp_endpoint0, sizeof(*wgp->wgp_endpoint0)); 3309 kmem_free(wgp->wgp_endpoint0, sizeof(*wgp->wgp_endpoint0));
3310 3310
3311 pserialize_destroy(wgp->wgp_psz); 3311 pserialize_destroy(wgp->wgp_psz);
3312 pcq_destroy(wgp->wgp_q); 3312 pcq_destroy(wgp->wgp_q);
3313 mutex_obj_free(wgp->wgp_lock); 3313 mutex_obj_free(wgp->wgp_lock);
3314 3314
3315 kmem_free(wgp, sizeof(*wgp)); 3315 kmem_free(wgp, sizeof(*wgp));
3316} 3316}
3317 3317
3318static void 3318static void
3319wg_destroy_all_peers(struct wg_softc *wg) 3319wg_destroy_all_peers(struct wg_softc *wg)
3320{ 3320{
3321 struct wg_peer *wgp; 3321 struct wg_peer *wgp;
3322 3322
3323restart: 3323restart:
3324 mutex_enter(wg->wg_lock); 3324 mutex_enter(wg->wg_lock);
3325 WG_PEER_WRITER_FOREACH(wgp, wg) { 3325 WG_PEER_WRITER_FOREACH(wgp, wg) {
3326 WG_PEER_WRITER_REMOVE(wgp); 3326 WG_PEER_WRITER_REMOVE(wgp);
3327 mutex_enter(wgp->wgp_lock); 3327 mutex_enter(wgp->wgp_lock);
3328 wgp->wgp_state = WGP_STATE_DESTROYING; 3328 wgp->wgp_state = WGP_STATE_DESTROYING;
3329 pserialize_perform(wgp->wgp_psz); 3329 pserialize_perform(wgp->wgp_psz);
3330 mutex_exit(wgp->wgp_lock); 3330 mutex_exit(wgp->wgp_lock);
3331 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry); 3331 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry);
3332 break; 3332 break;
3333 } 3333 }
3334 mutex_exit(wg->wg_lock); 3334 mutex_exit(wg->wg_lock);
3335 3335
3336 if (wgp == NULL) 3336 if (wgp == NULL)
3337 return; 3337 return;
3338 3338
3339 psref_target_destroy(&wgp->wgp_psref, wg_psref_class); 3339 psref_target_destroy(&wgp->wgp_psref, wg_psref_class);
3340 3340
3341 wg_destroy_peer(wgp); 3341 wg_destroy_peer(wgp);
3342 3342
3343 goto restart; 3343 goto restart;
3344} 3344}
3345 3345
3346static int 3346static int
3347wg_destroy_peer_name(struct wg_softc *wg, const char *name) 3347wg_destroy_peer_name(struct wg_softc *wg, const char *name)
3348{ 3348{
3349 struct wg_peer *wgp; 3349 struct wg_peer *wgp;
3350 3350
3351 mutex_enter(wg->wg_lock); 3351 mutex_enter(wg->wg_lock);
3352 WG_PEER_WRITER_FOREACH(wgp, wg) { 3352 WG_PEER_WRITER_FOREACH(wgp, wg) {
3353 if (strcmp(wgp->wgp_name, name) == 0) 3353 if (strcmp(wgp->wgp_name, name) == 0)
3354 break; 3354 break;
3355 } 3355 }
3356 if (wgp != NULL) { 3356 if (wgp != NULL) {
3357 WG_PEER_WRITER_REMOVE(wgp); 3357 WG_PEER_WRITER_REMOVE(wgp);
3358 wg->wg_npeers--; 3358 wg->wg_npeers--;
3359 mutex_enter(wgp->wgp_lock); 3359 mutex_enter(wgp->wgp_lock);
3360 wgp->wgp_state = WGP_STATE_DESTROYING; 3360 wgp->wgp_state = WGP_STATE_DESTROYING;
3361 pserialize_perform(wgp->wgp_psz); 3361 pserialize_perform(wgp->wgp_psz);
3362 mutex_exit(wgp->wgp_lock); 3362 mutex_exit(wgp->wgp_lock);
3363 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry); 3363 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry);
3364 } 3364 }
3365 mutex_exit(wg->wg_lock); 3365 mutex_exit(wg->wg_lock);
3366 3366
3367 if (wgp == NULL) 3367 if (wgp == NULL)
3368 return ENOENT; 3368 return ENOENT;
3369 3369
3370 psref_target_destroy(&wgp->wgp_psref, wg_psref_class); 3370 psref_target_destroy(&wgp->wgp_psref, wg_psref_class);
3371 3371
3372 wg_destroy_peer(wgp); 3372 wg_destroy_peer(wgp);
3373 3373
3374 return 0; 3374 return 0;
3375} 3375}
3376 3376
3377static int 3377static int
3378wg_if_attach(struct wg_softc *wg) 3378wg_if_attach(struct wg_softc *wg)
3379{ 3379{
3380 int error; 3380 int error;
3381 3381
3382 wg->wg_if.if_addrlen = 0; 3382 wg->wg_if.if_addrlen = 0;
3383 wg->wg_if.if_mtu = WG_MTU; 3383 wg->wg_if.if_mtu = WG_MTU;
3384 wg->wg_if.if_flags = IFF_POINTOPOINT; 3384 wg->wg_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
3385 wg->wg_if.if_extflags = IFEF_NO_LINK_STATE_CHANGE; 3385 wg->wg_if.if_extflags = IFEF_NO_LINK_STATE_CHANGE;
3386 wg->wg_if.if_extflags |= IFEF_MPSAFE; 3386 wg->wg_if.if_extflags |= IFEF_MPSAFE;
3387 wg->wg_if.if_ioctl = wg_ioctl; 3387 wg->wg_if.if_ioctl = wg_ioctl;
3388 wg->wg_if.if_output = wg_output; 3388 wg->wg_if.if_output = wg_output;
3389 wg->wg_if.if_init = wg_init; 3389 wg->wg_if.if_init = wg_init;
3390 wg->wg_if.if_stop = wg_stop; 3390 wg->wg_if.if_stop = wg_stop;
3391 wg->wg_if.if_type = IFT_OTHER; 3391 wg->wg_if.if_type = IFT_OTHER;
3392 wg->wg_if.if_dlt = DLT_NULL; 3392 wg->wg_if.if_dlt = DLT_NULL;
3393 wg->wg_if.if_softc = wg; 3393 wg->wg_if.if_softc = wg;
3394 IFQ_SET_READY(&wg->wg_if.if_snd); 3394 IFQ_SET_READY(&wg->wg_if.if_snd);
3395 3395
3396 error = if_initialize(&wg->wg_if); 3396 error = if_initialize(&wg->wg_if);
3397 if (error != 0) 3397 if (error != 0)
3398 return error; 3398 return error;
3399 3399
3400 if_alloc_sadl(&wg->wg_if); 3400 if_alloc_sadl(&wg->wg_if);
3401 if_register(&wg->wg_if); 3401 if_register(&wg->wg_if);
3402 3402
3403 bpf_attach(&wg->wg_if, DLT_NULL, sizeof(uint32_t)); 3403 bpf_attach(&wg->wg_if, DLT_NULL, sizeof(uint32_t));
3404 3404
3405 return 0; 3405 return 0;
3406} 3406}
3407 3407
3408static int 3408static int
3409wg_clone_create(struct if_clone *ifc, int unit) 3409wg_clone_create(struct if_clone *ifc, int unit)
3410{ 3410{
3411 struct wg_softc *wg; 3411 struct wg_softc *wg;
3412 int error; 3412 int error;
3413 3413
3414 wg = kmem_zalloc(sizeof(struct wg_softc), KM_SLEEP); 3414 wg = kmem_zalloc(sizeof(struct wg_softc), KM_SLEEP);
3415 3415
3416 if_initname(&wg->wg_if, ifc->ifc_name, unit); 3416 if_initname(&wg->wg_if, ifc->ifc_name, unit);
3417 3417
3418 error = wg_worker_init(wg); 3418 error = wg_worker_init(wg);
3419 if (error != 0) { 3419 if (error != 0) {
3420 kmem_free(wg, sizeof(struct wg_softc)); 3420 kmem_free(wg, sizeof(struct wg_softc));
3421 return error; 3421 return error;
3422 } 3422 }
3423 3423
3424 rn_inithead((void **)&wg->wg_rtable_ipv4, 3424 rn_inithead((void **)&wg->wg_rtable_ipv4,
3425 offsetof(struct sockaddr_in, sin_addr) * NBBY); 3425 offsetof(struct sockaddr_in, sin_addr) * NBBY);
3426#ifdef INET6 3426#ifdef INET6
3427 rn_inithead((void **)&wg->wg_rtable_ipv6, 3427 rn_inithead((void **)&wg->wg_rtable_ipv6,
3428 offsetof(struct sockaddr_in6, sin6_addr) * NBBY); 3428 offsetof(struct sockaddr_in6, sin6_addr) * NBBY);
3429#endif 3429#endif
3430 3430
3431 PSLIST_INIT(&wg->wg_peers); 3431 PSLIST_INIT(&wg->wg_peers);
3432 wg->wg_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 3432 wg->wg_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
3433 wg->wg_rwlock = rw_obj_alloc(); 3433 wg->wg_rwlock = rw_obj_alloc();
3434 wg->wg_ops = &wg_ops_rumpkernel; 3434 wg->wg_ops = &wg_ops_rumpkernel;
3435 3435
3436 error = wg_if_attach(wg); 3436 error = wg_if_attach(wg);
3437 if (error != 0) { 3437 if (error != 0) {
3438 wg_worker_destroy(wg); 3438 wg_worker_destroy(wg);
3439 if (wg->wg_rtable_ipv4 != NULL) 3439 if (wg->wg_rtable_ipv4 != NULL)
3440 free(wg->wg_rtable_ipv4, M_RTABLE); 3440 free(wg->wg_rtable_ipv4, M_RTABLE);
3441 if (wg->wg_rtable_ipv6 != NULL) 3441 if (wg->wg_rtable_ipv6 != NULL)
3442 free(wg->wg_rtable_ipv6, M_RTABLE); 3442 free(wg->wg_rtable_ipv6, M_RTABLE);
3443 PSLIST_DESTROY(&wg->wg_peers); 3443 PSLIST_DESTROY(&wg->wg_peers);
3444 mutex_obj_free(wg->wg_lock); 3444 mutex_obj_free(wg->wg_lock);
3445 kmem_free(wg, sizeof(struct wg_softc)); 3445 kmem_free(wg, sizeof(struct wg_softc));
3446 return error; 3446 return error;
3447 } 3447 }
3448 3448
3449 mutex_enter(&wg_softcs.lock); 3449 mutex_enter(&wg_softcs.lock);
3450 LIST_INSERT_HEAD(&wg_softcs.list, wg, wg_list); 3450 LIST_INSERT_HEAD(&wg_softcs.list, wg, wg_list);
3451 mutex_exit(&wg_softcs.lock); 3451 mutex_exit(&wg_softcs.lock);
3452 3452
3453 return 0; 3453 return 0;
3454} 3454}
3455 3455
3456static int 3456static int
3457wg_clone_destroy(struct ifnet *ifp) 3457wg_clone_destroy(struct ifnet *ifp)
3458{ 3458{
3459 struct wg_softc *wg = container_of(ifp, struct wg_softc, wg_if); 3459 struct wg_softc *wg = container_of(ifp, struct wg_softc, wg_if);
3460 3460
3461 mutex_enter(&wg_softcs.lock); 3461 mutex_enter(&wg_softcs.lock);
3462 LIST_REMOVE(wg, wg_list); 3462 LIST_REMOVE(wg, wg_list);
3463 mutex_exit(&wg_softcs.lock); 3463 mutex_exit(&wg_softcs.lock);
3464 3464
3465#ifdef WG_RUMPKERNEL 3465#ifdef WG_RUMPKERNEL
3466 if (wg_user_mode(wg)) { 3466 if (wg_user_mode(wg)) {
3467 rumpuser_wg_destroy(wg->wg_user); 3467 rumpuser_wg_destroy(wg->wg_user);
3468 wg->wg_user = NULL; 3468 wg->wg_user = NULL;
3469 } 3469 }
3470#endif 3470#endif
3471 3471
3472 bpf_detach(ifp); 3472 bpf_detach(ifp);
3473 if_detach(ifp); 3473 if_detach(ifp);
3474 wg_worker_destroy(wg); 3474 wg_worker_destroy(wg);
3475 wg_destroy_all_peers(wg); 3475 wg_destroy_all_peers(wg);
3476 if (wg->wg_rtable_ipv4 != NULL) 3476 if (wg->wg_rtable_ipv4 != NULL)
3477 free(wg->wg_rtable_ipv4, M_RTABLE); 3477 free(wg->wg_rtable_ipv4, M_RTABLE);
3478 if (wg->wg_rtable_ipv6 != NULL) 3478 if (wg->wg_rtable_ipv6 != NULL)
3479 free(wg->wg_rtable_ipv6, M_RTABLE); 3479 free(wg->wg_rtable_ipv6, M_RTABLE);
3480 3480
3481 PSLIST_DESTROY(&wg->wg_peers); 3481 PSLIST_DESTROY(&wg->wg_peers);
3482 mutex_obj_free(wg->wg_lock); 3482 mutex_obj_free(wg->wg_lock);
3483 rw_obj_free(wg->wg_rwlock); 3483 rw_obj_free(wg->wg_rwlock);
3484 3484
3485 kmem_free(wg, sizeof(struct wg_softc)); 3485 kmem_free(wg, sizeof(struct wg_softc));
3486 3486
3487 return 0; 3487 return 0;
3488} 3488}
3489 3489
3490static struct wg_peer * 3490static struct wg_peer *
3491wg_pick_peer_by_sa(struct wg_softc *wg, const struct sockaddr *sa, 3491wg_pick_peer_by_sa(struct wg_softc *wg, const struct sockaddr *sa,
3492 struct psref *psref) 3492 struct psref *psref)
3493{ 3493{
3494 struct radix_node_head *rnh; 3494 struct radix_node_head *rnh;
3495 struct radix_node *rn; 3495 struct radix_node *rn;
3496 struct wg_peer *wgp = NULL; 3496 struct wg_peer *wgp = NULL;
3497 struct wg_allowedip *wga; 3497 struct wg_allowedip *wga;
3498 3498
3499#ifdef WG_DEBUG_LOG 3499#ifdef WG_DEBUG_LOG
3500 char addrstr[128]; 3500 char addrstr[128];
3501 sockaddr_format(sa, addrstr, sizeof(addrstr)); 3501 sockaddr_format(sa, addrstr, sizeof(addrstr));
3502 WG_DLOG("sa=%s\n", addrstr); 3502 WG_DLOG("sa=%s\n", addrstr);
3503#endif 3503#endif
3504 3504
3505 rw_enter(wg->wg_rwlock, RW_READER); 3505 rw_enter(wg->wg_rwlock, RW_READER);
3506 3506
3507 rnh = wg_rnh(wg, sa->sa_family); 3507 rnh = wg_rnh(wg, sa->sa_family);
3508 if (rnh == NULL) 3508 if (rnh == NULL)
3509 goto out; 3509 goto out;
3510 3510
3511 rn = rnh->rnh_matchaddr(sa, rnh); 3511 rn = rnh->rnh_matchaddr(sa, rnh);
3512 if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0) 3512 if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0)
3513 goto out; 3513 goto out;
3514 3514
3515 WG_TRACE("success"); 3515 WG_TRACE("success");
3516 3516
3517 wga = container_of(rn, struct wg_allowedip, wga_nodes[0]); 3517 wga = container_of(rn, struct wg_allowedip, wga_nodes[0]);
3518 wgp = wga->wga_peer; 3518 wgp = wga->wga_peer;
3519 wg_get_peer(wgp, psref); 3519 wg_get_peer(wgp, psref);
3520 3520
3521out: 3521out:
3522 rw_exit(wg->wg_rwlock); 3522 rw_exit(wg->wg_rwlock);
3523 return wgp; 3523 return wgp;
3524} 3524}
3525 3525
3526static void 3526static void
3527wg_fill_msg_data(struct wg_softc *wg, struct wg_peer *wgp, 3527wg_fill_msg_data(struct wg_softc *wg, struct wg_peer *wgp,
3528 struct wg_session *wgs, struct wg_msg_data *wgmd) 3528 struct wg_session *wgs, struct wg_msg_data *wgmd)
3529{ 3529{
3530 3530
3531 memset(wgmd, 0, sizeof(*wgmd)); 3531 memset(wgmd, 0, sizeof(*wgmd));
3532 wgmd->wgmd_type = WG_MSG_TYPE_DATA; 3532 wgmd->wgmd_type = WG_MSG_TYPE_DATA;
3533 wgmd->wgmd_receiver = wgs->wgs_receiver_index; 3533 wgmd->wgmd_receiver = wgs->wgs_receiver_index;
3534 /* [W] 5.4.6: msg.counter := Nm^send */ 3534 /* [W] 5.4.6: msg.counter := Nm^send */
3535 /* [W] 5.4.6: Nm^send := Nm^send + 1 */ 3535 /* [W] 5.4.6: Nm^send := Nm^send + 1 */
3536 wgmd->wgmd_counter = wg_session_inc_send_counter(wgs); 3536 wgmd->wgmd_counter = wg_session_inc_send_counter(wgs);
3537 WG_DLOG("counter=%"PRIu64"\n", wgmd->wgmd_counter); 3537 WG_DLOG("counter=%"PRIu64"\n", wgmd->wgmd_counter);
3538} 3538}
3539 3539
3540static int 3540static int
3541wg_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 3541wg_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
3542 const struct rtentry *rt) 3542 const struct rtentry *rt)
3543{ 3543{
3544 struct wg_softc *wg = ifp->if_softc; 3544 struct wg_softc *wg = ifp->if_softc;
3545 int error = 0; 3545 int error = 0;
3546 int bound; 3546 int bound;
3547 struct psref psref; 3547 struct psref psref;
3548 3548
3549 /* TODO make the nest limit configurable via sysctl */ 3549 /* TODO make the nest limit configurable via sysctl */
3550 error = if_tunnel_check_nesting(ifp, m, 1); 3550 error = if_tunnel_check_nesting(ifp, m, 1);
3551 if (error != 0) { 3551 if (error != 0) {
3552 m_freem(m); 3552 m_freem(m);
3553 WGLOG(LOG_ERR, "tunneling loop detected and packet dropped\n"); 3553 WGLOG(LOG_ERR, "tunneling loop detected and packet dropped\n");
3554 return error; 3554 return error;
3555 } 3555 }
3556 3556
3557 bound = curlwp_bind(); 3557 bound = curlwp_bind();
3558 3558
3559 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family); 3559 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
3560 3560
3561 bpf_mtap_af(ifp, dst->sa_family, m, BPF_D_OUT); 3561 bpf_mtap_af(ifp, dst->sa_family, m, BPF_D_OUT);
3562 3562
3563 m->m_flags &= ~(M_BCAST|M_MCAST); 3563 m->m_flags &= ~(M_BCAST|M_MCAST);
3564 3564
3565 struct wg_peer *wgp = wg_pick_peer_by_sa(wg, dst, &psref); 3565 struct wg_peer *wgp = wg_pick_peer_by_sa(wg, dst, &psref);
3566 if (wgp == NULL) { 3566 if (wgp == NULL) {
3567 WG_TRACE("peer not found"); 3567 WG_TRACE("peer not found");
3568 error = EHOSTUNREACH; 3568 error = EHOSTUNREACH;
3569 goto error; 3569 goto error;
3570 } 3570 }
3571 3571
3572 /* Clear checksum-offload flags. */ 3572 /* Clear checksum-offload flags. */
3573 m->m_pkthdr.csum_flags = 0; 3573 m->m_pkthdr.csum_flags = 0;
3574 m->m_pkthdr.csum_data = 0; 3574 m->m_pkthdr.csum_data = 0;
3575 3575
3576 if (!pcq_put(wgp->wgp_q, m)) { 3576 if (!pcq_put(wgp->wgp_q, m)) {
3577 error = ENOBUFS; 3577 error = ENOBUFS;
3578 goto error; 3578 goto error;
3579 } 3579 }
3580 3580
3581 struct psref psref_wgs; 3581 struct psref psref_wgs;
3582 struct wg_session *wgs; 3582 struct wg_session *wgs;
3583 wgs = wg_get_stable_session(wgp, &psref_wgs); 3583 wgs = wg_get_stable_session(wgp, &psref_wgs);
3584 if (wgs->wgs_state == WGS_STATE_ESTABLISHED && 3584 if (wgs->wgs_state == WGS_STATE_ESTABLISHED &&
3585 !wg_session_hit_limits(wgs)) { 3585 !wg_session_hit_limits(wgs)) {
3586 kpreempt_disable(); 3586 kpreempt_disable();
3587 softint_schedule(wgp->wgp_si); 3587 softint_schedule(wgp->wgp_si);
3588 kpreempt_enable(); 3588 kpreempt_enable();
3589 WG_TRACE("softint scheduled"); 3589 WG_TRACE("softint scheduled");
3590 } else { 3590 } else {
3591 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3591 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3592 WG_TRACE("softint NOT scheduled"); 3592 WG_TRACE("softint NOT scheduled");
3593 } 3593 }
3594 wg_put_session(wgs, &psref_wgs); 3594 wg_put_session(wgs, &psref_wgs);
3595 wg_put_peer(wgp, &psref); 3595 wg_put_peer(wgp, &psref);
3596 3596
3597 return 0; 3597 return 0;
3598 3598
3599error: 3599error:
3600 if (wgp != NULL) 3600 if (wgp != NULL)
3601 wg_put_peer(wgp, &psref); 3601 wg_put_peer(wgp, &psref);
3602 if (m != NULL) 3602 if (m != NULL)
3603 m_freem(m); 3603 m_freem(m);
3604 curlwp_bindx(bound); 3604 curlwp_bindx(bound);
3605 return error; 3605 return error;
3606} 3606}
3607 3607
3608static int 3608static int
3609wg_send_udp(struct wg_peer *wgp, struct mbuf *m) 3609wg_send_udp(struct wg_peer *wgp, struct mbuf *m)
3610{ 3610{
3611 struct psref psref; 3611 struct psref psref;
3612 struct wg_sockaddr *wgsa; 3612 struct wg_sockaddr *wgsa;
3613 int error; 3613 int error;
3614 struct socket *so = wg_get_so_by_peer(wgp); 3614 struct socket *so = wg_get_so_by_peer(wgp);
3615 3615
3616 solock(so); 3616 solock(so);
3617 wgsa = wg_get_endpoint_sa(wgp, &psref); 3617 wgsa = wg_get_endpoint_sa(wgp, &psref);
3618 if (wgsatosa(wgsa)->sa_family == AF_INET) { 3618 if (wgsatosa(wgsa)->sa_family == AF_INET) {
3619 error = udp_send(so, m, wgsatosa(wgsa), NULL, curlwp); 3619 error = udp_send(so, m, wgsatosa(wgsa), NULL, curlwp);
3620 } else { 3620 } else {
3621#ifdef INET6 3621#ifdef INET6
3622 error = udp6_output(sotoin6pcb(so), m, wgsatosin6(wgsa), 3622 error = udp6_output(sotoin6pcb(so), m, wgsatosin6(wgsa),
3623 NULL, curlwp); 3623 NULL, curlwp);
3624#else 3624#else
3625 error = EPROTONOSUPPORT; 3625 error = EPROTONOSUPPORT;
3626#endif 3626#endif
3627 } 3627 }
3628 wg_put_sa(wgp, wgsa, &psref); 3628 wg_put_sa(wgp, wgsa, &psref);
3629 sounlock(so); 3629 sounlock(so);
3630 3630
3631 return error; 3631 return error;
3632} 3632}
3633 3633
3634/* Inspired by pppoe_get_mbuf */ 3634/* Inspired by pppoe_get_mbuf */
3635static struct mbuf * 3635static struct mbuf *
3636wg_get_mbuf(size_t leading_len, size_t len) 3636wg_get_mbuf(size_t leading_len, size_t len)
3637{ 3637{
3638 struct mbuf *m; 3638 struct mbuf *m;
3639 3639
3640 KASSERT(leading_len <= MCLBYTES); 3640 KASSERT(leading_len <= MCLBYTES);
3641 KASSERT(len <= MCLBYTES - leading_len); 3641 KASSERT(len <= MCLBYTES - leading_len);
3642 3642
3643 m = m_gethdr(M_DONTWAIT, MT_DATA); 3643 m = m_gethdr(M_DONTWAIT, MT_DATA);
3644 if (m == NULL) 3644 if (m == NULL)
3645 return NULL; 3645 return NULL;
3646 if (len + leading_len > MHLEN) { 3646 if (len + leading_len > MHLEN) {
3647 m_clget(m, M_DONTWAIT); 3647 m_clget(m, M_DONTWAIT);
3648 if ((m->m_flags & M_EXT) == 0) { 3648 if ((m->m_flags & M_EXT) == 0) {
3649 m_free(m); 3649 m_free(m);
3650 return NULL; 3650 return NULL;
3651 } 3651 }
3652 } 3652 }
3653 m->m_data += leading_len; 3653 m->m_data += leading_len;
3654 m->m_pkthdr.len = m->m_len = len; 3654 m->m_pkthdr.len = m->m_len = len;
3655 3655
3656 return m; 3656 return m;
3657} 3657}
3658 3658
3659static int 3659static int
3660wg_send_data_msg(struct wg_peer *wgp, struct wg_session *wgs, 3660wg_send_data_msg(struct wg_peer *wgp, struct wg_session *wgs,
3661 struct mbuf *m) 3661 struct mbuf *m)
3662{ 3662{
3663 struct wg_softc *wg = wgp->wgp_sc; 3663 struct wg_softc *wg = wgp->wgp_sc;
3664 int error; 3664 int error;
3665 size_t inner_len, padded_len, encrypted_len; 3665 size_t inner_len, padded_len, encrypted_len;
3666 char *padded_buf = NULL; 3666 char *padded_buf = NULL;
3667 size_t mlen; 3667 size_t mlen;
3668 struct wg_msg_data *wgmd; 3668 struct wg_msg_data *wgmd;
3669 bool free_padded_buf = false; 3669 bool free_padded_buf = false;
3670 struct mbuf *n; 3670 struct mbuf *n;
3671 size_t leading_len = max_linkhdr + sizeof(struct ip6_hdr) + 3671 size_t leading_len = max_linkhdr + sizeof(struct ip6_hdr) +
3672 sizeof(struct udphdr); 3672 sizeof(struct udphdr);
3673 3673
3674 mlen = m_length(m); 3674 mlen = m_length(m);
3675 inner_len = mlen; 3675 inner_len = mlen;
3676 padded_len = roundup(mlen, 16); 3676 padded_len = roundup(mlen, 16);
3677 encrypted_len = padded_len + WG_AUTHTAG_LEN; 3677 encrypted_len = padded_len + WG_AUTHTAG_LEN;
3678 WG_DLOG("inner=%lu, padded=%lu, encrypted_len=%lu\n", 3678 WG_DLOG("inner=%lu, padded=%lu, encrypted_len=%lu\n",
3679 inner_len, padded_len, encrypted_len); 3679 inner_len, padded_len, encrypted_len);
3680 if (mlen != 0) { 3680 if (mlen != 0) {
3681 bool success; 3681 bool success;
3682 success = m_ensure_contig(&m, padded_len); 3682 success = m_ensure_contig(&m, padded_len);
3683 if (success) { 3683 if (success) {
3684 padded_buf = mtod(m, char *); 3684 padded_buf = mtod(m, char *);
3685 } else { 3685 } else {
3686 padded_buf = kmem_intr_alloc(padded_len, KM_NOSLEEP); 3686 padded_buf = kmem_intr_alloc(padded_len, KM_NOSLEEP);
3687 if (padded_buf == NULL) { 3687 if (padded_buf == NULL) {
3688 error = ENOBUFS; 3688 error = ENOBUFS;
3689 goto end; 3689 goto end;
3690 } 3690 }
3691 free_padded_buf = true; 3691 free_padded_buf = true;
3692 m_copydata(m, 0, mlen, padded_buf); 3692 m_copydata(m, 0, mlen, padded_buf);
3693 } 3693 }
3694 memset(padded_buf + mlen, 0, padded_len - inner_len); 3694 memset(padded_buf + mlen, 0, padded_len - inner_len);
3695 } 3695 }
3696 3696
3697 n = wg_get_mbuf(leading_len, sizeof(*wgmd) + encrypted_len); 3697 n = wg_get_mbuf(leading_len, sizeof(*wgmd) + encrypted_len);
3698 if (n == NULL) { 3698 if (n == NULL) {
3699 error = ENOBUFS; 3699 error = ENOBUFS;
3700 goto end; 3700 goto end;
3701 } 3701 }
3702 KASSERT(n->m_len >= sizeof(*wgmd)); 3702 KASSERT(n->m_len >= sizeof(*wgmd));
3703 wgmd = mtod(n, struct wg_msg_data *); 3703 wgmd = mtod(n, struct wg_msg_data *);
3704 wg_fill_msg_data(wg, wgp, wgs, wgmd); 3704 wg_fill_msg_data(wg, wgp, wgs, wgmd);
3705 /* [W] 5.4.6: AEAD(Tm^send, Nm^send, P, e) */ 3705 /* [W] 5.4.6: AEAD(Tm^send, Nm^send, P, e) */
3706 wg_algo_aead_enc((char *)wgmd + sizeof(*wgmd), encrypted_len, 3706 wg_algo_aead_enc((char *)wgmd + sizeof(*wgmd), encrypted_len,
3707 wgs->wgs_tkey_send, wgmd->wgmd_counter, padded_buf, padded_len, 3707 wgs->wgs_tkey_send, wgmd->wgmd_counter, padded_buf, padded_len,
3708 NULL, 0); 3708 NULL, 0);
3709 3709
3710 error = wg->wg_ops->send_data_msg(wgp, n); 3710 error = wg->wg_ops->send_data_msg(wgp, n);
3711 if (error == 0) { 3711 if (error == 0) {
3712 struct ifnet *ifp = &wg->wg_if; 3712 struct ifnet *ifp = &wg->wg_if;
3713 if_statadd(ifp, if_obytes, mlen); 3713 if_statadd(ifp, if_obytes, mlen);
3714 if_statinc(ifp, if_opackets); 3714 if_statinc(ifp, if_opackets);
3715 if (wgs->wgs_is_initiator && 3715 if (wgs->wgs_is_initiator &&
3716 wgs->wgs_time_last_data_sent == 0) { 3716 wgs->wgs_time_last_data_sent == 0) {
3717 /* 3717 /*
3718 * [W] 6.2 Transport Message Limits 3718 * [W] 6.2 Transport Message Limits
3719 * "if a peer is the initiator of a current secure 3719 * "if a peer is the initiator of a current secure
3720 * session, WireGuard will send a handshake initiation 3720 * session, WireGuard will send a handshake initiation
3721 * message to begin a new secure session if, after 3721 * message to begin a new secure session if, after
3722 * transmitting a transport data message, the current 3722 * transmitting a transport data message, the current
3723 * secure session is REKEY-AFTER-TIME seconds old," 3723 * secure session is REKEY-AFTER-TIME seconds old,"
3724 */ 3724 */
3725 wg_schedule_rekey_timer(wgp); 3725 wg_schedule_rekey_timer(wgp);
3726 } 3726 }
3727 wgs->wgs_time_last_data_sent = time_uptime; 3727 wgs->wgs_time_last_data_sent = time_uptime;
3728 if (wg_session_get_send_counter(wgs) >= 3728 if (wg_session_get_send_counter(wgs) >=
3729 wg_rekey_after_messages) { 3729 wg_rekey_after_messages) {
3730 /* 3730 /*
3731 * [W] 6.2 Transport Message Limits 3731 * [W] 6.2 Transport Message Limits
3732 * "WireGuard will try to create a new session, by 3732 * "WireGuard will try to create a new session, by
3733 * sending a handshake initiation message (section 3733 * sending a handshake initiation message (section
3734 * 5.4.2), after it has sent REKEY-AFTER-MESSAGES 3734 * 5.4.2), after it has sent REKEY-AFTER-MESSAGES
3735 * transport data messages..." 3735 * transport data messages..."
3736 */ 3736 */
3737 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3737 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3738 } 3738 }
3739 } 3739 }
3740end: 3740end:
3741 m_freem(m); 3741 m_freem(m);
3742 if (free_padded_buf) 3742 if (free_padded_buf)
3743 kmem_intr_free(padded_buf, padded_len); 3743 kmem_intr_free(padded_buf, padded_len);
3744 return error; 3744 return error;
3745} 3745}
3746 3746
3747static void 3747static void
3748wg_input(struct ifnet *ifp, struct mbuf *m, const int af) 3748wg_input(struct ifnet *ifp, struct mbuf *m, const int af)
3749{ 3749{
3750 pktqueue_t *pktq; 3750 pktqueue_t *pktq;
3751 size_t pktlen; 3751 size_t pktlen;
3752 3752
3753 KASSERT(af == AF_INET || af == AF_INET6); 3753 KASSERT(af == AF_INET || af == AF_INET6);
3754 3754
3755 WG_TRACE(""); 3755 WG_TRACE("");
3756 3756
3757 m_set_rcvif(m, ifp); 3757 m_set_rcvif(m, ifp);
3758 pktlen = m->m_pkthdr.len; 3758 pktlen = m->m_pkthdr.len;
3759 3759
3760 bpf_mtap_af(ifp, af, m, BPF_D_IN); 3760 bpf_mtap_af(ifp, af, m, BPF_D_IN);
3761 3761
3762 switch (af) { 3762 switch (af) {
3763 case AF_INET: 3763 case AF_INET:
3764 pktq = ip_pktq; 3764 pktq = ip_pktq;
3765 break; 3765 break;
3766#ifdef INET6 3766#ifdef INET6
3767 case AF_INET6: 3767 case AF_INET6:
3768 pktq = ip6_pktq; 3768 pktq = ip6_pktq;
3769 break; 3769 break;
3770#endif 3770#endif
3771 default: 3771 default:
3772 panic("invalid af=%d", af); 3772 panic("invalid af=%d", af);
3773 } 3773 }
3774 3774
3775 const u_int h = curcpu()->ci_index; 3775 const u_int h = curcpu()->ci_index;
3776 if (__predict_true(pktq_enqueue(pktq, m, h))) { 3776 if (__predict_true(pktq_enqueue(pktq, m, h))) {
3777 if_statadd(ifp, if_ibytes, pktlen); 3777 if_statadd(ifp, if_ibytes, pktlen);
3778 if_statinc(ifp, if_ipackets); 3778 if_statinc(ifp, if_ipackets);
3779 } else { 3779 } else {
3780 m_freem(m); 3780 m_freem(m);
3781 } 3781 }
3782} 3782}
3783 3783
3784static void 3784static void
3785wg_calc_pubkey(uint8_t pubkey[WG_STATIC_KEY_LEN], 3785wg_calc_pubkey(uint8_t pubkey[WG_STATIC_KEY_LEN],
3786 const uint8_t privkey[WG_STATIC_KEY_LEN]) 3786 const uint8_t privkey[WG_STATIC_KEY_LEN])
3787{ 3787{
3788 3788
3789 crypto_scalarmult_base(pubkey, privkey); 3789 crypto_scalarmult_base(pubkey, privkey);
3790} 3790}
3791 3791
3792static int 3792static int
3793wg_rtable_add_route(struct wg_softc *wg, struct wg_allowedip *wga) 3793wg_rtable_add_route(struct wg_softc *wg, struct wg_allowedip *wga)
3794{ 3794{
3795 struct radix_node_head *rnh; 3795 struct radix_node_head *rnh;
3796 struct radix_node *rn; 3796 struct radix_node *rn;
3797 int error = 0; 3797 int error = 0;
3798 3798
3799 rw_enter(wg->wg_rwlock, RW_WRITER); 3799 rw_enter(wg->wg_rwlock, RW_WRITER);
3800 rnh = wg_rnh(wg, wga->wga_family); 3800 rnh = wg_rnh(wg, wga->wga_family);
3801 KASSERT(rnh != NULL); 3801 KASSERT(rnh != NULL);
3802 rn = rnh->rnh_addaddr(&wga->wga_sa_addr, &wga->wga_sa_mask, rnh, 3802 rn = rnh->rnh_addaddr(&wga->wga_sa_addr, &wga->wga_sa_mask, rnh,
3803 wga->wga_nodes); 3803 wga->wga_nodes);
3804 rw_exit(wg->wg_rwlock); 3804 rw_exit(wg->wg_rwlock);
3805 3805
3806 if (rn == NULL) 3806 if (rn == NULL)
3807 error = EEXIST; 3807 error = EEXIST;
3808 3808
3809 return error; 3809 return error;
3810} 3810}
3811 3811
3812static int 3812static int
3813wg_handle_prop_peer(struct wg_softc *wg, prop_dictionary_t peer, 3813wg_handle_prop_peer(struct wg_softc *wg, prop_dictionary_t peer,
3814 struct wg_peer **wgpp) 3814 struct wg_peer **wgpp)
3815{ 3815{
3816 int error = 0; 3816 int error = 0;
3817 const void *pubkey; 3817 const void *pubkey;
3818 size_t pubkey_len; 3818 size_t pubkey_len;
3819 const void *psk; 3819 const void *psk;
3820 size_t psk_len; 3820 size_t psk_len;
3821 const char *name = NULL; 3821 const char *name = NULL;
3822 3822
3823 if (prop_dictionary_get_string(peer, "name", &name)) { 3823 if (prop_dictionary_get_string(peer, "name", &name)) {
3824 if (strlen(name) > WG_PEER_NAME_MAXLEN) { 3824 if (strlen(name) > WG_PEER_NAME_MAXLEN) {
3825 error = EINVAL; 3825 error = EINVAL;
3826 goto out; 3826 goto out;
3827 } 3827 }
3828 } 3828 }
3829 3829
3830 if (!prop_dictionary_get_data(peer, "public_key", 3830 if (!prop_dictionary_get_data(peer, "public_key",
3831 &pubkey, &pubkey_len)) { 3831 &pubkey, &pubkey_len)) {
3832 error = EINVAL; 3832 error = EINVAL;
3833 goto out; 3833 goto out;
3834 } 3834 }
3835#ifdef WG_DEBUG_DUMP 3835#ifdef WG_DEBUG_DUMP
3836 log(LOG_DEBUG, "pubkey=%p, pubkey_len=%lu\n", pubkey, pubkey_len); 3836 log(LOG_DEBUG, "pubkey=%p, pubkey_len=%lu\n", pubkey, pubkey_len);
3837 for (int _i = 0; _i < pubkey_len; _i++) 3837 for (int _i = 0; _i < pubkey_len; _i++)
3838 log(LOG_DEBUG, "%c", ((const char *)pubkey)[_i]); 3838 log(LOG_DEBUG, "%c", ((const char *)pubkey)[_i]);
3839 log(LOG_DEBUG, "\n"); 3839 log(LOG_DEBUG, "\n");
3840#endif 3840#endif
3841 3841
3842 struct wg_peer *wgp = wg_alloc_peer(wg); 3842 struct wg_peer *wgp = wg_alloc_peer(wg);
3843 memcpy(wgp->wgp_pubkey, pubkey, sizeof(wgp->wgp_pubkey)); 3843 memcpy(wgp->wgp_pubkey, pubkey, sizeof(wgp->wgp_pubkey));
3844 if (name != NULL) 3844 if (name != NULL)
3845 strncpy(wgp->wgp_name, name, sizeof(wgp->wgp_name)); 3845 strncpy(wgp->wgp_name, name, sizeof(wgp->wgp_name));
3846 3846
3847 if (prop_dictionary_get_data(peer, "preshared_key", &psk, &psk_len)) { 3847 if (prop_dictionary_get_data(peer, "preshared_key", &psk, &psk_len)) {
3848 if (psk_len != sizeof(wgp->wgp_psk)) { 3848 if (psk_len != sizeof(wgp->wgp_psk)) {
3849 error = EINVAL; 3849 error = EINVAL;
3850 goto out; 3850 goto out;
3851 } 3851 }
3852 memcpy(wgp->wgp_psk, psk, sizeof(wgp->wgp_psk)); 3852 memcpy(wgp->wgp_psk, psk, sizeof(wgp->wgp_psk));
3853 } 3853 }
3854 3854
3855 struct sockaddr_storage sockaddr; 3855 struct sockaddr_storage sockaddr;
3856 const void *addr; 3856 const void *addr;
3857 size_t addr_len; 3857 size_t addr_len;
3858 3858
3859 if (!prop_dictionary_get_data(peer, "endpoint", &addr, &addr_len)) 3859 if (!prop_dictionary_get_data(peer, "endpoint", &addr, &addr_len))
3860 goto skip_endpoint; 3860 goto skip_endpoint;
3861 memcpy(&sockaddr, addr, addr_len); 3861 memcpy(&sockaddr, addr, addr_len);
3862 switch (sockaddr.ss_family) { 3862 switch (sockaddr.ss_family) {
3863 case AF_INET: { 3863 case AF_INET: {
3864 struct sockaddr_in sin; 3864 struct sockaddr_in sin;
3865 sockaddr_copy(sintosa(&sin), sizeof(sin), 3865 sockaddr_copy(sintosa(&sin), sizeof(sin),
3866 (const struct sockaddr *)&sockaddr); 3866 (const struct sockaddr *)&sockaddr);
3867 sockaddr_copy(sintosa(&wgp->wgp_sin), 3867 sockaddr_copy(sintosa(&wgp->wgp_sin),
3868 sizeof(wgp->wgp_sin), (const struct sockaddr *)&sockaddr); 3868 sizeof(wgp->wgp_sin), (const struct sockaddr *)&sockaddr);
3869 char addrstr[128]; 3869 char addrstr[128];
3870 sockaddr_format(sintosa(&sin), addrstr, sizeof(addrstr)); 3870 sockaddr_format(sintosa(&sin), addrstr, sizeof(addrstr));
3871 WG_DLOG("addr=%s\n", addrstr); 3871 WG_DLOG("addr=%s\n", addrstr);
3872 break; 3872 break;
3873 } 3873 }
3874#ifdef INET6 3874#ifdef INET6
3875 case AF_INET6: { 3875 case AF_INET6: {
3876 struct sockaddr_in6 sin6; 3876 struct sockaddr_in6 sin6;
3877 char addrstr[128]; 3877 char addrstr[128];
3878 sockaddr_copy(sintosa(&sin6), sizeof(sin6), 3878 sockaddr_copy(sintosa(&sin6), sizeof(sin6),
3879 (const struct sockaddr *)&sockaddr); 3879 (const struct sockaddr *)&sockaddr);
3880 sockaddr_format(sintosa(&sin6), addrstr, sizeof(addrstr)); 3880 sockaddr_format(sintosa(&sin6), addrstr, sizeof(addrstr));
3881 WG_DLOG("addr=%s\n", addrstr); 3881 WG_DLOG("addr=%s\n", addrstr);
3882 sockaddr_copy(sin6tosa(&wgp->wgp_sin6), 3882 sockaddr_copy(sin6tosa(&wgp->wgp_sin6),
3883 sizeof(wgp->wgp_sin6), (const struct sockaddr *)&sockaddr); 3883 sizeof(wgp->wgp_sin6), (const struct sockaddr *)&sockaddr);
3884 break; 3884 break;
3885 } 3885 }
3886#endif 3886#endif
3887 default: 3887 default:
3888 break; 3888 break;
3889 } 3889 }
3890 wgp->wgp_endpoint_available = true; 3890 wgp->wgp_endpoint_available = true;
3891 3891
3892 prop_array_t allowedips; 3892 prop_array_t allowedips;
3893skip_endpoint: 3893skip_endpoint:
3894 allowedips = prop_dictionary_get(peer, "allowedips"); 3894 allowedips = prop_dictionary_get(peer, "allowedips");
3895 if (allowedips == NULL) 3895 if (allowedips == NULL)
3896 goto skip; 3896 goto skip;
3897 3897
3898 prop_object_iterator_t _it = prop_array_iterator(allowedips); 3898 prop_object_iterator_t _it = prop_array_iterator(allowedips);
3899 prop_dictionary_t prop_allowedip; 3899 prop_dictionary_t prop_allowedip;
3900 int j = 0; 3900 int j = 0;
3901 while ((prop_allowedip = prop_object_iterator_next(_it)) != NULL) { 3901 while ((prop_allowedip = prop_object_iterator_next(_it)) != NULL) {
3902 struct wg_allowedip *wga = &wgp->wgp_allowedips[j]; 3902 struct wg_allowedip *wga = &wgp->wgp_allowedips[j];
3903 3903
3904 if (!prop_dictionary_get_int(prop_allowedip, "family", 3904 if (!prop_dictionary_get_int(prop_allowedip, "family",
3905 &wga->wga_family)) 3905 &wga->wga_family))
3906 continue; 3906 continue;
3907 if (!prop_dictionary_get_data(prop_allowedip, "ip", 3907 if (!prop_dictionary_get_data(prop_allowedip, "ip",
3908 &addr, &addr_len)) 3908 &addr, &addr_len))
3909 continue; 3909 continue;
3910 if (!prop_dictionary_get_uint8(prop_allowedip, "cidr", 3910 if (!prop_dictionary_get_uint8(prop_allowedip, "cidr",
3911 &wga->wga_cidr)) 3911 &wga->wga_cidr))
3912 continue; 3912 continue;
3913 3913
3914 switch (wga->wga_family) { 3914 switch (wga->wga_family) {
3915 case AF_INET: { 3915 case AF_INET: {
3916 struct sockaddr_in sin; 3916 struct sockaddr_in sin;
3917 char addrstr[128]; 3917 char addrstr[128];
3918 struct in_addr mask; 3918 struct in_addr mask;
3919 struct sockaddr_in sin_mask; 3919 struct sockaddr_in sin_mask;
3920 3920
3921 if (addr_len != sizeof(struct in_addr)) 3921 if (addr_len != sizeof(struct in_addr))
3922 return EINVAL; 3922 return EINVAL;
3923 memcpy(&wga->wga_addr4, addr, addr_len); 3923 memcpy(&wga->wga_addr4, addr, addr_len);
3924 3924
3925 sockaddr_in_init(&sin, (const struct in_addr *)addr, 3925 sockaddr_in_init(&sin, (const struct in_addr *)addr,
3926 0); 3926 0);
3927 sockaddr_copy(&wga->wga_sa_addr, 3927 sockaddr_copy(&wga->wga_sa_addr,
3928 sizeof(sin), sintosa(&sin)); 3928 sizeof(sin), sintosa(&sin));
3929 3929
3930 sockaddr_format(sintosa(&sin), 3930 sockaddr_format(sintosa(&sin),
3931 addrstr, sizeof(addrstr)); 3931 addrstr, sizeof(addrstr));
3932 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr); 3932 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr);
3933 3933
3934 in_len2mask(&mask, wga->wga_cidr); 3934 in_len2mask(&mask, wga->wga_cidr);
3935 sockaddr_in_init(&sin_mask, &mask, 0); 3935 sockaddr_in_init(&sin_mask, &mask, 0);
3936 sockaddr_copy(&wga->wga_sa_mask, 3936 sockaddr_copy(&wga->wga_sa_mask,
3937 sizeof(sin_mask), sintosa(&sin_mask)); 3937 sizeof(sin_mask), sintosa(&sin_mask));
3938 3938
3939 break; 3939 break;
3940 } 3940 }
3941#ifdef INET6 3941#ifdef INET6
3942 case AF_INET6: { 3942 case AF_INET6: {
3943 struct sockaddr_in6 sin6; 3943 struct sockaddr_in6 sin6;
3944 char addrstr[128]; 3944 char addrstr[128];
3945 struct in6_addr mask; 3945 struct in6_addr mask;
3946 struct sockaddr_in6 sin6_mask; 3946 struct sockaddr_in6 sin6_mask;
3947 3947
3948 if (addr_len != sizeof(struct in6_addr)) 3948 if (addr_len != sizeof(struct in6_addr))
3949 return EINVAL; 3949 return EINVAL;
3950 memcpy(&wga->wga_addr6, addr, addr_len); 3950 memcpy(&wga->wga_addr6, addr, addr_len);
3951 3951
3952 sockaddr_in6_init(&sin6, (const struct in6_addr *)addr, 3952 sockaddr_in6_init(&sin6, (const struct in6_addr *)addr,
3953 0, 0, 0); 3953 0, 0, 0);
3954 sockaddr_copy(&wga->wga_sa_addr, 3954 sockaddr_copy(&wga->wga_sa_addr,
3955 sizeof(sin6), sin6tosa(&sin6)); 3955 sizeof(sin6), sin6tosa(&sin6));
3956 3956
3957 sockaddr_format(sin6tosa(&sin6), 3957 sockaddr_format(sin6tosa(&sin6),
3958 addrstr, sizeof(addrstr)); 3958 addrstr, sizeof(addrstr));
3959 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr); 3959 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr);
3960 3960
3961 in6_prefixlen2mask(&mask, wga->wga_cidr); 3961 in6_prefixlen2mask(&mask, wga->wga_cidr);
3962 sockaddr_in6_init(&sin6_mask, &mask, 0, 0, 0); 3962 sockaddr_in6_init(&sin6_mask, &mask, 0, 0, 0);
3963 sockaddr_copy(&wga->wga_sa_mask, 3963 sockaddr_copy(&wga->wga_sa_mask,
3964 sizeof(sin6_mask), sin6tosa(&sin6_mask)); 3964 sizeof(sin6_mask), sin6tosa(&sin6_mask));
3965 3965
3966 break; 3966 break;
3967 } 3967 }
3968#endif 3968#endif
3969 default: 3969 default:
3970 error = EINVAL; 3970 error = EINVAL;
3971 goto out; 3971 goto out;
3972 } 3972 }
3973 wga->wga_peer = wgp; 3973 wga->wga_peer = wgp;
3974 3974
3975 error = wg_rtable_add_route(wg, wga); 3975 error = wg_rtable_add_route(wg, wga);
3976 if (error != 0) 3976 if (error != 0)
3977 goto out; 3977 goto out;
3978 3978
3979 j++; 3979 j++;
3980 } 3980 }
3981 wgp->wgp_n_allowedips = j; 3981 wgp->wgp_n_allowedips = j;
3982skip: 3982skip:
3983 *wgpp = wgp; 3983 *wgpp = wgp;
3984out: 3984out:
3985 return error; 3985 return error;
3986} 3986}
3987 3987
3988static int 3988static int
3989wg_alloc_prop_buf(char **_buf, struct ifdrv *ifd) 3989wg_alloc_prop_buf(char **_buf, struct ifdrv *ifd)
3990{ 3990{
3991 int error; 3991 int error;
3992 char *buf; 3992 char *buf;
3993 3993
3994 WG_DLOG("buf=%p, len=%lu\n", ifd->ifd_data, ifd->ifd_len); 3994 WG_DLOG("buf=%p, len=%lu\n", ifd->ifd_data, ifd->ifd_len);
3995 buf = kmem_alloc(ifd->ifd_len + 1, KM_SLEEP); 3995 buf = kmem_alloc(ifd->ifd_len + 1, KM_SLEEP);
3996 error = copyin(ifd->ifd_data, buf, ifd->ifd_len); 3996 error = copyin(ifd->ifd_data, buf, ifd->ifd_len);
3997 if (error != 0) 3997 if (error != 0)
3998 return error; 3998 return error;
3999 buf[ifd->ifd_len] = '\0'; 3999 buf[ifd->ifd_len] = '\0';
4000#ifdef WG_DEBUG_DUMP 4000#ifdef WG_DEBUG_DUMP
4001 for (int i = 0; i < ifd->ifd_len; i++) 4001 for (int i = 0; i < ifd->ifd_len; i++)
4002 log(LOG_DEBUG, "%c", buf[i]); 4002 log(LOG_DEBUG, "%c", buf[i]);
4003 log(LOG_DEBUG, "\n"); 4003 log(LOG_DEBUG, "\n");
4004#endif 4004#endif
4005 *_buf = buf; 4005 *_buf = buf;
4006 return 0; 4006 return 0;
4007} 4007}
4008 4008
4009static int 4009static int
4010wg_ioctl_set_private_key(struct wg_softc *wg, struct ifdrv *ifd) 4010wg_ioctl_set_private_key(struct wg_softc *wg, struct ifdrv *ifd)
4011{ 4011{
4012 int error; 4012 int error;
4013 prop_dictionary_t prop_dict; 4013 prop_dictionary_t prop_dict;
4014 char *buf = NULL; 4014 char *buf = NULL;
4015 const void *privkey; 4015 const void *privkey;
4016 size_t privkey_len; 4016 size_t privkey_len;
4017 4017
4018 error = wg_alloc_prop_buf(&buf, ifd); 4018 error = wg_alloc_prop_buf(&buf, ifd);
4019 if (error != 0) 4019 if (error != 0)
4020 return error; 4020 return error;
4021 error = EINVAL; 4021 error = EINVAL;
4022 prop_dict = prop_dictionary_internalize(buf); 4022 prop_dict = prop_dictionary_internalize(buf);
4023 if (prop_dict == NULL) 4023 if (prop_dict == NULL)
4024 goto out; 4024 goto out;
4025 if (!prop_dictionary_get_data(prop_dict, "private_key", 4025 if (!prop_dictionary_get_data(prop_dict, "private_key",
4026 &privkey, &privkey_len)) 4026 &privkey, &privkey_len))
4027 goto out; 4027 goto out;
4028#ifdef WG_DEBUG_DUMP 4028#ifdef WG_DEBUG_DUMP
4029 log(LOG_DEBUG, "privkey=%p, privkey_len=%lu\n", privkey, privkey_len); 4029 log(LOG_DEBUG, "privkey=%p, privkey_len=%lu\n", privkey, privkey_len);
4030 for (int i = 0; i < privkey_len; i++) 4030 for (int i = 0; i < privkey_len; i++)
4031 log(LOG_DEBUG, "%c", ((const char *)privkey)[i]); 4031 log(LOG_DEBUG, "%c", ((const char *)privkey)[i]);
4032 log(LOG_DEBUG, "\n"); 4032 log(LOG_DEBUG, "\n");
4033#endif 4033#endif
4034 if (privkey_len != WG_STATIC_KEY_LEN) 4034 if (privkey_len != WG_STATIC_KEY_LEN)
4035 goto out; 4035 goto out;
4036 memcpy(wg->wg_privkey, privkey, WG_STATIC_KEY_LEN); 4036 memcpy(wg->wg_privkey, privkey, WG_STATIC_KEY_LEN);
4037 wg_calc_pubkey(wg->wg_pubkey, wg->wg_privkey); 4037 wg_calc_pubkey(wg->wg_pubkey, wg->wg_privkey);
4038 error = 0; 4038 error = 0;
4039 4039
4040out: 4040out:
4041 kmem_free(buf, ifd->ifd_len + 1); 4041 kmem_free(buf, ifd->ifd_len + 1);
4042 return error; 4042 return error;
4043} 4043}
4044 4044
4045static int 4045static int
4046wg_ioctl_set_listen_port(struct wg_softc *wg, struct ifdrv *ifd) 4046wg_ioctl_set_listen_port(struct wg_softc *wg, struct ifdrv *ifd)
4047{ 4047{
4048 int error; 4048 int error;
4049 prop_dictionary_t prop_dict; 4049 prop_dictionary_t prop_dict;
4050 char *buf = NULL; 4050 char *buf = NULL;
4051 uint16_t port; 4051 uint16_t port;
4052 4052
4053 error = wg_alloc_prop_buf(&buf, ifd); 4053 error = wg_alloc_prop_buf(&buf, ifd);
4054 if (error != 0) 4054 if (error != 0)
4055 return error; 4055 return error;
4056 error = EINVAL; 4056 error = EINVAL;
4057 prop_dict = prop_dictionary_internalize(buf); 4057 prop_dict = prop_dictionary_internalize(buf);
4058 if (prop_dict == NULL) 4058 if (prop_dict == NULL)
4059 goto out; 4059 goto out;
4060 if (!prop_dictionary_get_uint16(prop_dict, "listen_port", &port)) 4060 if (!prop_dictionary_get_uint16(prop_dict, "listen_port", &port))
4061 goto out; 4061 goto out;
4062 4062
4063 error = wg->wg_ops->bind_port(wg, (uint16_t)port); 4063 error = wg->wg_ops->bind_port(wg, (uint16_t)port);
4064 4064
4065out: 4065out:
4066 kmem_free(buf, ifd->ifd_len + 1); 4066 kmem_free(buf, ifd->ifd_len + 1);
4067 return error; 4067 return error;
4068} 4068}
4069 4069
4070static int 4070static int
4071wg_ioctl_add_peer(struct wg_softc *wg, struct ifdrv *ifd) 4071wg_ioctl_add_peer(struct wg_softc *wg, struct ifdrv *ifd)
4072{ 4072{
4073 int error; 4073 int error;
4074 prop_dictionary_t prop_dict; 4074 prop_dictionary_t prop_dict;
4075 char *buf = NULL; 4075 char *buf = NULL;
4076 struct wg_peer *wgp = NULL; 4076 struct wg_peer *wgp = NULL;
4077 4077
4078 error = wg_alloc_prop_buf(&buf, ifd); 4078 error = wg_alloc_prop_buf(&buf, ifd);
4079 if (error != 0) 4079 if (error != 0)
4080 return error; 4080 return error;
4081 error = EINVAL; 4081 error = EINVAL;
4082 prop_dict = prop_dictionary_internalize(buf); 4082 prop_dict = prop_dictionary_internalize(buf);
4083 if (prop_dict == NULL) 4083 if (prop_dict == NULL)
4084 goto out; 4084 goto out;
4085 4085
4086 error = wg_handle_prop_peer(wg, prop_dict, &wgp); 4086 error = wg_handle_prop_peer(wg, prop_dict, &wgp);
4087 if (error != 0) 4087 if (error != 0)
4088 goto out; 4088 goto out;
4089 4089
4090 mutex_enter(wg->wg_lock); 4090 mutex_enter(wg->wg_lock);
4091 WG_PEER_WRITER_INSERT_HEAD(wgp, wg); 4091 WG_PEER_WRITER_INSERT_HEAD(wgp, wg);
4092 wg->wg_npeers++; 4092 wg->wg_npeers++;
4093 mutex_exit(wg->wg_lock); 4093 mutex_exit(wg->wg_lock);
4094 4094
4095out: 4095out:
4096 kmem_free(buf, ifd->ifd_len + 1); 4096 kmem_free(buf, ifd->ifd_len + 1);
4097 return error; 4097 return error;
4098} 4098}
4099 4099
4100static int 4100static int
4101wg_ioctl_delete_peer(struct wg_softc *wg, struct ifdrv *ifd) 4101wg_ioctl_delete_peer(struct wg_softc *wg, struct ifdrv *ifd)
4102{ 4102{
4103 int error; 4103 int error;
4104 prop_dictionary_t prop_dict; 4104 prop_dictionary_t prop_dict;
4105 char *buf = NULL; 4105 char *buf = NULL;
4106 const char *name; 4106 const char *name;
4107 4107
4108 error = wg_alloc_prop_buf(&buf, ifd); 4108 error = wg_alloc_prop_buf(&buf, ifd);
4109 if (error != 0) 4109 if (error != 0)
4110 return error; 4110 return error;
4111 error = EINVAL; 4111 error = EINVAL;
4112 prop_dict = prop_dictionary_internalize(buf); 4112 prop_dict = prop_dictionary_internalize(buf);
4113 if (prop_dict == NULL) 4113 if (prop_dict == NULL)
4114 goto out; 4114 goto out;
4115 4115
4116 if (!prop_dictionary_get_string(prop_dict, "name", &name)) 4116 if (!prop_dictionary_get_string(prop_dict, "name", &name))
4117 goto out; 4117 goto out;
4118 if (strlen(name) > WG_PEER_NAME_MAXLEN) 4118 if (strlen(name) > WG_PEER_NAME_MAXLEN)
4119 goto out; 4119 goto out;
4120 4120
4121 error = wg_destroy_peer_name(wg, name); 4121 error = wg_destroy_peer_name(wg, name);
4122out: 4122out:
4123 kmem_free(buf, ifd->ifd_len + 1); 4123 kmem_free(buf, ifd->ifd_len + 1);
4124 return error; 4124 return error;
4125} 4125}
4126 4126
4127static int 4127static int
4128wg_ioctl_get(struct wg_softc *wg, struct ifdrv *ifd) 4128wg_ioctl_get(struct wg_softc *wg, struct ifdrv *ifd)
4129{ 4129{
4130 int error = ENOMEM; 4130 int error = ENOMEM;
4131 prop_dictionary_t prop_dict; 4131 prop_dictionary_t prop_dict;
4132 prop_array_t peers = NULL; 4132 prop_array_t peers = NULL;
4133 char *buf; 4133 char *buf;
4134 struct wg_peer *wgp; 4134 struct wg_peer *wgp;
4135 int s, i; 4135 int s, i;
4136 4136
4137 prop_dict = prop_dictionary_create(); 4137 prop_dict = prop_dictionary_create();
4138 if (prop_dict == NULL) 4138 if (prop_dict == NULL)
4139 goto error; 4139 goto error;
4140 4140
4141 if (!prop_dictionary_set_data(prop_dict, "private_key", wg->wg_privkey, 4141 if (!prop_dictionary_set_data(prop_dict, "private_key", wg->wg_privkey,
4142 WG_STATIC_KEY_LEN)) 4142 WG_STATIC_KEY_LEN))
4143 goto error; 4143 goto error;
4144 4144
4145 if (wg->wg_listen_port != 0) { 4145 if (wg->wg_listen_port != 0) {
4146 if (!prop_dictionary_set_uint16(prop_dict, "listen_port", 4146 if (!prop_dictionary_set_uint16(prop_dict, "listen_port",
4147 wg->wg_listen_port)) 4147 wg->wg_listen_port))
4148 goto error; 4148 goto error;
4149 } 4149 }
4150 4150
4151 if (wg->wg_npeers == 0) 4151 if (wg->wg_npeers == 0)
4152 goto skip_peers; 4152 goto skip_peers;
4153 4153
4154 peers = prop_array_create(); 4154 peers = prop_array_create();
4155 if (peers == NULL) 4155 if (peers == NULL)
4156 goto error; 4156 goto error;
4157 4157
4158 s = pserialize_read_enter(); 4158 s = pserialize_read_enter();
4159 i = 0; 4159 i = 0;
4160 WG_PEER_READER_FOREACH(wgp, wg) { 4160 WG_PEER_READER_FOREACH(wgp, wg) {
4161 struct psref psref; 4161 struct psref psref;
4162 prop_dictionary_t prop_peer; 4162 prop_dictionary_t prop_peer;
4163 4163
4164 wg_get_peer(wgp, &psref); 4164 wg_get_peer(wgp, &psref);
4165 pserialize_read_exit(s); 4165 pserialize_read_exit(s);
4166 4166
4167 prop_peer = prop_dictionary_create(); 4167 prop_peer = prop_dictionary_create();
4168 if (prop_peer == NULL) 4168 if (prop_peer == NULL)
4169 goto next; 4169 goto next;
4170 4170
4171 if (strlen(wgp->wgp_name) > 0) { 4171 if (strlen(wgp->wgp_name) > 0) {
4172 if (!prop_dictionary_set_string(prop_peer, "name", 4172 if (!prop_dictionary_set_string(prop_peer, "name",
4173 wgp->wgp_name)) 4173 wgp->wgp_name))
4174 goto next; 4174 goto next;
4175 } 4175 }
4176 4176
4177 if (!prop_dictionary_set_data(prop_peer, "public_key", 4177 if (!prop_dictionary_set_data(prop_peer, "public_key",
4178 wgp->wgp_pubkey, sizeof(wgp->wgp_pubkey))) 4178 wgp->wgp_pubkey, sizeof(wgp->wgp_pubkey)))
4179 goto next; 4179 goto next;
4180 4180
4181 uint8_t psk_zero[WG_PRESHARED_KEY_LEN] = {0}; 4181 uint8_t psk_zero[WG_PRESHARED_KEY_LEN] = {0};
4182 if (!consttime_memequal(wgp->wgp_psk, psk_zero, 4182 if (!consttime_memequal(wgp->wgp_psk, psk_zero,
4183 sizeof(wgp->wgp_psk))) { 4183 sizeof(wgp->wgp_psk))) {
4184 if (!prop_dictionary_set_data(prop_peer, 4184 if (!prop_dictionary_set_data(prop_peer,
4185 "preshared_key", 4185 "preshared_key",
4186 wgp->wgp_psk, sizeof(wgp->wgp_psk))) 4186 wgp->wgp_psk, sizeof(wgp->wgp_psk)))
4187 goto next; 4187 goto next;
4188 } 4188 }
4189 4189
4190 switch (wgp->wgp_sa.sa_family) { 4190 switch (wgp->wgp_sa.sa_family) {
4191 case AF_INET: 4191 case AF_INET:
4192 if (!prop_dictionary_set_data(prop_peer, "endpoint", 4192 if (!prop_dictionary_set_data(prop_peer, "endpoint",
4193 &wgp->wgp_sin, sizeof(wgp->wgp_sin))) 4193 &wgp->wgp_sin, sizeof(wgp->wgp_sin)))
4194 goto next; 4194 goto next;
4195 break; 4195 break;
4196#ifdef INET6 4196#ifdef INET6
4197 case AF_INET6: 4197 case AF_INET6:
4198 if (!prop_dictionary_set_data(prop_peer, "endpoint", 4198 if (!prop_dictionary_set_data(prop_peer, "endpoint",
4199 &wgp->wgp_sin6, sizeof(wgp->wgp_sin6))) 4199 &wgp->wgp_sin6, sizeof(wgp->wgp_sin6)))
4200 goto next; 4200 goto next;
4201 break; 4201 break;
4202#endif 4202#endif
4203 } 4203 }
4204 4204
4205 const struct timespec *t = &wgp->wgp_last_handshake_time; 4205 const struct timespec *t = &wgp->wgp_last_handshake_time;
4206 4206
4207 if (!prop_dictionary_set_uint64(prop_peer, 4207 if (!prop_dictionary_set_uint64(prop_peer,
4208 "last_handshake_time_sec", t->tv_sec)) 4208 "last_handshake_time_sec", t->tv_sec))
4209 goto next; 4209 goto next;
4210 if (!prop_dictionary_set_uint32(prop_peer, 4210 if (!prop_dictionary_set_uint32(prop_peer,
4211 "last_handshake_time_nsec", t->tv_nsec)) 4211 "last_handshake_time_nsec", t->tv_nsec))
4212 goto next; 4212 goto next;
4213 4213
4214 if (wgp->wgp_n_allowedips == 0) 4214 if (wgp->wgp_n_allowedips == 0)
4215 goto skip_allowedips; 4215 goto skip_allowedips;
4216 4216
4217 prop_array_t allowedips = prop_array_create(); 4217 prop_array_t allowedips = prop_array_create();
4218 if (allowedips == NULL) 4218 if (allowedips == NULL)
4219 goto next; 4219 goto next;
4220 for (int j = 0; j < wgp->wgp_n_allowedips; j++) { 4220 for (int j = 0; j < wgp->wgp_n_allowedips; j++) {
4221 struct wg_allowedip *wga = &wgp->wgp_allowedips[j]; 4221 struct wg_allowedip *wga = &wgp->wgp_allowedips[j];
4222 prop_dictionary_t prop_allowedip; 4222 prop_dictionary_t prop_allowedip;
4223 4223
4224 prop_allowedip = prop_dictionary_create(); 4224 prop_allowedip = prop_dictionary_create();
4225 if (prop_allowedip == NULL) 4225 if (prop_allowedip == NULL)
4226 break; 4226 break;
4227 4227
4228 if (!prop_dictionary_set_int(prop_allowedip, "family", 4228 if (!prop_dictionary_set_int(prop_allowedip, "family",
4229 wga->wga_family)) 4229 wga->wga_family))
4230 goto _next; 4230 goto _next;
4231 if (!prop_dictionary_set_uint8(prop_allowedip, "cidr", 4231 if (!prop_dictionary_set_uint8(prop_allowedip, "cidr",
4232 wga->wga_cidr)) 4232 wga->wga_cidr))
4233 goto _next; 4233 goto _next;
4234 4234
4235 switch (wga->wga_family) { 4235 switch (wga->wga_family) {
4236 case AF_INET: 4236 case AF_INET:
4237 if (!prop_dictionary_set_data(prop_allowedip, 4237 if (!prop_dictionary_set_data(prop_allowedip,
4238 "ip", &wga->wga_addr4, 4238 "ip", &wga->wga_addr4,
4239 sizeof(wga->wga_addr4))) 4239 sizeof(wga->wga_addr4)))
4240 goto _next; 4240 goto _next;
4241 break; 4241 break;
4242#ifdef INET6 4242#ifdef INET6
4243 case AF_INET6: 4243 case AF_INET6:
4244 if (!prop_dictionary_set_data(prop_allowedip, 4244 if (!prop_dictionary_set_data(prop_allowedip,
4245 "ip", &wga->wga_addr6, 4245 "ip", &wga->wga_addr6,
4246 sizeof(wga->wga_addr6))) 4246 sizeof(wga->wga_addr6)))
4247 goto _next; 4247 goto _next;
4248 break; 4248 break;
4249#endif 4249#endif
4250 default: 4250 default:
4251 break; 4251 break;
4252 } 4252 }
4253 prop_array_set(allowedips, j, prop_allowedip); 4253 prop_array_set(allowedips, j, prop_allowedip);
4254 _next: 4254 _next:
4255 prop_object_release(prop_allowedip); 4255 prop_object_release(prop_allowedip);
4256 } 4256 }
4257 prop_dictionary_set(prop_peer, "allowedips", allowedips); 4257 prop_dictionary_set(prop_peer, "allowedips", allowedips);
4258 prop_object_release(allowedips); 4258 prop_object_release(allowedips);
4259 4259
4260 skip_allowedips: 4260 skip_allowedips:
4261 4261
4262 prop_array_set(peers, i, prop_peer); 4262 prop_array_set(peers, i, prop_peer);
4263 next: 4263 next:
4264 if (prop_peer) 4264 if (prop_peer)
4265 prop_object_release(prop_peer); 4265 prop_object_release(prop_peer);
4266 i++; 4266 i++;
4267 4267
4268 s = pserialize_read_enter(); 4268 s = pserialize_read_enter();
4269 wg_put_peer(wgp, &psref); 4269 wg_put_peer(wgp, &psref);
4270 } 4270 }
4271 pserialize_read_exit(s); 4271 pserialize_read_exit(s);
4272 4272
4273 prop_dictionary_set(prop_dict, "peers", peers); 4273 prop_dictionary_set(prop_dict, "peers", peers);
4274 prop_object_release(peers); 4274 prop_object_release(peers);
4275 peers = NULL; 4275 peers = NULL;
4276 4276
4277skip_peers: 4277skip_peers:
4278 buf = prop_dictionary_externalize(prop_dict); 4278 buf = prop_dictionary_externalize(prop_dict);
4279 if (buf == NULL) 4279 if (buf == NULL)
4280 goto error; 4280 goto error;
4281 if (ifd->ifd_len < (strlen(buf) + 1)) { 4281 if (ifd->ifd_len < (strlen(buf) + 1)) {
4282 error = EINVAL; 4282 error = EINVAL;
4283 goto error; 4283 goto error;
4284 } 4284 }
4285 error = copyout(buf, ifd->ifd_data, strlen(buf) + 1); 4285 error = copyout(buf, ifd->ifd_data, strlen(buf) + 1);
4286 4286
4287 free(buf, 0); 4287 free(buf, 0);
4288error: 4288error:
4289 if (peers != NULL) 4289 if (peers != NULL)
4290 prop_object_release(peers); 4290 prop_object_release(peers);
4291 if (prop_dict != NULL) 4291 if (prop_dict != NULL)
4292 prop_object_release(prop_dict); 4292 prop_object_release(prop_dict);
4293 4293
4294 return error; 4294 return error;
4295} 4295}
4296 4296
4297static int 4297static int
4298wg_ioctl(struct ifnet *ifp, u_long cmd, void *data) 4298wg_ioctl(struct ifnet *ifp, u_long cmd, void *data)
4299{ 4299{
4300 struct wg_softc *wg = ifp->if_softc; 4300 struct wg_softc *wg = ifp->if_softc;
4301 struct ifreq *ifr = data; 4301 struct ifreq *ifr = data;
4302 struct ifaddr *ifa = data; 4302 struct ifaddr *ifa = data;
4303 struct ifdrv *ifd = data; 4303 struct ifdrv *ifd = data;
4304 int error = 0; 4304 int error = 0;
4305 4305
4306 switch (cmd) { 4306 switch (cmd) {
4307 case SIOCINITIFADDR: 4307 case SIOCINITIFADDR:
4308 if (ifa->ifa_addr->sa_family != AF_LINK && 4308 if (ifa->ifa_addr->sa_family != AF_LINK &&
4309 (ifp->if_flags & (IFF_UP | IFF_RUNNING)) != 4309 (ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
4310 (IFF_UP | IFF_RUNNING)) { 4310 (IFF_UP | IFF_RUNNING)) {
4311 ifp->if_flags |= IFF_UP; 4311 ifp->if_flags |= IFF_UP;
4312 error = ifp->if_init(ifp); 4312 error = ifp->if_init(ifp);
4313 } 4313 }
4314 return error; 4314 return error;
4315 case SIOCADDMULTI: 4315 case SIOCADDMULTI:
4316 case SIOCDELMULTI: 4316 case SIOCDELMULTI:
4317 switch (ifr->ifr_addr.sa_family) { 4317 switch (ifr->ifr_addr.sa_family) {
4318 case AF_INET: /* IP supports Multicast */ 4318 case AF_INET: /* IP supports Multicast */
4319 break; 4319 break;
4320#ifdef INET6 4320#ifdef INET6
4321 case AF_INET6: /* IP6 supports Multicast */ 4321 case AF_INET6: /* IP6 supports Multicast */
4322 break; 4322 break;
4323#endif 4323#endif
4324 default: /* Other protocols doesn't support Multicast */ 4324 default: /* Other protocols doesn't support Multicast */
4325 error = EAFNOSUPPORT; 4325 error = EAFNOSUPPORT;
4326 break; 4326 break;
4327 } 4327 }
4328 return error; 4328 return error;
4329 case SIOCSDRVSPEC: 4329 case SIOCSDRVSPEC:
4330 switch (ifd->ifd_cmd) { 4330 switch (ifd->ifd_cmd) {
4331 case WG_IOCTL_SET_PRIVATE_KEY: 4331 case WG_IOCTL_SET_PRIVATE_KEY:
4332 error = wg_ioctl_set_private_key(wg, ifd); 4332 error = wg_ioctl_set_private_key(wg, ifd);
4333 break; 4333 break;
4334 case WG_IOCTL_SET_LISTEN_PORT: 4334 case WG_IOCTL_SET_LISTEN_PORT:
4335 error = wg_ioctl_set_listen_port(wg, ifd); 4335 error = wg_ioctl_set_listen_port(wg, ifd);
4336 break; 4336 break;
4337 case WG_IOCTL_ADD_PEER: 4337 case WG_IOCTL_ADD_PEER:
4338 error = wg_ioctl_add_peer(wg, ifd); 4338 error = wg_ioctl_add_peer(wg, ifd);
4339 break; 4339 break;
4340 case WG_IOCTL_DELETE_PEER: 4340 case WG_IOCTL_DELETE_PEER:
4341 error = wg_ioctl_delete_peer(wg, ifd); 4341 error = wg_ioctl_delete_peer(wg, ifd);
4342 break; 4342 break;
4343 default: 4343 default:
4344 error = EINVAL; 4344 error = EINVAL;
4345 break; 4345 break;
4346 } 4346 }
4347 return error; 4347 return error;
4348 case SIOCGDRVSPEC: 4348 case SIOCGDRVSPEC:
4349 return wg_ioctl_get(wg, ifd); 4349 return wg_ioctl_get(wg, ifd);
4350 case SIOCSIFFLAGS: 4350 case SIOCSIFFLAGS:
4351 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 4351 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
4352 break; 4352 break;
4353 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 4353 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
4354 case IFF_RUNNING: 4354 case IFF_RUNNING:
4355 /* 4355 /*
4356 * If interface is marked down and it is running, 4356 * If interface is marked down and it is running,
4357 * then stop and disable it. 4357 * then stop and disable it.
4358 */ 4358 */
4359 (*ifp->if_stop)(ifp, 1); 4359 (*ifp->if_stop)(ifp, 1);
4360 break; 4360 break;
4361 case IFF_UP: 4361 case IFF_UP:
4362 /* 4362 /*
4363 * If interface is marked up and it is stopped, then 4363 * If interface is marked up and it is stopped, then
4364 * start it. 4364 * start it.
4365 */ 4365 */
4366 error = (*ifp->if_init)(ifp); 4366 error = (*ifp->if_init)(ifp);
4367 break; 4367 break;
4368 default: 4368 default:
4369 break; 4369 break;
4370 } 4370 }
4371 return error; 4371 return error;
4372#ifdef WG_RUMPKERNEL 4372#ifdef WG_RUMPKERNEL
4373 case SIOCSLINKSTR: 4373 case SIOCSLINKSTR:
4374 error = wg_ioctl_linkstr(wg, ifd); 4374 error = wg_ioctl_linkstr(wg, ifd);
4375 if (error == 0) 4375 if (error == 0)
4376 wg->wg_ops = &wg_ops_rumpuser; 4376 wg->wg_ops = &wg_ops_rumpuser;
4377 return error; 4377 return error;
4378#endif 4378#endif
4379 default: 4379 default:
4380 break; 4380 break;
4381 } 4381 }
4382 4382
4383 error = ifioctl_common(ifp, cmd, data); 4383 error = ifioctl_common(ifp, cmd, data);