Mon Aug 31 20:33:58 2020 UTC ()
wg: Simplify locking.

Summary: Access to a stable established session is still allowed via
psref; all other access to peer and session state is now serialized
by struct wg_peer::wgp_lock, with no dancing around a per-session
lock.  This way, the handshake paths are locked, while the data
transmission paths are pserialized.

- Eliminate struct wg_session::wgs_lock.

- Eliminate wg_get_unstable_session -- access to the unstable session
  is allowed only with struct wgp_peer::wgp_lock held.

- Push INIT_PASSIVE->ESTABLISHED transition down into a thread task.

- Push rekey down into a thread task.

- Allocate session indices only on transition from UNKNOWN and free
  them only on transition back to UNKNOWN.

- Be a little more explicit about allowed state transitions, and
  reject some nonsensical ones.

- Sprinkle assertions and comments.

- Reduce atomic r/m/w swap operations that can just as well be
  store-release.


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

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

--- src/sys/net/if_wg.c 2020/08/31 20:31:43 1.48
+++ src/sys/net/if_wg.c 2020/08/31 20:33:58 1.49
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_wg.c,v 1.48 2020/08/31 20:31:43 riastradh Exp $ */ 1/* $NetBSD: if_wg.c,v 1.49 2020/08/31 20:33:58 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com> 4 * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -31,27 +31,27 @@ @@ -31,27 +31,27 @@
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.48 2020/08/31 20:31:43 riastradh Exp $"); 44__KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.49 2020/08/31 20:33:58 riastradh Exp $");
45 45
46#ifdef _KERNEL_OPT 46#ifdef _KERNEL_OPT
47#include "opt_inet.h" 47#include "opt_inet.h"
48#endif 48#endif
49 49
50#include <sys/param.h> 50#include <sys/param.h>
51#include <sys/types.h> 51#include <sys/types.h>
52 52
53#include <sys/atomic.h> 53#include <sys/atomic.h>
54#include <sys/callout.h> 54#include <sys/callout.h>
55#include <sys/cprng.h> 55#include <sys/cprng.h>
56#include <sys/cpu.h> 56#include <sys/cpu.h>
57#include <sys/device.h> 57#include <sys/device.h>
@@ -127,53 +127,50 @@ __KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1. @@ -127,53 +127,50 @@ __KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.
127 * - It has a softint that is used to send packets over an wg interface 127 * - It has a softint that is used to send packets over an wg interface
128 * to a peer 128 * to a peer
129 * - It has a pair of session instances (struct wg_session) 129 * - It has a pair of session instances (struct wg_session)
130 * - It has a pair of endpoint instances (struct wg_sockaddr) 130 * - It has a pair of endpoint instances (struct wg_sockaddr)
131 * - Normally one endpoint is used and the second one is used only on 131 * - Normally one endpoint is used and the second one is used only on
132 * a peer migration (a change of peer's IP address) 132 * a peer migration (a change of peer's IP address)
133 * - It has a list of IP addresses and sub networks called allowedips 133 * - It has a list of IP addresses and sub networks called allowedips
134 * (struct wg_allowedip) 134 * (struct wg_allowedip)
135 * - A packets sent over a session is allowed if its destination matches 135 * - A packets sent over a session is allowed if its destination matches
136 * any IP addresses or sub networks of the list 136 * any IP addresses or sub networks of the list
137 * - struct wg_session represents a session of a secure tunnel with a peer 137 * - struct wg_session represents a session of a secure tunnel with a peer
138 * - Two instances of sessions belong to a peer; a stable session and a 138 * - Two instances of sessions belong to a peer; a stable session and a
139 * unstable session 139 * unstable session
140 * - A handshake process of a session always starts with a unstable instace 140 * - A handshake process of a session always starts with a unstable instance
141 * - Once a session is established, its instance becomes stable and the 141 * - Once a session is established, its instance becomes stable and the
142 * other becomes unstable instead 142 * other becomes unstable instead
143 * - Data messages are always sent via a stable session 143 * - Data messages are always sent via a stable session
144 * 144 *
145 * Locking notes: 145 * Locking notes:
146 * - wg interfaces (struct wg_softc, wg) is listed in wg_softcs.list and 146 * - wg interfaces (struct wg_softc, wg) is listed in wg_softcs.list and
147 * protected by wg_softcs.lock 147 * protected by wg_softcs.lock
148 * - Each wg has a mutex(9) and a rwlock(9) 148 * - Each wg has a mutex(9) wg_lock, and a rwlock(9) wg_rwlock
149 * - The mutex (wg_lock) protects its peer list (wg_peers) 149 * - Changes to the peer list are serialized by wg_lock
150 * - A peer on the list is also protected by pserialize(9) or psref(9) 150 * - The peer list may be read with pserialize(9) and psref(9)
151 * - The rwlock (wg_rwlock) protects the routing tables (wg_rtable_ipv[46]) 151 * - The rwlock (wg_rwlock) protects the routing tables (wg_rtable_ipv[46])
152 * - Each peer (struct wg_peer, wgp) has a mutex 152 * => XXX replace by pserialize when routing table is psz-safe
153 * - The mutex (wgp_lock) protects wgp_session_unstable and wgp_state 153 * - Each peer (struct wg_peer, wgp) has a mutex wgp_lock, which can be taken
154 * - Each session (struct wg_session, wgs) has a mutex 154 * only in thread context and serializes:
155 * - The mutex (wgs_lock) protects its state (wgs_state) and its handshake 155 * - the stable and unstable session pointers
156 * states 156 * - all unstable session state
157 * - wgs_state of a unstable session can be changed while it never be 157 * - Packet processing may be done in softint context:
158 * changed on a stable session, so once get a session instace via 158 * - The stable session can be read under pserialize(9) or psref(9)
159 * wgp_session_stable we can safely access wgs_state without 159 * - The stable session is always ESTABLISHED
160 * holding wgs_lock 
161 * - A session is protected by pserialize or psref like wgp 
162 * - On a session swap, we must wait for all readers to release a 160 * - On a session swap, we must wait for all readers to release a
163 * reference to a stable session before changing wgs_state and 161 * reference to a stable session before changing wgs_state and
164 * session states 162 * session states
165 * 163 * - Lock order: wg_lock -> wgp_lock
166 * Lock order: wg_lock -> wgp_lock -> wgs_lock 
167 */ 164 */
168 165
169 166
170#define WGLOG(level, fmt, args...) \ 167#define WGLOG(level, fmt, args...) \
171 log(level, "%s: " fmt, __func__, ##args) 168 log(level, "%s: " fmt, __func__, ##args)
172 169
173/* Debug options */ 170/* Debug options */
174#ifdef WG_DEBUG 171#ifdef WG_DEBUG
175/* Output debug logs */ 172/* Output debug logs */
176#ifndef WG_DEBUG_LOG 173#ifndef WG_DEBUG_LOG
177#define WG_DEBUG_LOG 174#define WG_DEBUG_LOG
178#endif 175#endif
179/* Output trace logs */ 176/* Output trace logs */
@@ -434,41 +431,40 @@ struct wg_worker { @@ -434,41 +431,40 @@ struct wg_worker {
434 bool wgw_todie; 431 bool wgw_todie;
435 struct socket *wgw_so4; 432 struct socket *wgw_so4;
436 struct socket *wgw_so6; 433 struct socket *wgw_so6;
437 int wgw_wakeup_reasons; 434 int wgw_wakeup_reasons;
438#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 __BIT(0) 435#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 __BIT(0)
439#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6 __BIT(1) 436#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6 __BIT(1)
440#define WG_WAKEUP_REASON_PEER __BIT(2) 437#define WG_WAKEUP_REASON_PEER __BIT(2)
441}; 438};
442 439
443struct wg_session { 440struct wg_session {
444 struct wg_peer *wgs_peer; 441 struct wg_peer *wgs_peer;
445 struct psref_target 442 struct psref_target
446 wgs_psref; 443 wgs_psref;
447 kmutex_t *wgs_lock; 
448 444
449 int wgs_state; 445 int wgs_state;
450#define WGS_STATE_UNKNOWN 0 446#define WGS_STATE_UNKNOWN 0
451#define WGS_STATE_INIT_ACTIVE 1 447#define WGS_STATE_INIT_ACTIVE 1
452#define WGS_STATE_INIT_PASSIVE 2 448#define WGS_STATE_INIT_PASSIVE 2
453#define WGS_STATE_ESTABLISHED 3 449#define WGS_STATE_ESTABLISHED 3
454#define WGS_STATE_DESTROYING 4 450#define WGS_STATE_DESTROYING 4
455 451
456 time_t wgs_time_established; 452 time_t wgs_time_established;
457 time_t wgs_time_last_data_sent; 453 time_t wgs_time_last_data_sent;
458 bool wgs_is_initiator; 454 bool wgs_is_initiator;
459 455
460 uint32_t wgs_sender_index; 456 uint32_t wgs_local_index;
461 uint32_t wgs_receiver_index; 457 uint32_t wgs_remote_index;
462#ifdef __HAVE_ATOMIC64_LOADSTORE 458#ifdef __HAVE_ATOMIC64_LOADSTORE
463 volatile uint64_t 459 volatile uint64_t
464 wgs_send_counter; 460 wgs_send_counter;
465#else 461#else
466 kmutex_t wgs_send_counter_lock; 462 kmutex_t wgs_send_counter_lock;
467 uint64_t wgs_send_counter; 463 uint64_t wgs_send_counter;
468#endif 464#endif
469 465
470 struct { 466 struct {
471 kmutex_t lock; 467 kmutex_t lock;
472 struct sliwin window; 468 struct sliwin window;
473 } *wgs_recvwin; 469 } *wgs_recvwin;
474 470
@@ -527,38 +523,32 @@ struct wg_ppsratecheck { @@ -527,38 +523,32 @@ struct wg_ppsratecheck {
527 523
528struct wg_softc; 524struct wg_softc;
529struct wg_peer { 525struct wg_peer {
530 struct wg_softc *wgp_sc; 526 struct wg_softc *wgp_sc;
531 char wgp_name[WG_PEER_NAME_MAXLEN + 1]; 527 char wgp_name[WG_PEER_NAME_MAXLEN + 1];
532 struct pslist_entry wgp_peerlist_entry; 528 struct pslist_entry wgp_peerlist_entry;
533 pserialize_t wgp_psz; 529 pserialize_t wgp_psz;
534 struct psref_target wgp_psref; 530 struct psref_target wgp_psref;
535 kmutex_t *wgp_lock; 531 kmutex_t *wgp_lock;
536 532
537 uint8_t wgp_pubkey[WG_STATIC_KEY_LEN]; 533 uint8_t wgp_pubkey[WG_STATIC_KEY_LEN];
538 struct wg_sockaddr *wgp_endpoint; 534 struct wg_sockaddr *wgp_endpoint;
539 struct wg_sockaddr *wgp_endpoint0; 535 struct wg_sockaddr *wgp_endpoint0;
540 bool wgp_endpoint_changing; 536 volatile unsigned wgp_endpoint_changing;
541 bool wgp_endpoint_available; 537 bool wgp_endpoint_available;
542 538
543 /* The preshared key (optional) */ 539 /* The preshared key (optional) */
544 uint8_t wgp_psk[WG_PRESHARED_KEY_LEN]; 540 uint8_t wgp_psk[WG_PRESHARED_KEY_LEN];
545 541
546 int wgp_state; 
547#define WGP_STATE_INIT 0 
548#define WGP_STATE_ESTABLISHED 1 
549#define WGP_STATE_GIVEUP 2 
550#define WGP_STATE_DESTROYING 3 
551 
552 void *wgp_si; 542 void *wgp_si;
553 pcq_t *wgp_q; 543 pcq_t *wgp_q;
554 544
555 struct wg_session *wgp_session_stable; 545 struct wg_session *wgp_session_stable;
556 struct wg_session *wgp_session_unstable; 546 struct wg_session *wgp_session_unstable;
557 547
558 /* timestamp in big-endian */ 548 /* timestamp in big-endian */
559 wg_timestamp_t wgp_timestamp_latest_init; 549 wg_timestamp_t wgp_timestamp_latest_init;
560 550
561 struct timespec wgp_last_handshake_time; 551 struct timespec wgp_last_handshake_time;
562 552
563 callout_t wgp_rekey_timer; 553 callout_t wgp_rekey_timer;
564 callout_t wgp_handshake_timeout_timer; 554 callout_t wgp_handshake_timeout_timer;
@@ -575,29 +565,31 @@ struct wg_peer { @@ -575,29 +565,31 @@ struct wg_peer {
575 bool wgp_last_sent_mac1_valid; 565 bool wgp_last_sent_mac1_valid;
576 uint8_t wgp_last_sent_cookie[WG_COOKIE_LEN]; 566 uint8_t wgp_last_sent_cookie[WG_COOKIE_LEN];
577 bool wgp_last_sent_cookie_valid; 567 bool wgp_last_sent_cookie_valid;
578 568
579 time_t wgp_last_msg_received_time[WG_MSG_TYPE_MAX]; 569 time_t wgp_last_msg_received_time[WG_MSG_TYPE_MAX];
580 570
581 time_t wgp_last_genrandval_time; 571 time_t wgp_last_genrandval_time;
582 uint32_t wgp_randval; 572 uint32_t wgp_randval;
583 573
584 struct wg_ppsratecheck wgp_ppsratecheck; 574 struct wg_ppsratecheck wgp_ppsratecheck;
585 575
586 volatile unsigned int wgp_tasks; 576 volatile unsigned int wgp_tasks;
587#define WGP_TASK_SEND_INIT_MESSAGE __BIT(0) 577#define WGP_TASK_SEND_INIT_MESSAGE __BIT(0)
588#define WGP_TASK_ENDPOINT_CHANGED __BIT(1) 578#define WGP_TASK_RETRY_HANDSHAKE __BIT(1)
589#define WGP_TASK_SEND_KEEPALIVE_MESSAGE __BIT(2) 579#define WGP_TASK_ESTABLISH_SESSION __BIT(2)
590#define WGP_TASK_DESTROY_PREV_SESSION __BIT(3) 580#define WGP_TASK_ENDPOINT_CHANGED __BIT(3)
 581#define WGP_TASK_SEND_KEEPALIVE_MESSAGE __BIT(4)
 582#define WGP_TASK_DESTROY_PREV_SESSION __BIT(5)
591}; 583};
592 584
593struct wg_ops; 585struct wg_ops;
594 586
595struct wg_softc { 587struct wg_softc {
596 struct ifnet wg_if; 588 struct ifnet wg_if;
597 LIST_ENTRY(wg_softc) wg_list; 589 LIST_ENTRY(wg_softc) wg_list;
598 kmutex_t *wg_lock; 590 kmutex_t *wg_lock;
599 krwlock_t *wg_rwlock; 591 krwlock_t *wg_rwlock;
600 592
601 uint8_t wg_privkey[WG_STATIC_KEY_LEN]; 593 uint8_t wg_privkey[WG_STATIC_KEY_LEN];
602 uint8_t wg_pubkey[WG_STATIC_KEY_LEN]; 594 uint8_t wg_pubkey[WG_STATIC_KEY_LEN];
603 595
@@ -642,28 +634,28 @@ static unsigned wg_reject_after_time = W @@ -642,28 +634,28 @@ static unsigned wg_reject_after_time = W
642static unsigned wg_rekey_attempt_time = WG_REKEY_ATTEMPT_TIME; 634static unsigned wg_rekey_attempt_time = WG_REKEY_ATTEMPT_TIME;
643static unsigned wg_rekey_timeout = WG_REKEY_TIMEOUT; 635static unsigned wg_rekey_timeout = WG_REKEY_TIMEOUT;
644static unsigned wg_keepalive_timeout = WG_KEEPALIVE_TIMEOUT; 636static unsigned wg_keepalive_timeout = WG_KEEPALIVE_TIMEOUT;
645 637
646static struct mbuf * 638static struct mbuf *
647 wg_get_mbuf(size_t, size_t); 639 wg_get_mbuf(size_t, size_t);
648 640
649static void wg_wakeup_worker(struct wg_worker *, int); 641static void wg_wakeup_worker(struct wg_worker *, int);
650 642
651static int wg_send_data_msg(struct wg_peer *, struct wg_session *, 643static int wg_send_data_msg(struct wg_peer *, struct wg_session *,
652 struct mbuf *); 644 struct mbuf *);
653static int wg_send_cookie_msg(struct wg_softc *, struct wg_peer *, 645static int wg_send_cookie_msg(struct wg_softc *, struct wg_peer *,
654 const uint32_t, const uint8_t [], const struct sockaddr *); 646 const uint32_t, const uint8_t [], const struct sockaddr *);
655static int wg_send_handshake_msg_resp(struct wg_softc *, 647static int wg_send_handshake_msg_resp(struct wg_softc *, struct wg_peer *,
656 struct wg_peer *, const struct wg_msg_init *); 648 struct wg_session *, const struct wg_msg_init *);
657static void wg_send_keepalive_msg(struct wg_peer *, struct wg_session *); 649static void wg_send_keepalive_msg(struct wg_peer *, struct wg_session *);
658 650
659static struct wg_peer * 651static struct wg_peer *
660 wg_pick_peer_by_sa(struct wg_softc *, const struct sockaddr *, 652 wg_pick_peer_by_sa(struct wg_softc *, const struct sockaddr *,
661 struct psref *); 653 struct psref *);
662static struct wg_peer * 654static struct wg_peer *
663 wg_lookup_peer_by_pubkey(struct wg_softc *, 655 wg_lookup_peer_by_pubkey(struct wg_softc *,
664 const uint8_t [], struct psref *); 656 const uint8_t [], struct psref *);
665 657
666static struct wg_session * 658static struct wg_session *
667 wg_lookup_session_by_index(struct wg_softc *, 659 wg_lookup_session_by_index(struct wg_softc *,
668 const uint32_t, struct psref *); 660 const uint32_t, struct psref *);
669 661
@@ -681,26 +673,28 @@ static void wg_clear_states(struct wg_se @@ -681,26 +673,28 @@ static void wg_clear_states(struct wg_se
681static void wg_get_peer(struct wg_peer *, struct psref *); 673static void wg_get_peer(struct wg_peer *, struct psref *);
682static void wg_put_peer(struct wg_peer *, struct psref *); 674static void wg_put_peer(struct wg_peer *, struct psref *);
683 675
684static int wg_send_so(struct wg_peer *, struct mbuf *); 676static int wg_send_so(struct wg_peer *, struct mbuf *);
685static int wg_send_udp(struct wg_peer *, struct mbuf *); 677static int wg_send_udp(struct wg_peer *, struct mbuf *);
686static int wg_output(struct ifnet *, struct mbuf *, 678static int wg_output(struct ifnet *, struct mbuf *,
687 const struct sockaddr *, const struct rtentry *); 679 const struct sockaddr *, const struct rtentry *);
688static void wg_input(struct ifnet *, struct mbuf *, const int); 680static void wg_input(struct ifnet *, struct mbuf *, const int);
689static int wg_ioctl(struct ifnet *, u_long, void *); 681static int wg_ioctl(struct ifnet *, u_long, void *);
690static int wg_bind_port(struct wg_softc *, const uint16_t); 682static int wg_bind_port(struct wg_softc *, const uint16_t);
691static int wg_init(struct ifnet *); 683static int wg_init(struct ifnet *);
692static void wg_stop(struct ifnet *, int); 684static void wg_stop(struct ifnet *, int);
693 685
 686static void wg_purge_pending_packets(struct wg_peer *);
 687
694static int wg_clone_create(struct if_clone *, int); 688static int wg_clone_create(struct if_clone *, int);
695static int wg_clone_destroy(struct ifnet *); 689static int wg_clone_destroy(struct ifnet *);
696 690
697struct wg_ops { 691struct wg_ops {
698 int (*send_hs_msg)(struct wg_peer *, struct mbuf *); 692 int (*send_hs_msg)(struct wg_peer *, struct mbuf *);
699 int (*send_data_msg)(struct wg_peer *, struct mbuf *); 693 int (*send_data_msg)(struct wg_peer *, struct mbuf *);
700 void (*input)(struct ifnet *, struct mbuf *, const int); 694 void (*input)(struct ifnet *, struct mbuf *, const int);
701 int (*bind_port)(struct wg_softc *, const uint16_t); 695 int (*bind_port)(struct wg_softc *, const uint16_t);
702}; 696};
703 697
704struct wg_ops wg_ops_rumpkernel = { 698struct wg_ops wg_ops_rumpkernel = {
705 .send_hs_msg = wg_send_so, 699 .send_hs_msg = wg_send_so,
706 .send_data_msg = wg_send_udp, 700 .send_data_msg = wg_send_udp,
@@ -1090,131 +1084,142 @@ wg_algo_tai64n(wg_timestamp_t timestamp) @@ -1090,131 +1084,142 @@ wg_algo_tai64n(wg_timestamp_t timestamp)
1090{ 1084{
1091 struct timespec ts; 1085 struct timespec ts;
1092 1086
1093 /* FIXME strict TAI64N (https://cr.yp.to/libtai/tai64.html) */ 1087 /* FIXME strict TAI64N (https://cr.yp.to/libtai/tai64.html) */
1094 getnanotime(&ts); 1088 getnanotime(&ts);
1095 /* TAI64 label in external TAI64 format */ 1089 /* TAI64 label in external TAI64 format */
1096 be32enc(timestamp, 0x40000000UL + (ts.tv_sec >> 32)); 1090 be32enc(timestamp, 0x40000000UL + (ts.tv_sec >> 32));
1097 /* second beginning from 1970 TAI */ 1091 /* second beginning from 1970 TAI */
1098 be32enc(timestamp + 4, ts.tv_sec & 0xffffffffU); 1092 be32enc(timestamp + 4, ts.tv_sec & 0xffffffffU);
1099 /* nanosecond in big-endian format */ 1093 /* nanosecond in big-endian format */
1100 be32enc(timestamp + 8, ts.tv_nsec); 1094 be32enc(timestamp + 8, ts.tv_nsec);
1101} 1095}
1102 1096
1103static struct wg_session * 1097/*
1104wg_get_unstable_session(struct wg_peer *wgp, struct psref *psref) 1098 * wg_get_stable_session(wgp, psref)
1105{ 1099 *
1106 int s; 1100 * Get a passive reference to the current stable session, or
1107 struct wg_session *wgs; 1101 * return NULL if there is no current stable session.
1108 1102 *
1109 s = pserialize_read_enter(); 1103 * The pointer is always there but the session is not necessarily
1110 wgs = wgp->wgp_session_unstable; 1104 * ESTABLISHED; if it is not ESTABLISHED, return NULL. However,
1111 psref_acquire(psref, &wgs->wgs_psref, wg_psref_class); 1105 * the session may transition from ESTABLISHED to DESTROYING while
1112 pserialize_read_exit(s); 1106 * holding the passive reference.
1113 return wgs; 1107 */
1114} 
1115 
1116static struct wg_session * 1108static struct wg_session *
1117wg_get_stable_session(struct wg_peer *wgp, struct psref *psref) 1109wg_get_stable_session(struct wg_peer *wgp, struct psref *psref)
1118{ 1110{
1119 int s; 1111 int s;
1120 struct wg_session *wgs; 1112 struct wg_session *wgs;
1121 1113
1122 s = pserialize_read_enter(); 1114 s = pserialize_read_enter();
1123 wgs = wgp->wgp_session_stable; 1115 wgs = atomic_load_consume(&wgp->wgp_session_stable);
1124 psref_acquire(psref, &wgs->wgs_psref, wg_psref_class); 1116 if (__predict_false(wgs->wgs_state != WGS_STATE_ESTABLISHED))
 1117 wgs = NULL;
 1118 else
 1119 psref_acquire(psref, &wgs->wgs_psref, wg_psref_class);
1125 pserialize_read_exit(s); 1120 pserialize_read_exit(s);
1126 return wgs; 
1127} 
1128 
1129static void 
1130wg_get_session(struct wg_session *wgs, struct psref *psref) 
1131{ 
1132 1121
1133 psref_acquire(psref, &wgs->wgs_psref, wg_psref_class); 1122 return wgs;
1134} 1123}
1135 1124
1136static void 1125static void
1137wg_put_session(struct wg_session *wgs, struct psref *psref) 1126wg_put_session(struct wg_session *wgs, struct psref *psref)
1138{ 1127{
1139 1128
1140 psref_release(psref, &wgs->wgs_psref, wg_psref_class); 1129 psref_release(psref, &wgs->wgs_psref, wg_psref_class);
1141} 1130}
1142 1131
1143static struct wg_session * 1132static void
1144wg_lock_unstable_session(struct wg_peer *wgp) 1133wg_destroy_session(struct wg_softc *wg, struct wg_session *wgs)
1145{ 1134{
1146 struct wg_session *wgs; 1135 struct wg_peer *wgp = wgs->wgs_peer;
 1136 struct wg_session *wgs0 __diagused;
 1137 void *garbage;
1147 1138
1148 mutex_enter(wgp->wgp_lock); 1139 KASSERT(mutex_owned(wgp->wgp_lock));
1149 wgs = wgp->wgp_session_unstable; 1140 KASSERT(wgs->wgs_state != WGS_STATE_UNKNOWN);
1150 mutex_enter(wgs->wgs_lock); 
1151 mutex_exit(wgp->wgp_lock); 
1152 return wgs; 
1153} 
1154 1141
1155#if 0 1142 /* Remove the session from the table. */
1156static void 1143 wgs0 = thmap_del(wg->wg_sessions_byindex,
1157wg_unlock_session(struct wg_peer *wgp, struct wg_session *wgs) 1144 &wgs->wgs_local_index, sizeof(wgs->wgs_local_index));
1158{ 1145 KASSERT(wgs0 == wgs);
 1146 garbage = thmap_stage_gc(wg->wg_sessions_byindex);
 1147
 1148 /* Wait for passive references to drain. */
 1149 pserialize_perform(wgp->wgp_psz);
 1150 psref_target_destroy(&wgs->wgs_psref, wg_psref_class);
1159 1151
1160 mutex_exit(wgs->wgs_lock); 1152 /* Free memory, zero state, and transition to UNKNOWN. */
 1153 thmap_gc(wg->wg_sessions_byindex, garbage);
 1154 wg_clear_states(wgs);
 1155 wgs->wgs_state = WGS_STATE_UNKNOWN;
1161} 1156}
1162#endif 
1163 1157
1164static uint32_t 1158/*
1165wg_assign_sender_index(struct wg_softc *wg, struct wg_session *wgs) 1159 * wg_get_session_index(wg, wgs)
 1160 *
 1161 * Choose a session index for wgs->wgs_local_index, and store it
 1162 * in wg's table of sessions by index.
 1163 *
 1164 * wgs must be the unstable session of its peer, and must be
 1165 * transitioning out of the UNKNOWN state.
 1166 */
 1167static void
 1168wg_get_session_index(struct wg_softc *wg, struct wg_session *wgs)
1166{ 1169{
1167 struct wg_peer *wgp = wgs->wgs_peer; 1170 struct wg_peer *wgp __diagused = wgs->wgs_peer;
1168 struct wg_session *wgs0; 1171 struct wg_session *wgs0;
1169 uint32_t index; 1172 uint32_t index;
1170 void *garbage; 
1171 1173
1172 mutex_enter(wgs->wgs_lock); 1174 KASSERT(mutex_owned(wgp->wgp_lock));
 1175 KASSERT(wgs == wgp->wgp_session_unstable);
 1176 KASSERT(wgs->wgs_state == WGS_STATE_UNKNOWN);
1173 1177
1174 /* Release the current index, if there is one. */ 1178 do {
1175 while ((index = wgs->wgs_sender_index) != 0) { 1179 /* Pick a uniform random index. */
1176 /* Remove the session by index. */ 1180 index = cprng_strong32();
1177 thmap_del(wg->wg_sessions_byindex, &index, sizeof index); 1181
1178 wgs->wgs_sender_index = 0; 1182 /* Try to take it. */
1179 mutex_exit(wgs->wgs_lock); 1183 wgs->wgs_local_index = index;
1180 1184 wgs0 = thmap_put(wg->wg_sessions_byindex,
1181 /* Wait for all thmap_gets to complete, and GC. */ 1185 &wgs->wgs_local_index, sizeof wgs->wgs_local_index, wgs);
1182 garbage = thmap_stage_gc(wg->wg_sessions_byindex); 
1183 mutex_enter(wgs->wgs_peer->wgp_lock); 
1184 pserialize_perform(wgp->wgp_psz); 
1185 mutex_exit(wgs->wgs_peer->wgp_lock); 
1186 thmap_gc(wg->wg_sessions_byindex, garbage); 
1187 1186
1188 mutex_enter(wgs->wgs_lock); 1187 /* If someone else beat us, start over. */
1189 } 1188 } while (__predict_false(wgs0 != wgs));
 1189}
1190 1190
1191restart: 1191/*
1192 /* Pick a uniform random nonzero index. */ 1192 * wg_put_session_index(wg, wgs)
1193 while (__predict_false((index = cprng_strong32()) == 0)) 1193 *
1194 continue; 1194 * Remove wgs from the table of sessions by index, wait for any
1195 1195 * passive references to drain, and transition the session to the
1196 /* Try to take it. */ 1196 * UNKNOWN state.
1197 wgs->wgs_sender_index = index; 1197 *
1198 wgs0 = thmap_put(wg->wg_sessions_byindex, 1198 * wgs must be the unstable session of its peer, and must not be
1199 &wgs->wgs_sender_index, sizeof wgs->wgs_sender_index, wgs); 1199 * UNKNOWN or ESTABLISHED.
1200 1200 */
1201 /* If someone else beat us, start over. */ 1201static void
1202 if (__predict_false(wgs0 != wgs)) 1202wg_put_session_index(struct wg_softc *wg, struct wg_session *wgs)
1203 goto restart; 1203{
 1204 struct wg_peer *wgp = wgs->wgs_peer;
1204 1205
1205 mutex_exit(wgs->wgs_lock); 1206 KASSERT(mutex_owned(wgp->wgp_lock));
 1207 KASSERT(wgs == wgp->wgp_session_unstable);
 1208 KASSERT(wgs->wgs_state != WGS_STATE_UNKNOWN);
 1209 KASSERT(wgs->wgs_state != WGS_STATE_ESTABLISHED);
1206 1210
1207 return index; 1211 wg_destroy_session(wg, wgs);
 1212 psref_target_init(&wgs->wgs_psref, wg_psref_class);
1208} 1213}
1209 1214
1210/* 1215/*
1211 * Handshake patterns 1216 * Handshake patterns
1212 * 1217 *
1213 * [W] 5: "These messages use the "IK" pattern from Noise" 1218 * [W] 5: "These messages use the "IK" pattern from Noise"
1214 * [N] 7.5. Interactive handshake patterns (fundamental) 1219 * [N] 7.5. Interactive handshake patterns (fundamental)
1215 * "The first character refers to the initiator’s static key:" 1220 * "The first character refers to the initiator’s static key:"
1216 * "I = Static key for initiator Immediately transmitted to responder, 1221 * "I = Static key for initiator Immediately transmitted to responder,
1217 * despite reduced or absent identity hiding" 1222 * despite reduced or absent identity hiding"
1218 * "The second character refers to the responder’s static key:" 1223 * "The second character refers to the responder’s static key:"
1219 * "K = Static key for responder Known to initiator" 1224 * "K = Static key for responder Known to initiator"
1220 * "IK: 1225 * "IK:
@@ -1229,28 +1234,32 @@ restart: @@ -1229,28 +1234,32 @@ restart:
1229 * -> e, es, s, ss 1234 * -> e, es, s, ss
1230 * <- e, ee, se, psk" 1235 * <- e, ee, se, psk"
1231 */ 1236 */
1232static void 1237static void
1233wg_fill_msg_init(struct wg_softc *wg, struct wg_peer *wgp, 1238wg_fill_msg_init(struct wg_softc *wg, struct wg_peer *wgp,
1234 struct wg_session *wgs, struct wg_msg_init *wgmi) 1239 struct wg_session *wgs, struct wg_msg_init *wgmi)
1235{ 1240{
1236 uint8_t ckey[WG_CHAINING_KEY_LEN]; /* [W] 5.4.2: Ci */ 1241 uint8_t ckey[WG_CHAINING_KEY_LEN]; /* [W] 5.4.2: Ci */
1237 uint8_t hash[WG_HASH_LEN]; /* [W] 5.4.2: Hi */ 1242 uint8_t hash[WG_HASH_LEN]; /* [W] 5.4.2: Hi */
1238 uint8_t cipher_key[WG_CIPHER_KEY_LEN]; 1243 uint8_t cipher_key[WG_CIPHER_KEY_LEN];
1239 uint8_t pubkey[WG_EPHEMERAL_KEY_LEN]; 1244 uint8_t pubkey[WG_EPHEMERAL_KEY_LEN];
1240 uint8_t privkey[WG_EPHEMERAL_KEY_LEN]; 1245 uint8_t privkey[WG_EPHEMERAL_KEY_LEN];
1241 1246
 1247 KASSERT(mutex_owned(wgp->wgp_lock));
 1248 KASSERT(wgs == wgp->wgp_session_unstable);
 1249 KASSERT(wgs->wgs_state == WGS_STATE_INIT_ACTIVE);
 1250
1242 wgmi->wgmi_type = htole32(WG_MSG_TYPE_INIT); 1251 wgmi->wgmi_type = htole32(WG_MSG_TYPE_INIT);
1243 wgmi->wgmi_sender = wg_assign_sender_index(wg, wgs); 1252 wgmi->wgmi_sender = wgs->wgs_local_index;
1244 1253
1245 /* [W] 5.4.2: First Message: Initiator to Responder */ 1254 /* [W] 5.4.2: First Message: Initiator to Responder */
1246 1255
1247 /* Ci := HASH(CONSTRUCTION) */ 1256 /* Ci := HASH(CONSTRUCTION) */
1248 /* Hi := HASH(Ci || IDENTIFIER) */ 1257 /* Hi := HASH(Ci || IDENTIFIER) */
1249 wg_init_key_and_hash(ckey, hash); 1258 wg_init_key_and_hash(ckey, hash);
1250 /* Hi := HASH(Hi || Sr^pub) */ 1259 /* Hi := HASH(Hi || Sr^pub) */
1251 wg_algo_hash(hash, wgp->wgp_pubkey, sizeof(wgp->wgp_pubkey)); 1260 wg_algo_hash(hash, wgp->wgp_pubkey, sizeof(wgp->wgp_pubkey));
1252 1261
1253 WG_DUMP_HASH("hash", hash); 1262 WG_DUMP_HASH("hash", hash);
1254 1263
1255 /* [N] 2.2: "e" */ 1264 /* [N] 2.2: "e" */
1256 /* Ei^priv, Ei^pub := DH-GENERATE() */ 1265 /* Ei^priv, Ei^pub := DH-GENERATE() */
@@ -1305,42 +1314,41 @@ wg_fill_msg_init(struct wg_softc *wg, st @@ -1305,42 +1314,41 @@ wg_fill_msg_init(struct wg_softc *wg, st
1305 memset(wgmi->wgmi_mac2, 0, sizeof(wgmi->wgmi_mac2)); 1314 memset(wgmi->wgmi_mac2, 0, sizeof(wgmi->wgmi_mac2));
1306 else { 1315 else {
1307 wg_algo_mac(wgmi->wgmi_mac2, sizeof(wgmi->wgmi_mac2), 1316 wg_algo_mac(wgmi->wgmi_mac2, sizeof(wgmi->wgmi_mac2),
1308 wgp->wgp_latest_cookie, WG_COOKIE_LEN, 1317 wgp->wgp_latest_cookie, WG_COOKIE_LEN,
1309 (const uint8_t *)wgmi, 1318 (const uint8_t *)wgmi,
1310 offsetof(struct wg_msg_init, wgmi_mac2), 1319 offsetof(struct wg_msg_init, wgmi_mac2),
1311 NULL, 0); 1320 NULL, 0);
1312 } 1321 }
1313 1322
1314 memcpy(wgs->wgs_ephemeral_key_pub, pubkey, sizeof(pubkey)); 1323 memcpy(wgs->wgs_ephemeral_key_pub, pubkey, sizeof(pubkey));
1315 memcpy(wgs->wgs_ephemeral_key_priv, privkey, sizeof(privkey)); 1324 memcpy(wgs->wgs_ephemeral_key_priv, privkey, sizeof(privkey));
1316 memcpy(wgs->wgs_handshake_hash, hash, sizeof(hash)); 1325 memcpy(wgs->wgs_handshake_hash, hash, sizeof(hash));
1317 memcpy(wgs->wgs_chaining_key, ckey, sizeof(ckey)); 1326 memcpy(wgs->wgs_chaining_key, ckey, sizeof(ckey));
1318 WG_DLOG("%s: sender=%x\n", __func__, wgs->wgs_sender_index); 1327 WG_DLOG("%s: sender=%x\n", __func__, wgs->wgs_local_index);
1319} 1328}
1320 1329
1321static void 1330static void
1322wg_handle_msg_init(struct wg_softc *wg, const struct wg_msg_init *wgmi, 1331wg_handle_msg_init(struct wg_softc *wg, const struct wg_msg_init *wgmi,
1323 const struct sockaddr *src) 1332 const struct sockaddr *src)
1324{ 1333{
1325 uint8_t ckey[WG_CHAINING_KEY_LEN]; /* [W] 5.4.2: Ci */ 1334 uint8_t ckey[WG_CHAINING_KEY_LEN]; /* [W] 5.4.2: Ci */
1326 uint8_t hash[WG_HASH_LEN]; /* [W] 5.4.2: Hi */ 1335 uint8_t hash[WG_HASH_LEN]; /* [W] 5.4.2: Hi */
1327 uint8_t cipher_key[WG_CIPHER_KEY_LEN]; 1336 uint8_t cipher_key[WG_CIPHER_KEY_LEN];
1328 uint8_t peer_pubkey[WG_STATIC_KEY_LEN]; 1337 uint8_t peer_pubkey[WG_STATIC_KEY_LEN];
1329 struct wg_peer *wgp; 1338 struct wg_peer *wgp;
1330 struct wg_session *wgs; 1339 struct wg_session *wgs;
1331 int error, ret; 1340 int error, ret;
1332 struct psref psref_peer; 1341 struct psref psref_peer;
1333 struct psref psref_session; 
1334 uint8_t mac1[WG_MAC_LEN]; 1342 uint8_t mac1[WG_MAC_LEN];
1335 1343
1336 WG_TRACE("init msg received"); 1344 WG_TRACE("init msg received");
1337 1345
1338 wg_algo_mac_mac1(mac1, sizeof(mac1), 1346 wg_algo_mac_mac1(mac1, sizeof(mac1),
1339 wg->wg_pubkey, sizeof(wg->wg_pubkey), 1347 wg->wg_pubkey, sizeof(wg->wg_pubkey),
1340 (const uint8_t *)wgmi, offsetof(struct wg_msg_init, wgmi_mac1)); 1348 (const uint8_t *)wgmi, offsetof(struct wg_msg_init, wgmi_mac1));
1341 1349
1342 /* 1350 /*
1343 * [W] 5.3: Denial of Service Mitigation & Cookies 1351 * [W] 5.3: Denial of Service Mitigation & Cookies
1344 * "the responder, ..., must always reject messages with an invalid 1352 * "the responder, ..., must always reject messages with an invalid
1345 * msg.mac1" 1353 * msg.mac1"
1346 */ 1354 */
@@ -1388,153 +1396,145 @@ wg_handle_msg_init(struct wg_softc *wg,  @@ -1388,153 +1396,145 @@ wg_handle_msg_init(struct wg_softc *wg,
1388 WG_LOG_RATECHECK(&wg->wg_ppsratecheck, LOG_DEBUG, 1396 WG_LOG_RATECHECK(&wg->wg_ppsratecheck, LOG_DEBUG,
1389 "wg_algo_aead_dec for secret key failed\n"); 1397 "wg_algo_aead_dec for secret key failed\n");
1390 return; 1398 return;
1391 } 1399 }
1392 /* Hi := HASH(Hi || msg.static) */ 1400 /* Hi := HASH(Hi || msg.static) */
1393 wg_algo_hash(hash, wgmi->wgmi_static, sizeof(wgmi->wgmi_static)); 1401 wg_algo_hash(hash, wgmi->wgmi_static, sizeof(wgmi->wgmi_static));
1394 1402
1395 wgp = wg_lookup_peer_by_pubkey(wg, peer_pubkey, &psref_peer); 1403 wgp = wg_lookup_peer_by_pubkey(wg, peer_pubkey, &psref_peer);
1396 if (wgp == NULL) { 1404 if (wgp == NULL) {
1397 WG_DLOG("peer not found\n"); 1405 WG_DLOG("peer not found\n");
1398 return; 1406 return;
1399 } 1407 }
1400 1408
 1409 /*
 1410 * Lock the peer to serialize access to cookie state.
 1411 *
 1412 * XXX Can we safely avoid holding the lock across DH? Take it
 1413 * just to verify mac2 and then unlock/DH/lock?
 1414 */
 1415 mutex_enter(wgp->wgp_lock);
 1416
1401 if (__predict_false(wg_is_underload(wg, wgp, WG_MSG_TYPE_INIT))) { 1417 if (__predict_false(wg_is_underload(wg, wgp, WG_MSG_TYPE_INIT))) {
1402 WG_TRACE("under load"); 1418 WG_TRACE("under load");
1403 /* 1419 /*
1404 * [W] 5.3: Denial of Service Mitigation & Cookies 1420 * [W] 5.3: Denial of Service Mitigation & Cookies
1405 * "the responder, ..., and when under load may reject messages 1421 * "the responder, ..., and when under load may reject messages
1406 * with an invalid msg.mac2. If the responder receives a 1422 * with an invalid msg.mac2. If the responder receives a
1407 * message with a valid msg.mac1 yet with an invalid msg.mac2, 1423 * message with a valid msg.mac1 yet with an invalid msg.mac2,
1408 * and is under load, it may respond with a cookie reply 1424 * and is under load, it may respond with a cookie reply
1409 * message" 1425 * message"
1410 */ 1426 */
1411 uint8_t zero[WG_MAC_LEN] = {0}; 1427 uint8_t zero[WG_MAC_LEN] = {0};
1412 if (consttime_memequal(wgmi->wgmi_mac2, zero, sizeof(zero))) { 1428 if (consttime_memequal(wgmi->wgmi_mac2, zero, sizeof(zero))) {
1413 WG_TRACE("sending a cookie message: no cookie included"); 1429 WG_TRACE("sending a cookie message: no cookie included");
1414 (void)wg_send_cookie_msg(wg, wgp, wgmi->wgmi_sender, 1430 (void)wg_send_cookie_msg(wg, wgp, wgmi->wgmi_sender,
1415 wgmi->wgmi_mac1, src); 1431 wgmi->wgmi_mac1, src);
1416 goto out_wgp; 1432 goto out;
1417 } 1433 }
1418 if (!wgp->wgp_last_sent_cookie_valid) { 1434 if (!wgp->wgp_last_sent_cookie_valid) {
1419 WG_TRACE("sending a cookie message: no cookie sent ever"); 1435 WG_TRACE("sending a cookie message: no cookie sent ever");
1420 (void)wg_send_cookie_msg(wg, wgp, wgmi->wgmi_sender, 1436 (void)wg_send_cookie_msg(wg, wgp, wgmi->wgmi_sender,
1421 wgmi->wgmi_mac1, src); 1437 wgmi->wgmi_mac1, src);
1422 goto out_wgp; 1438 goto out;
1423 } 1439 }
1424 uint8_t mac2[WG_MAC_LEN]; 1440 uint8_t mac2[WG_MAC_LEN];
1425 wg_algo_mac(mac2, sizeof(mac2), wgp->wgp_last_sent_cookie, 1441 wg_algo_mac(mac2, sizeof(mac2), wgp->wgp_last_sent_cookie,
1426 WG_COOKIE_LEN, (const uint8_t *)wgmi, 1442 WG_COOKIE_LEN, (const uint8_t *)wgmi,
1427 offsetof(struct wg_msg_init, wgmi_mac2), NULL, 0); 1443 offsetof(struct wg_msg_init, wgmi_mac2), NULL, 0);
1428 if (!consttime_memequal(mac2, wgmi->wgmi_mac2, sizeof(mac2))) { 1444 if (!consttime_memequal(mac2, wgmi->wgmi_mac2, sizeof(mac2))) {
1429 WG_DLOG("mac2 is invalid\n"); 1445 WG_DLOG("mac2 is invalid\n");
1430 goto out_wgp; 1446 goto out;
1431 } 1447 }
1432 WG_TRACE("under load, but continue to sending"); 1448 WG_TRACE("under load, but continue to sending");
1433 } 1449 }
1434 1450
1435 /* [N] 2.2: "ss" */ 1451 /* [N] 2.2: "ss" */
1436 /* Ci, k := KDF2(Ci, DH(Si^priv, Sr^pub)) */ 1452 /* Ci, k := KDF2(Ci, DH(Si^priv, Sr^pub)) */
1437 wg_algo_dh_kdf(ckey, cipher_key, wg->wg_privkey, wgp->wgp_pubkey); 1453 wg_algo_dh_kdf(ckey, cipher_key, wg->wg_privkey, wgp->wgp_pubkey);
1438 1454
1439 /* msg.timestamp := AEAD(k, TIMESTAMP(), Hi) */ 1455 /* msg.timestamp := AEAD(k, TIMESTAMP(), Hi) */
1440 wg_timestamp_t timestamp; 1456 wg_timestamp_t timestamp;
1441 error = wg_algo_aead_dec(timestamp, sizeof(timestamp), cipher_key, 0, 1457 error = wg_algo_aead_dec(timestamp, sizeof(timestamp), cipher_key, 0,
1442 wgmi->wgmi_timestamp, sizeof(wgmi->wgmi_timestamp), 1458 wgmi->wgmi_timestamp, sizeof(wgmi->wgmi_timestamp),
1443 hash, sizeof(hash)); 1459 hash, sizeof(hash));
1444 if (error != 0) { 1460 if (error != 0) {
1445 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 1461 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
1446 "wg_algo_aead_dec for timestamp failed\n"); 1462 "wg_algo_aead_dec for timestamp failed\n");
1447 goto out_wgp; 1463 goto out;
1448 } 1464 }
1449 /* Hi := HASH(Hi || msg.timestamp) */ 1465 /* Hi := HASH(Hi || msg.timestamp) */
1450 wg_algo_hash(hash, wgmi->wgmi_timestamp, sizeof(wgmi->wgmi_timestamp)); 1466 wg_algo_hash(hash, wgmi->wgmi_timestamp, sizeof(wgmi->wgmi_timestamp));
1451 1467
1452 wgs = wg_lock_unstable_session(wgp); 
1453 if (wgs->wgs_state == WGS_STATE_DESTROYING) { 
1454 /* 
1455 * We can assume that the peer doesn't have an 
1456 * established session, so clear it now. If the timer 
1457 * fired, tough -- it won't have any effect unless we 
1458 * manage to transition back to WGS_STATE_DESTROYING. 
1459 */ 
1460 WG_TRACE("Session destroying, but force to clear"); 
1461 callout_stop(&wgp->wgp_session_dtor_timer); 
1462 wg_clear_states(wgs); 
1463 wgs->wgs_state = WGS_STATE_UNKNOWN; 
1464 } 
1465 if (wgs->wgs_state == WGS_STATE_INIT_ACTIVE) { 
1466 WG_TRACE("Sesssion already initializing, ignoring the message"); 
1467 mutex_exit(wgs->wgs_lock); 
1468 goto out_wgp; 
1469 } 
1470 if (wgs->wgs_state == WGS_STATE_INIT_PASSIVE) { 
1471 WG_TRACE("Sesssion already initializing, destroying old states"); 
1472 wg_clear_states(wgs); 
1473 } 
1474 wgs->wgs_state = WGS_STATE_INIT_PASSIVE; 
1475 wg_get_session(wgs, &psref_session); 
1476 mutex_exit(wgs->wgs_lock); 
1477 
1478 /* 1468 /*
1479 * [W] 5.1 "The responder keeps track of the greatest timestamp 1469 * [W] 5.1 "The responder keeps track of the greatest timestamp
1480 * received per peer and discards packets containing 1470 * received per peer and discards packets containing
1481 * timestamps less than or equal to it." 1471 * timestamps less than or equal to it."
1482 */ 1472 */
1483 ret = memcmp(timestamp, wgp->wgp_timestamp_latest_init, 1473 ret = memcmp(timestamp, wgp->wgp_timestamp_latest_init,
1484 sizeof(timestamp)); 1474 sizeof(timestamp));
1485 if (ret <= 0) { 1475 if (ret <= 0) {
1486 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 1476 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
1487 "invalid init msg: timestamp is old\n"); 1477 "invalid init msg: timestamp is old\n");
1488 goto out; 1478 goto out;
1489 } 1479 }
1490 memcpy(wgp->wgp_timestamp_latest_init, timestamp, sizeof(timestamp)); 1480 memcpy(wgp->wgp_timestamp_latest_init, timestamp, sizeof(timestamp));
1491 1481
 1482 /*
 1483 * Message is good -- we're committing to handle it now, unless
 1484 * we were already initiating a session.
 1485 */
 1486 wgs = wgp->wgp_session_unstable;
 1487 switch (wgs->wgs_state) {
 1488 case WGS_STATE_UNKNOWN: /* new session initiated by peer */
 1489 wg_get_session_index(wg, wgs);
 1490 break;
 1491 case WGS_STATE_INIT_ACTIVE: /* we're already initiating, drop */
 1492 WG_TRACE("Session already initializing, ignoring the message");
 1493 goto out;
 1494 case WGS_STATE_INIT_PASSIVE: /* peer is retrying, start over */
 1495 WG_TRACE("Session already initializing, destroying old states");
 1496 wg_clear_states(wgs);
 1497 /* keep session index */
 1498 break;
 1499 case WGS_STATE_ESTABLISHED: /* can't happen */
 1500 panic("unstable session can't be established");
 1501 break;
 1502 case WGS_STATE_DESTROYING: /* rekey initiated by peer */
 1503 WG_TRACE("Session destroying, but force to clear");
 1504 callout_stop(&wgp->wgp_session_dtor_timer);
 1505 wg_clear_states(wgs);
 1506 /* keep session index */
 1507 break;
 1508 default:
 1509 panic("invalid session state: %d", wgs->wgs_state);
 1510 }
 1511 wgs->wgs_state = WGS_STATE_INIT_PASSIVE;
 1512
1492 memcpy(wgs->wgs_handshake_hash, hash, sizeof(hash)); 1513 memcpy(wgs->wgs_handshake_hash, hash, sizeof(hash));
1493 memcpy(wgs->wgs_chaining_key, ckey, sizeof(ckey)); 1514 memcpy(wgs->wgs_chaining_key, ckey, sizeof(ckey));
1494 memcpy(wgs->wgs_ephemeral_key_peer, wgmi->wgmi_ephemeral, 1515 memcpy(wgs->wgs_ephemeral_key_peer, wgmi->wgmi_ephemeral,
1495 sizeof(wgmi->wgmi_ephemeral)); 1516 sizeof(wgmi->wgmi_ephemeral));
1496 1517
1497 wg_update_endpoint_if_necessary(wgp, src); 1518 wg_update_endpoint_if_necessary(wgp, src);
1498 1519
1499 (void)wg_send_handshake_msg_resp(wg, wgp, wgmi); 1520 (void)wg_send_handshake_msg_resp(wg, wgp, wgs, wgmi);
1500 1521
1501 wg_calculate_keys(wgs, false); 1522 wg_calculate_keys(wgs, false);
1502 wg_clear_states(wgs); 1523 wg_clear_states(wgs);
1503 1524
1504 wg_put_session(wgs, &psref_session); 
1505 wg_put_peer(wgp, &psref_peer); 
1506 return; 
1507 
1508out: 1525out:
1509 mutex_enter(wgs->wgs_lock); 
1510 KASSERT(wgs->wgs_state == WGS_STATE_INIT_PASSIVE); 
1511 wgs->wgs_state = WGS_STATE_UNKNOWN; 
1512 mutex_exit(wgs->wgs_lock); 
1513 wg_put_session(wgs, &psref_session); 
1514out_wgp: 
1515 wg_put_peer(wgp, &psref_peer); 
1516} 
1517 
1518static void 
1519wg_schedule_handshake_timeout_timer(struct wg_peer *wgp) 
1520{ 
1521 
1522 mutex_enter(wgp->wgp_lock); 
1523 if (__predict_true(wgp->wgp_state != WGP_STATE_DESTROYING)) { 
1524 callout_schedule(&wgp->wgp_handshake_timeout_timer, 
1525 MIN(wg_rekey_timeout, INT_MAX/hz) * hz); 
1526 } 
1527 mutex_exit(wgp->wgp_lock); 1526 mutex_exit(wgp->wgp_lock);
 1527 wg_put_peer(wgp, &psref_peer);
1528} 1528}
1529 1529
1530static struct socket * 1530static struct socket *
1531wg_get_so_by_af(struct wg_worker *wgw, const int af) 1531wg_get_so_by_af(struct wg_worker *wgw, const int af)
1532{ 1532{
1533 1533
1534 return (af == AF_INET) ? wgw->wgw_so4 : wgw->wgw_so6; 1534 return (af == AF_INET) ? wgw->wgw_so4 : wgw->wgw_so6;
1535} 1535}
1536 1536
1537static struct socket * 1537static struct socket *
1538wg_get_so_by_peer(struct wg_peer *wgp, struct wg_sockaddr *wgsa) 1538wg_get_so_by_peer(struct wg_peer *wgp, struct wg_sockaddr *wgsa)
1539{ 1539{
1540 1540
@@ -1575,89 +1575,93 @@ wg_send_so(struct wg_peer *wgp, struct m @@ -1575,89 +1575,93 @@ wg_send_so(struct wg_peer *wgp, struct m
1575 error = sosend(so, wgsatosa(wgsa), NULL, m, NULL, 0, curlwp); 1575 error = sosend(so, wgsatosa(wgsa), NULL, m, NULL, 0, curlwp);
1576 wg_put_sa(wgp, wgsa, &psref); 1576 wg_put_sa(wgp, wgsa, &psref);
1577 1577
1578 return error; 1578 return error;
1579} 1579}
1580 1580
1581static int 1581static int
1582wg_send_handshake_msg_init(struct wg_softc *wg, struct wg_peer *wgp) 1582wg_send_handshake_msg_init(struct wg_softc *wg, struct wg_peer *wgp)
1583{ 1583{
1584 int error; 1584 int error;
1585 struct mbuf *m; 1585 struct mbuf *m;
1586 struct wg_msg_init *wgmi; 1586 struct wg_msg_init *wgmi;
1587 struct wg_session *wgs; 1587 struct wg_session *wgs;
1588 struct psref psref; 
1589 1588
1590 wgs = wg_lock_unstable_session(wgp); 1589 KASSERT(mutex_owned(wgp->wgp_lock));
1591 if (wgs->wgs_state == WGS_STATE_DESTROYING) { 1590
 1591 wgs = wgp->wgp_session_unstable;
 1592 /* XXX pull dispatch out into wg_task_send_init_message */
 1593 switch (wgs->wgs_state) {
 1594 case WGS_STATE_UNKNOWN: /* new session initiated by us */
 1595 wg_get_session_index(wg, wgs);
 1596 break;
 1597 case WGS_STATE_INIT_ACTIVE: /* we're already initiating, stop */
 1598 WG_TRACE("Session already initializing, skip starting new one");
 1599 return EBUSY;
 1600 case WGS_STATE_INIT_PASSIVE: /* peer was trying -- XXX what now? */
 1601 WG_TRACE("Session already initializing, destroying old states");
 1602 wg_clear_states(wgs);
 1603 /* keep session index */
 1604 break;
 1605 case WGS_STATE_ESTABLISHED: /* can't happen */
 1606 panic("unstable session can't be established");
 1607 break;
 1608 case WGS_STATE_DESTROYING: /* rekey initiated by us too early */
1592 WG_TRACE("Session destroying"); 1609 WG_TRACE("Session destroying");
1593 mutex_exit(wgs->wgs_lock); 
1594 /* XXX should wait? */ 1610 /* XXX should wait? */
1595 return EBUSY; 1611 return EBUSY;
1596 } 1612 }
1597 if (wgs->wgs_state == WGS_STATE_INIT_ACTIVE) { 
1598 WG_TRACE("Sesssion already initializing, skip starting a new one"); 
1599 mutex_exit(wgs->wgs_lock); 
1600 return EBUSY; 
1601 } 
1602 if (wgs->wgs_state == WGS_STATE_INIT_PASSIVE) { 
1603 WG_TRACE("Sesssion already initializing, destroying old states"); 
1604 wg_clear_states(wgs); 
1605 } 
1606 wgs->wgs_state = WGS_STATE_INIT_ACTIVE; 1613 wgs->wgs_state = WGS_STATE_INIT_ACTIVE;
1607 wg_get_session(wgs, &psref); 
1608 mutex_exit(wgs->wgs_lock); 
1609 1614
1610 m = m_gethdr(M_WAIT, MT_DATA); 1615 m = m_gethdr(M_WAIT, MT_DATA);
1611 m->m_pkthdr.len = m->m_len = sizeof(*wgmi); 1616 m->m_pkthdr.len = m->m_len = sizeof(*wgmi);
1612 wgmi = mtod(m, struct wg_msg_init *); 1617 wgmi = mtod(m, struct wg_msg_init *);
1613 wg_fill_msg_init(wg, wgp, wgs, wgmi); 1618 wg_fill_msg_init(wg, wgp, wgs, wgmi);
1614 1619
1615 error = wg->wg_ops->send_hs_msg(wgp, m); 1620 error = wg->wg_ops->send_hs_msg(wgp, m);
1616 if (error == 0) { 1621 if (error == 0) {
1617 WG_TRACE("init msg sent"); 1622 WG_TRACE("init msg sent");
1618 1623
1619 if (wgp->wgp_handshake_start_time == 0) 1624 if (wgp->wgp_handshake_start_time == 0)
1620 wgp->wgp_handshake_start_time = time_uptime; 1625 wgp->wgp_handshake_start_time = time_uptime;
1621 wg_schedule_handshake_timeout_timer(wgp); 1626 callout_schedule(&wgp->wgp_handshake_timeout_timer,
 1627 MIN(wg_rekey_timeout, INT_MAX/hz) * hz);
1622 } else { 1628 } else {
1623 mutex_enter(wgs->wgs_lock); 1629 wg_put_session_index(wg, wgs);
1624 KASSERT(wgs->wgs_state == WGS_STATE_INIT_ACTIVE); 
1625 wgs->wgs_state = WGS_STATE_UNKNOWN; 
1626 mutex_exit(wgs->wgs_lock); 
1627 } 1630 }
1628 wg_put_session(wgs, &psref); 
1629 1631
1630 return error; 1632 return error;
1631} 1633}
1632 1634
1633static void 1635static void
1634wg_fill_msg_resp(struct wg_softc *wg, struct wg_peer *wgp, 1636wg_fill_msg_resp(struct wg_softc *wg, struct wg_peer *wgp,
1635 struct wg_msg_resp *wgmr, const struct wg_msg_init *wgmi) 1637 struct wg_session *wgs, struct wg_msg_resp *wgmr,
 1638 const struct wg_msg_init *wgmi)
1636{ 1639{
1637 uint8_t ckey[WG_CHAINING_KEY_LEN]; /* [W] 5.4.3: Cr */ 1640 uint8_t ckey[WG_CHAINING_KEY_LEN]; /* [W] 5.4.3: Cr */
1638 uint8_t hash[WG_HASH_LEN]; /* [W] 5.4.3: Hr */ 1641 uint8_t hash[WG_HASH_LEN]; /* [W] 5.4.3: Hr */
1639 uint8_t cipher_key[WG_KDF_OUTPUT_LEN]; 1642 uint8_t cipher_key[WG_KDF_OUTPUT_LEN];
1640 uint8_t pubkey[WG_EPHEMERAL_KEY_LEN]; 1643 uint8_t pubkey[WG_EPHEMERAL_KEY_LEN];
1641 uint8_t privkey[WG_EPHEMERAL_KEY_LEN]; 1644 uint8_t privkey[WG_EPHEMERAL_KEY_LEN];
1642 struct wg_session *wgs; 
1643 struct psref psref; 
1644 1645
1645 wgs = wg_get_unstable_session(wgp, &psref); 1646 KASSERT(mutex_owned(wgp->wgp_lock));
 1647 KASSERT(wgs == wgp->wgp_session_unstable);
 1648 KASSERT(wgs->wgs_state == WGS_STATE_INIT_PASSIVE);
 1649
1646 memcpy(hash, wgs->wgs_handshake_hash, sizeof(hash)); 1650 memcpy(hash, wgs->wgs_handshake_hash, sizeof(hash));
1647 memcpy(ckey, wgs->wgs_chaining_key, sizeof(ckey)); 1651 memcpy(ckey, wgs->wgs_chaining_key, sizeof(ckey));
1648 1652
1649 wgmr->wgmr_type = htole32(WG_MSG_TYPE_RESP); 1653 wgmr->wgmr_type = htole32(WG_MSG_TYPE_RESP);
1650 wgmr->wgmr_sender = wg_assign_sender_index(wg, wgs); 1654 wgmr->wgmr_sender = wgs->wgs_local_index;
1651 wgmr->wgmr_receiver = wgmi->wgmi_sender; 1655 wgmr->wgmr_receiver = wgmi->wgmi_sender;
1652 1656
1653 /* [W] 5.4.3 Second Message: Responder to Initiator */ 1657 /* [W] 5.4.3 Second Message: Responder to Initiator */
1654 1658
1655 /* [N] 2.2: "e" */ 1659 /* [N] 2.2: "e" */
1656 /* Er^priv, Er^pub := DH-GENERATE() */ 1660 /* Er^priv, Er^pub := DH-GENERATE() */
1657 wg_algo_generate_keypair(pubkey, privkey); 1661 wg_algo_generate_keypair(pubkey, privkey);
1658 /* Cr := KDF1(Cr, Er^pub) */ 1662 /* Cr := KDF1(Cr, Er^pub) */
1659 wg_algo_kdf(ckey, NULL, NULL, ckey, pubkey, sizeof(pubkey)); 1663 wg_algo_kdf(ckey, NULL, NULL, ckey, pubkey, sizeof(pubkey));
1660 /* msg.ephemeral := Er^pub */ 1664 /* msg.ephemeral := Er^pub */
1661 memcpy(wgmr->wgmr_ephemeral, pubkey, sizeof(wgmr->wgmr_ephemeral)); 1665 memcpy(wgmr->wgmr_ephemeral, pubkey, sizeof(wgmr->wgmr_ephemeral));
1662 /* Hr := HASH(Hr || msg.ephemeral) */ 1666 /* Hr := HASH(Hr || msg.ephemeral) */
1663 wg_algo_hash(hash, pubkey, sizeof(pubkey)); 1667 wg_algo_hash(hash, pubkey, sizeof(pubkey));
@@ -1708,41 +1712,46 @@ wg_fill_msg_resp(struct wg_softc *wg, st @@ -1708,41 +1712,46 @@ wg_fill_msg_resp(struct wg_softc *wg, st
1708 else { 1712 else {
1709 /* msg.mac2 := MAC(Lm, msg_b) */ 1713 /* msg.mac2 := MAC(Lm, msg_b) */
1710 wg_algo_mac(wgmr->wgmr_mac2, sizeof(wgmi->wgmi_mac2), 1714 wg_algo_mac(wgmr->wgmr_mac2, sizeof(wgmi->wgmi_mac2),
1711 wgp->wgp_latest_cookie, WG_COOKIE_LEN, 1715 wgp->wgp_latest_cookie, WG_COOKIE_LEN,
1712 (const uint8_t *)wgmr, 1716 (const uint8_t *)wgmr,
1713 offsetof(struct wg_msg_resp, wgmr_mac2), 1717 offsetof(struct wg_msg_resp, wgmr_mac2),
1714 NULL, 0); 1718 NULL, 0);
1715 } 1719 }
1716 1720
1717 memcpy(wgs->wgs_handshake_hash, hash, sizeof(hash)); 1721 memcpy(wgs->wgs_handshake_hash, hash, sizeof(hash));
1718 memcpy(wgs->wgs_chaining_key, ckey, sizeof(ckey)); 1722 memcpy(wgs->wgs_chaining_key, ckey, sizeof(ckey));
1719 memcpy(wgs->wgs_ephemeral_key_pub, pubkey, sizeof(pubkey)); 1723 memcpy(wgs->wgs_ephemeral_key_pub, pubkey, sizeof(pubkey));
1720 memcpy(wgs->wgs_ephemeral_key_priv, privkey, sizeof(privkey)); 1724 memcpy(wgs->wgs_ephemeral_key_priv, privkey, sizeof(privkey));
1721 wgs->wgs_receiver_index = wgmi->wgmi_sender; 1725 wgs->wgs_remote_index = wgmi->wgmi_sender;
1722 WG_DLOG("sender=%x\n", wgs->wgs_sender_index); 1726 WG_DLOG("sender=%x\n", wgs->wgs_local_index);
1723 WG_DLOG("receiver=%x\n", wgs->wgs_receiver_index); 1727 WG_DLOG("receiver=%x\n", wgs->wgs_remote_index);
1724 wg_put_session(wgs, &psref); 
1725} 1728}
1726 1729
1727static void 1730static void
1728wg_swap_sessions(struct wg_peer *wgp) 1731wg_swap_sessions(struct wg_peer *wgp)
1729{ 1732{
 1733 struct wg_session *wgs, *wgs_prev;
1730 1734
1731 KASSERT(mutex_owned(wgp->wgp_lock)); 1735 KASSERT(mutex_owned(wgp->wgp_lock));
1732 1736
1733 wgp->wgp_session_unstable = atomic_swap_ptr(&wgp->wgp_session_stable, 1737 wgs = wgp->wgp_session_unstable;
1734 wgp->wgp_session_unstable); 1738 KASSERT(wgs->wgs_state == WGS_STATE_ESTABLISHED);
1735 KASSERT(wgp->wgp_session_stable->wgs_state == WGS_STATE_ESTABLISHED); 1739
 1740 wgs_prev = wgp->wgp_session_stable;
 1741 KASSERT(wgs_prev->wgs_state == WGS_STATE_ESTABLISHED ||
 1742 wgs_prev->wgs_state == WGS_STATE_UNKNOWN);
 1743 atomic_store_release(&wgp->wgp_session_stable, wgs);
 1744 wgp->wgp_session_unstable = wgs_prev;
1736} 1745}
1737 1746
1738static void 1747static void
1739wg_handle_msg_resp(struct wg_softc *wg, const struct wg_msg_resp *wgmr, 1748wg_handle_msg_resp(struct wg_softc *wg, const struct wg_msg_resp *wgmr,
1740 const struct sockaddr *src) 1749 const struct sockaddr *src)
1741{ 1750{
1742 uint8_t ckey[WG_CHAINING_KEY_LEN]; /* [W] 5.4.3: Cr */ 1751 uint8_t ckey[WG_CHAINING_KEY_LEN]; /* [W] 5.4.3: Cr */
1743 uint8_t hash[WG_HASH_LEN]; /* [W] 5.4.3: Kr */ 1752 uint8_t hash[WG_HASH_LEN]; /* [W] 5.4.3: Kr */
1744 uint8_t cipher_key[WG_KDF_OUTPUT_LEN]; 1753 uint8_t cipher_key[WG_KDF_OUTPUT_LEN];
1745 struct wg_peer *wgp; 1754 struct wg_peer *wgp;
1746 struct wg_session *wgs; 1755 struct wg_session *wgs;
1747 struct psref psref; 1756 struct psref psref;
1748 int error; 1757 int error;
@@ -1762,26 +1771,34 @@ wg_handle_msg_resp(struct wg_softc *wg,  @@ -1762,26 +1771,34 @@ wg_handle_msg_resp(struct wg_softc *wg,
1762 WG_DLOG("mac1 is invalid\n"); 1771 WG_DLOG("mac1 is invalid\n");
1763 return; 1772 return;
1764 } 1773 }
1765 1774
1766 WG_TRACE("resp msg received"); 1775 WG_TRACE("resp msg received");
1767 wgs = wg_lookup_session_by_index(wg, wgmr->wgmr_receiver, &psref); 1776 wgs = wg_lookup_session_by_index(wg, wgmr->wgmr_receiver, &psref);
1768 if (wgs == NULL) { 1777 if (wgs == NULL) {
1769 WG_TRACE("No session found"); 1778 WG_TRACE("No session found");
1770 return; 1779 return;
1771 } 1780 }
1772 1781
1773 wgp = wgs->wgs_peer; 1782 wgp = wgs->wgs_peer;
1774 1783
 1784 mutex_enter(wgp->wgp_lock);
 1785
 1786 /* If we weren't waiting for a handshake response, drop it. */
 1787 if (wgs->wgs_state != WGS_STATE_INIT_ACTIVE) {
 1788 WG_TRACE("peer sent spurious handshake response, ignoring");
 1789 goto out;
 1790 }
 1791
1775 if (__predict_false(wg_is_underload(wg, wgp, WG_MSG_TYPE_RESP))) { 1792 if (__predict_false(wg_is_underload(wg, wgp, WG_MSG_TYPE_RESP))) {
1776 WG_TRACE("under load"); 1793 WG_TRACE("under load");
1777 /* 1794 /*
1778 * [W] 5.3: Denial of Service Mitigation & Cookies 1795 * [W] 5.3: Denial of Service Mitigation & Cookies
1779 * "the responder, ..., and when under load may reject messages 1796 * "the responder, ..., and when under load may reject messages
1780 * with an invalid msg.mac2. If the responder receives a 1797 * with an invalid msg.mac2. If the responder receives a
1781 * message with a valid msg.mac1 yet with an invalid msg.mac2, 1798 * message with a valid msg.mac1 yet with an invalid msg.mac2,
1782 * and is under load, it may respond with a cookie reply 1799 * and is under load, it may respond with a cookie reply
1783 * message" 1800 * message"
1784 */ 1801 */
1785 uint8_t zero[WG_MAC_LEN] = {0}; 1802 uint8_t zero[WG_MAC_LEN] = {0};
1786 if (consttime_memequal(wgmr->wgmr_mac2, zero, sizeof(zero))) { 1803 if (consttime_memequal(wgmr->wgmr_mac2, zero, sizeof(zero))) {
1787 WG_TRACE("sending a cookie message: no cookie included"); 1804 WG_TRACE("sending a cookie message: no cookie included");
@@ -1855,90 +1872,100 @@ wg_handle_msg_resp(struct wg_softc *wg,  @@ -1855,90 +1872,100 @@ wg_handle_msg_resp(struct wg_softc *wg,
1855 sizeof(wgmr->wgmr_empty), hash, sizeof(hash)); 1872 sizeof(wgmr->wgmr_empty), hash, sizeof(hash));
1856 WG_DUMP_HASH("wgmr_empty", wgmr->wgmr_empty); 1873 WG_DUMP_HASH("wgmr_empty", wgmr->wgmr_empty);
1857 if (error != 0) { 1874 if (error != 0) {
1858 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 1875 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
1859 "wg_algo_aead_dec for empty message failed\n"); 1876 "wg_algo_aead_dec for empty message failed\n");
1860 goto out; 1877 goto out;
1861 } 1878 }
1862 /* Hr := HASH(Hr || msg.empty) */ 1879 /* Hr := HASH(Hr || msg.empty) */
1863 wg_algo_hash(hash, wgmr->wgmr_empty, sizeof(wgmr->wgmr_empty)); 1880 wg_algo_hash(hash, wgmr->wgmr_empty, sizeof(wgmr->wgmr_empty));
1864 } 1881 }
1865 1882
1866 memcpy(wgs->wgs_handshake_hash, hash, sizeof(wgs->wgs_handshake_hash)); 1883 memcpy(wgs->wgs_handshake_hash, hash, sizeof(wgs->wgs_handshake_hash));
1867 memcpy(wgs->wgs_chaining_key, ckey, sizeof(wgs->wgs_chaining_key)); 1884 memcpy(wgs->wgs_chaining_key, ckey, sizeof(wgs->wgs_chaining_key));
1868 wgs->wgs_receiver_index = wgmr->wgmr_sender; 1885 wgs->wgs_remote_index = wgmr->wgmr_sender;
1869 WG_DLOG("receiver=%x\n", wgs->wgs_receiver_index); 1886 WG_DLOG("receiver=%x\n", wgs->wgs_remote_index);
1870 1887
 1888 KASSERT(wgs->wgs_state == WGS_STATE_INIT_ACTIVE);
1871 wgs->wgs_state = WGS_STATE_ESTABLISHED; 1889 wgs->wgs_state = WGS_STATE_ESTABLISHED;
1872 wgs->wgs_time_established = time_uptime; 1890 wgs->wgs_time_established = time_uptime;
1873 wgs->wgs_time_last_data_sent = 0; 1891 wgs->wgs_time_last_data_sent = 0;
1874 wgs->wgs_is_initiator = true; 1892 wgs->wgs_is_initiator = true;
1875 wg_calculate_keys(wgs, true); 1893 wg_calculate_keys(wgs, true);
1876 wg_clear_states(wgs); 1894 wg_clear_states(wgs);
1877 WG_TRACE("WGS_STATE_ESTABLISHED"); 1895 WG_TRACE("WGS_STATE_ESTABLISHED");
1878 1896
1879 callout_halt(&wgp->wgp_handshake_timeout_timer, NULL); 1897 callout_stop(&wgp->wgp_handshake_timeout_timer);
1880 1898
1881 mutex_enter(wgp->wgp_lock); 
1882 wg_swap_sessions(wgp); 1899 wg_swap_sessions(wgp);
 1900 KASSERT(wgs == wgp->wgp_session_stable);
1883 wgs_prev = wgp->wgp_session_unstable; 1901 wgs_prev = wgp->wgp_session_unstable;
1884 mutex_enter(wgs_prev->wgs_lock); 
1885 
1886 getnanotime(&wgp->wgp_last_handshake_time); 1902 getnanotime(&wgp->wgp_last_handshake_time);
1887 wgp->wgp_handshake_start_time = 0; 1903 wgp->wgp_handshake_start_time = 0;
1888 wgp->wgp_last_sent_mac1_valid = false; 1904 wgp->wgp_last_sent_mac1_valid = false;
1889 wgp->wgp_last_sent_cookie_valid = false; 1905 wgp->wgp_last_sent_cookie_valid = false;
1890 mutex_exit(wgp->wgp_lock); 
1891 1906
1892 wg_schedule_rekey_timer(wgp); 1907 wg_schedule_rekey_timer(wgp);
1893 1908
1894 wg_update_endpoint_if_necessary(wgp, src); 1909 wg_update_endpoint_if_necessary(wgp, src);
1895 1910
1896 /* 1911 /*
1897 * Send something immediately (same as the official implementation) 1912 * Send something immediately (same as the official implementation)
1898 * XXX if there are pending data packets, we don't need to send 1913 * XXX if there are pending data packets, we don't need to send
1899 * a keepalive message. 1914 * a keepalive message.
1900 */ 1915 */
1901 wg_send_keepalive_msg(wgp, wgs); 1916 wg_send_keepalive_msg(wgp, wgs);
1902 1917
1903 /* Anyway run a softint to flush pending packets */ 1918 /* Anyway run a softint to flush pending packets */
1904 kpreempt_disable(); 1919 kpreempt_disable();
1905 softint_schedule(wgp->wgp_si); 1920 softint_schedule(wgp->wgp_si);
1906 kpreempt_enable(); 1921 kpreempt_enable();
1907 WG_TRACE("softint scheduled"); 1922 WG_TRACE("softint scheduled");
1908 1923
1909 if (wgs_prev->wgs_state == WGS_STATE_ESTABLISHED) { 1924 if (wgs_prev->wgs_state == WGS_STATE_ESTABLISHED) {
 1925 /* Wait for wg_get_stable_session to drain. */
 1926 pserialize_perform(wgp->wgp_psz);
 1927
 1928 /* Transition ESTABLISHED->DESTROYING. */
1910 wgs_prev->wgs_state = WGS_STATE_DESTROYING; 1929 wgs_prev->wgs_state = WGS_STATE_DESTROYING;
 1930
1911 /* We can't destroy the old session immediately */ 1931 /* We can't destroy the old session immediately */
1912 wg_schedule_session_dtor_timer(wgp); 1932 wg_schedule_session_dtor_timer(wgp);
 1933 } else {
 1934 KASSERTMSG(wgs_prev->wgs_state == WGS_STATE_UNKNOWN,
 1935 "state=%d", wgs_prev->wgs_state);
1913 } 1936 }
1914 mutex_exit(wgs_prev->wgs_lock); 
1915 1937
1916out: 1938out:
 1939 mutex_exit(wgp->wgp_lock);
1917 wg_put_session(wgs, &psref); 1940 wg_put_session(wgs, &psref);
1918} 1941}
1919 1942
1920static int 1943static int
1921wg_send_handshake_msg_resp(struct wg_softc *wg, struct wg_peer *wgp, 1944wg_send_handshake_msg_resp(struct wg_softc *wg, struct wg_peer *wgp,
1922 const struct wg_msg_init *wgmi) 1945 struct wg_session *wgs, const struct wg_msg_init *wgmi)
1923{ 1946{
1924 int error; 1947 int error;
1925 struct mbuf *m; 1948 struct mbuf *m;
1926 struct wg_msg_resp *wgmr; 1949 struct wg_msg_resp *wgmr;
1927 1950
 1951 KASSERT(mutex_owned(wgp->wgp_lock));
 1952 KASSERT(wgs == wgp->wgp_session_unstable);
 1953 KASSERT(wgs->wgs_state == WGS_STATE_INIT_PASSIVE);
 1954
1928 m = m_gethdr(M_WAIT, MT_DATA); 1955 m = m_gethdr(M_WAIT, MT_DATA);
1929 m->m_pkthdr.len = m->m_len = sizeof(*wgmr); 1956 m->m_pkthdr.len = m->m_len = sizeof(*wgmr);
1930 wgmr = mtod(m, struct wg_msg_resp *); 1957 wgmr = mtod(m, struct wg_msg_resp *);
1931 wg_fill_msg_resp(wg, wgp, wgmr, wgmi); 1958 wg_fill_msg_resp(wg, wgp, wgs, wgmr, wgmi);
1932 1959
1933 error = wg->wg_ops->send_hs_msg(wgp, m); 1960 error = wg->wg_ops->send_hs_msg(wgp, m);
1934 if (error == 0) 1961 if (error == 0)
1935 WG_TRACE("resp msg sent"); 1962 WG_TRACE("resp msg sent");
1936 return error; 1963 return error;
1937} 1964}
1938 1965
1939static struct wg_peer * 1966static struct wg_peer *
1940wg_lookup_peer_by_pubkey(struct wg_softc *wg, 1967wg_lookup_peer_by_pubkey(struct wg_softc *wg,
1941 const uint8_t pubkey[WG_STATIC_KEY_LEN], struct psref *psref) 1968 const uint8_t pubkey[WG_STATIC_KEY_LEN], struct psref *psref)
1942{ 1969{
1943 struct wg_peer *wgp; 1970 struct wg_peer *wgp;
1944 1971
@@ -1952,26 +1979,28 @@ wg_lookup_peer_by_pubkey(struct wg_softc @@ -1952,26 +1979,28 @@ wg_lookup_peer_by_pubkey(struct wg_softc
1952} 1979}
1953 1980
1954static void 1981static void
1955wg_fill_msg_cookie(struct wg_softc *wg, struct wg_peer *wgp, 1982wg_fill_msg_cookie(struct wg_softc *wg, struct wg_peer *wgp,
1956 struct wg_msg_cookie *wgmc, const uint32_t sender, 1983 struct wg_msg_cookie *wgmc, const uint32_t sender,
1957 const uint8_t mac1[WG_MAC_LEN], const struct sockaddr *src) 1984 const uint8_t mac1[WG_MAC_LEN], const struct sockaddr *src)
1958{ 1985{
1959 uint8_t cookie[WG_COOKIE_LEN]; 1986 uint8_t cookie[WG_COOKIE_LEN];
1960 uint8_t key[WG_HASH_LEN]; 1987 uint8_t key[WG_HASH_LEN];
1961 uint8_t addr[sizeof(struct in6_addr)]; 1988 uint8_t addr[sizeof(struct in6_addr)];
1962 size_t addrlen; 1989 size_t addrlen;
1963 uint16_t uh_sport; /* be */ 1990 uint16_t uh_sport; /* be */
1964 1991
 1992 KASSERT(mutex_owned(wgp->wgp_lock));
 1993
1965 wgmc->wgmc_type = htole32(WG_MSG_TYPE_COOKIE); 1994 wgmc->wgmc_type = htole32(WG_MSG_TYPE_COOKIE);
1966 wgmc->wgmc_receiver = sender; 1995 wgmc->wgmc_receiver = sender;
1967 cprng_fast(wgmc->wgmc_salt, sizeof(wgmc->wgmc_salt)); 1996 cprng_fast(wgmc->wgmc_salt, sizeof(wgmc->wgmc_salt));
1968 1997
1969 /* 1998 /*
1970 * [W] 5.4.7: Under Load: Cookie Reply Message 1999 * [W] 5.4.7: Under Load: Cookie Reply Message
1971 * "The secret variable, Rm, changes every two minutes to a 2000 * "The secret variable, Rm, changes every two minutes to a
1972 * random value" 2001 * random value"
1973 */ 2002 */
1974 if ((time_uptime - wgp->wgp_last_genrandval_time) > WG_RANDVAL_TIME) { 2003 if ((time_uptime - wgp->wgp_last_genrandval_time) > WG_RANDVAL_TIME) {
1975 wgp->wgp_randval = cprng_strong32(); 2004 wgp->wgp_randval = cprng_strong32();
1976 wgp->wgp_last_genrandval_time = time_uptime; 2005 wgp->wgp_last_genrandval_time = time_uptime;
1977 } 2006 }
@@ -2009,26 +2038,28 @@ wg_fill_msg_cookie(struct wg_softc *wg,  @@ -2009,26 +2038,28 @@ wg_fill_msg_cookie(struct wg_softc *wg,
2009 memcpy(wgp->wgp_last_sent_cookie, cookie, sizeof(cookie)); 2038 memcpy(wgp->wgp_last_sent_cookie, cookie, sizeof(cookie));
2010 wgp->wgp_last_sent_cookie_valid = true; 2039 wgp->wgp_last_sent_cookie_valid = true;
2011} 2040}
2012 2041
2013static int 2042static int
2014wg_send_cookie_msg(struct wg_softc *wg, struct wg_peer *wgp, 2043wg_send_cookie_msg(struct wg_softc *wg, struct wg_peer *wgp,
2015 const uint32_t sender, const uint8_t mac1[WG_MAC_LEN], 2044 const uint32_t sender, const uint8_t mac1[WG_MAC_LEN],
2016 const struct sockaddr *src) 2045 const struct sockaddr *src)
2017{ 2046{
2018 int error; 2047 int error;
2019 struct mbuf *m; 2048 struct mbuf *m;
2020 struct wg_msg_cookie *wgmc; 2049 struct wg_msg_cookie *wgmc;
2021 2050
 2051 KASSERT(mutex_owned(wgp->wgp_lock));
 2052
2022 m = m_gethdr(M_WAIT, MT_DATA); 2053 m = m_gethdr(M_WAIT, MT_DATA);
2023 m->m_pkthdr.len = m->m_len = sizeof(*wgmc); 2054 m->m_pkthdr.len = m->m_len = sizeof(*wgmc);
2024 wgmc = mtod(m, struct wg_msg_cookie *); 2055 wgmc = mtod(m, struct wg_msg_cookie *);
2025 wg_fill_msg_cookie(wg, wgp, wgmc, sender, mac1, src); 2056 wg_fill_msg_cookie(wg, wgp, wgmc, sender, mac1, src);
2026 2057
2027 error = wg->wg_ops->send_hs_msg(wgp, m); 2058 error = wg->wg_ops->send_hs_msg(wgp, m);
2028 if (error == 0) 2059 if (error == 0)
2029 WG_TRACE("cookie msg sent"); 2060 WG_TRACE("cookie msg sent");
2030 return error; 2061 return error;
2031} 2062}
2032 2063
2033static bool 2064static bool
2034wg_is_underload(struct wg_softc *wg, struct wg_peer *wgp, int msgtype) 2065wg_is_underload(struct wg_softc *wg, struct wg_peer *wgp, int msgtype)
@@ -2043,26 +2074,28 @@ wg_is_underload(struct wg_softc *wg, str @@ -2043,26 +2074,28 @@ wg_is_underload(struct wg_softc *wg, str
2043 * the mechanism is a DoS mitigation, so we consider frequent handshake 2074 * the mechanism is a DoS mitigation, so we consider frequent handshake
2044 * messages as (a kind of) load; if a message of the same type comes 2075 * messages as (a kind of) load; if a message of the same type comes
2045 * to a peer within 1 second, we consider we are under load. 2076 * to a peer within 1 second, we consider we are under load.
2046 */ 2077 */
2047 time_t last = wgp->wgp_last_msg_received_time[msgtype]; 2078 time_t last = wgp->wgp_last_msg_received_time[msgtype];
2048 wgp->wgp_last_msg_received_time[msgtype] = time_uptime; 2079 wgp->wgp_last_msg_received_time[msgtype] = time_uptime;
2049 return (time_uptime - last) == 0; 2080 return (time_uptime - last) == 0;
2050} 2081}
2051 2082
2052static void 2083static void
2053wg_calculate_keys(struct wg_session *wgs, const bool initiator) 2084wg_calculate_keys(struct wg_session *wgs, const bool initiator)
2054{ 2085{
2055 2086
 2087 KASSERT(mutex_owned(wgs->wgs_peer->wgp_lock));
 2088
2056 /* 2089 /*
2057 * [W] 5.4.5: Ti^send = Tr^recv, Ti^recv = Tr^send := KDF2(Ci = Cr, e) 2090 * [W] 5.4.5: Ti^send = Tr^recv, Ti^recv = Tr^send := KDF2(Ci = Cr, e)
2058 */ 2091 */
2059 if (initiator) { 2092 if (initiator) {
2060 wg_algo_kdf(wgs->wgs_tkey_send, wgs->wgs_tkey_recv, NULL, 2093 wg_algo_kdf(wgs->wgs_tkey_send, wgs->wgs_tkey_recv, NULL,
2061 wgs->wgs_chaining_key, NULL, 0); 2094 wgs->wgs_chaining_key, NULL, 0);
2062 } else { 2095 } else {
2063 wg_algo_kdf(wgs->wgs_tkey_recv, wgs->wgs_tkey_send, NULL, 2096 wg_algo_kdf(wgs->wgs_tkey_recv, wgs->wgs_tkey_send, NULL,
2064 wgs->wgs_chaining_key, NULL, 0); 2097 wgs->wgs_chaining_key, NULL, 0);
2065 } 2098 }
2066 WG_DUMP_HASH("wgs_tkey_send", wgs->wgs_tkey_send); 2099 WG_DUMP_HASH("wgs_tkey_send", wgs->wgs_tkey_send);
2067 WG_DUMP_HASH("wgs_tkey_recv", wgs->wgs_tkey_recv); 2100 WG_DUMP_HASH("wgs_tkey_recv", wgs->wgs_tkey_recv);
2068} 2101}
@@ -2093,48 +2126,53 @@ wg_session_inc_send_counter(struct wg_se @@ -2093,48 +2126,53 @@ wg_session_inc_send_counter(struct wg_se
2093 2126
2094 mutex_enter(&wgs->wgs_send_counter_lock); 2127 mutex_enter(&wgs->wgs_send_counter_lock);
2095 send_counter = wgs->wgs_send_counter++; 2128 send_counter = wgs->wgs_send_counter++;
2096 mutex_exit(&wgs->wgs_send_counter_lock); 2129 mutex_exit(&wgs->wgs_send_counter_lock);
2097 2130
2098 return send_counter; 2131 return send_counter;
2099#endif 2132#endif
2100} 2133}
2101 2134
2102static void 2135static void
2103wg_clear_states(struct wg_session *wgs) 2136wg_clear_states(struct wg_session *wgs)
2104{ 2137{
2105 2138
 2139 KASSERT(mutex_owned(wgs->wgs_peer->wgp_lock));
 2140
2106 wgs->wgs_send_counter = 0; 2141 wgs->wgs_send_counter = 0;
2107 sliwin_reset(&wgs->wgs_recvwin->window); 2142 sliwin_reset(&wgs->wgs_recvwin->window);
2108 2143
2109#define wgs_clear(v) explicit_memset(wgs->wgs_##v, 0, sizeof(wgs->wgs_##v)) 2144#define wgs_clear(v) explicit_memset(wgs->wgs_##v, 0, sizeof(wgs->wgs_##v))
2110 wgs_clear(handshake_hash); 2145 wgs_clear(handshake_hash);
2111 wgs_clear(chaining_key); 2146 wgs_clear(chaining_key);
2112 wgs_clear(ephemeral_key_pub); 2147 wgs_clear(ephemeral_key_pub);
2113 wgs_clear(ephemeral_key_priv); 2148 wgs_clear(ephemeral_key_priv);
2114 wgs_clear(ephemeral_key_peer); 2149 wgs_clear(ephemeral_key_peer);
2115#undef wgs_clear 2150#undef wgs_clear
2116} 2151}
2117 2152
2118static struct wg_session * 2153static struct wg_session *
2119wg_lookup_session_by_index(struct wg_softc *wg, const uint32_t index, 2154wg_lookup_session_by_index(struct wg_softc *wg, const uint32_t index,
2120 struct psref *psref) 2155 struct psref *psref)
2121{ 2156{
2122 struct wg_session *wgs; 2157 struct wg_session *wgs;
2123 2158
2124 int s = pserialize_read_enter(); 2159 int s = pserialize_read_enter();
2125 wgs = thmap_get(wg->wg_sessions_byindex, &index, sizeof index); 2160 wgs = thmap_get(wg->wg_sessions_byindex, &index, sizeof index);
2126 if (wgs != NULL) 2161 if (wgs != NULL) {
 2162 KASSERT(atomic_load_relaxed(&wgs->wgs_state) !=
 2163 WGS_STATE_UNKNOWN);
2127 psref_acquire(psref, &wgs->wgs_psref, wg_psref_class); 2164 psref_acquire(psref, &wgs->wgs_psref, wg_psref_class);
 2165 }
2128 pserialize_read_exit(s); 2166 pserialize_read_exit(s);
2129 2167
2130 return wgs; 2168 return wgs;
2131} 2169}
2132 2170
2133static void 2171static void
2134wg_schedule_rekey_timer(struct wg_peer *wgp) 2172wg_schedule_rekey_timer(struct wg_peer *wgp)
2135{ 2173{
2136 int timeout = MIN(wg_rekey_after_time, INT_MAX/hz); 2174 int timeout = MIN(wg_rekey_after_time, INT_MAX/hz);
2137 2175
2138 callout_schedule(&wgp->wgp_rekey_timer, timeout * hz); 2176 callout_schedule(&wgp->wgp_rekey_timer, timeout * hz);
2139} 2177}
2140 2178
@@ -2171,39 +2209,36 @@ wg_need_to_send_init_message(struct wg_s @@ -2171,39 +2209,36 @@ wg_need_to_send_init_message(struct wg_s
2171 2209
2172static void 2210static void
2173wg_schedule_peer_task(struct wg_peer *wgp, int task) 2211wg_schedule_peer_task(struct wg_peer *wgp, int task)
2174{ 2212{
2175 2213
2176 atomic_or_uint(&wgp->wgp_tasks, task); 2214 atomic_or_uint(&wgp->wgp_tasks, task);
2177 WG_DLOG("tasks=%d, task=%d\n", wgp->wgp_tasks, task); 2215 WG_DLOG("tasks=%d, task=%d\n", wgp->wgp_tasks, task);
2178 wg_wakeup_worker(wgp->wgp_sc->wg_worker, WG_WAKEUP_REASON_PEER); 2216 wg_wakeup_worker(wgp->wgp_sc->wg_worker, WG_WAKEUP_REASON_PEER);
2179} 2217}
2180 2218
2181static void 2219static void
2182wg_change_endpoint(struct wg_peer *wgp, const struct sockaddr *new) 2220wg_change_endpoint(struct wg_peer *wgp, const struct sockaddr *new)
2183{ 2221{
2184 2222 struct wg_sockaddr *wgsa_prev;
2185 KASSERT(mutex_owned(wgp->wgp_lock)); 
2186 2223
2187 WG_TRACE("Changing endpoint"); 2224 WG_TRACE("Changing endpoint");
2188 2225
2189 memcpy(wgp->wgp_endpoint0, new, new->sa_len); 2226 memcpy(wgp->wgp_endpoint0, new, new->sa_len);
2190#ifndef __HAVE_ATOMIC_AS_MEMBAR /* store-release */ 2227 wgsa_prev = wgp->wgp_endpoint;
2191 membar_exit(); 2228 atomic_store_release(&wgp->wgp_endpoint, wgp->wgp_endpoint0);
2192#endif 2229 wgp->wgp_endpoint0 = wgsa_prev;
2193 wgp->wgp_endpoint0 = atomic_swap_ptr(&wgp->wgp_endpoint, 2230 atomic_store_release(&wgp->wgp_endpoint_available, true);
2194 wgp->wgp_endpoint0); 2231
2195 wgp->wgp_endpoint_available = true; 
2196 wgp->wgp_endpoint_changing = true; 
2197 wg_schedule_peer_task(wgp, WGP_TASK_ENDPOINT_CHANGED); 2232 wg_schedule_peer_task(wgp, WGP_TASK_ENDPOINT_CHANGED);
2198} 2233}
2199 2234
2200static bool 2235static bool
2201wg_validate_inner_packet(const char *packet, size_t decrypted_len, int *af) 2236wg_validate_inner_packet(const char *packet, size_t decrypted_len, int *af)
2202{ 2237{
2203 uint16_t packet_len; 2238 uint16_t packet_len;
2204 const struct ip *ip; 2239 const struct ip *ip;
2205 2240
2206 if (__predict_false(decrypted_len < sizeof(struct ip))) 2241 if (__predict_false(decrypted_len < sizeof(struct ip)))
2207 return false; 2242 return false;
2208 2243
2209 ip = (const struct ip *)packet; 2244 ip = (const struct ip *)packet;
@@ -2271,33 +2306,26 @@ wg_validate_route(struct wg_softc *wg, s @@ -2271,33 +2306,26 @@ wg_validate_route(struct wg_softc *wg, s
2271 if (wgp != NULL) 2306 if (wgp != NULL)
2272 wg_put_peer(wgp, &psref); 2307 wg_put_peer(wgp, &psref);
2273 2308
2274 return ok; 2309 return ok;
2275} 2310}
2276 2311
2277static void 2312static void
2278wg_session_dtor_timer(void *arg) 2313wg_session_dtor_timer(void *arg)
2279{ 2314{
2280 struct wg_peer *wgp = arg; 2315 struct wg_peer *wgp = arg;
2281 2316
2282 WG_TRACE("enter"); 2317 WG_TRACE("enter");
2283 2318
2284 mutex_enter(wgp->wgp_lock); 
2285 if (__predict_false(wgp->wgp_state == WGP_STATE_DESTROYING)) { 
2286 mutex_exit(wgp->wgp_lock); 
2287 return; 
2288 } 
2289 mutex_exit(wgp->wgp_lock); 
2290 
2291 wg_schedule_peer_task(wgp, WGP_TASK_DESTROY_PREV_SESSION); 2319 wg_schedule_peer_task(wgp, WGP_TASK_DESTROY_PREV_SESSION);
2292} 2320}
2293 2321
2294static void 2322static void
2295wg_schedule_session_dtor_timer(struct wg_peer *wgp) 2323wg_schedule_session_dtor_timer(struct wg_peer *wgp)
2296{ 2324{
2297 2325
2298 /* 1 second grace period */ 2326 /* 1 second grace period */
2299 callout_schedule(&wgp->wgp_session_dtor_timer, hz); 2327 callout_schedule(&wgp->wgp_session_dtor_timer, hz);
2300} 2328}
2301 2329
2302static bool 2330static bool
2303sockaddr_port_match(const struct sockaddr *sa1, const struct sockaddr *sa2) 2331sockaddr_port_match(const struct sockaddr *sa1, const struct sockaddr *sa2)
@@ -2327,200 +2355,218 @@ wg_update_endpoint_if_necessary(struct w @@ -2327,200 +2355,218 @@ wg_update_endpoint_if_necessary(struct w
2327#ifdef WG_DEBUG_LOG 2355#ifdef WG_DEBUG_LOG
2328 char oldaddr[128], newaddr[128]; 2356 char oldaddr[128], newaddr[128];
2329 sockaddr_format(wgsatosa(wgsa), oldaddr, sizeof(oldaddr)); 2357 sockaddr_format(wgsatosa(wgsa), oldaddr, sizeof(oldaddr));
2330 sockaddr_format(src, newaddr, sizeof(newaddr)); 2358 sockaddr_format(src, newaddr, sizeof(newaddr));
2331 WG_DLOG("old=%s, new=%s\n", oldaddr, newaddr); 2359 WG_DLOG("old=%s, new=%s\n", oldaddr, newaddr);
2332#endif 2360#endif
2333 2361
2334 /* 2362 /*
2335 * III: "Since the packet has authenticated correctly, the source IP of 2363 * III: "Since the packet has authenticated correctly, the source IP of
2336 * the outer UDP/IP packet is used to update the endpoint for peer..." 2364 * the outer UDP/IP packet is used to update the endpoint for peer..."
2337 */ 2365 */
2338 if (__predict_false(sockaddr_cmp(src, wgsatosa(wgsa)) != 0 || 2366 if (__predict_false(sockaddr_cmp(src, wgsatosa(wgsa)) != 0 ||
2339 !sockaddr_port_match(src, wgsatosa(wgsa)))) { 2367 !sockaddr_port_match(src, wgsatosa(wgsa)))) {
2340 mutex_enter(wgp->wgp_lock); 
2341 /* XXX We can't change the endpoint twice in a short period */ 2368 /* XXX We can't change the endpoint twice in a short period */
2342 if (!wgp->wgp_endpoint_changing) { 2369 if (atomic_swap_uint(&wgp->wgp_endpoint_changing, 1) == 0) {
2343 wg_change_endpoint(wgp, src); 2370 wg_change_endpoint(wgp, src);
2344 } 2371 }
2345 mutex_exit(wgp->wgp_lock); 
2346 } 2372 }
2347 2373
2348 wg_put_sa(wgp, wgsa, &psref); 2374 wg_put_sa(wgp, wgsa, &psref);
2349} 2375}
2350 2376
2351static void 2377static void
2352wg_handle_msg_data(struct wg_softc *wg, struct mbuf *m, 2378wg_handle_msg_data(struct wg_softc *wg, struct mbuf *m,
2353 const struct sockaddr *src) 2379 const struct sockaddr *src)
2354{ 2380{
2355 struct wg_msg_data *wgmd; 2381 struct wg_msg_data *wgmd;
2356 char *encrypted_buf = NULL, *decrypted_buf; 2382 char *encrypted_buf = NULL, *decrypted_buf;
2357 size_t encrypted_len, decrypted_len; 2383 size_t encrypted_len, decrypted_len;
2358 struct wg_session *wgs; 2384 struct wg_session *wgs;
2359 struct wg_peer *wgp; 2385 struct wg_peer *wgp;
 2386 int state;
2360 size_t mlen; 2387 size_t mlen;
2361 struct psref psref; 2388 struct psref psref;
2362 int error, af; 2389 int error, af;
2363 bool success, free_encrypted_buf = false, ok; 2390 bool success, free_encrypted_buf = false, ok;
2364 struct mbuf *n; 2391 struct mbuf *n;
2365 2392
2366 KASSERT(m->m_len >= sizeof(struct wg_msg_data)); 2393 KASSERT(m->m_len >= sizeof(struct wg_msg_data));
2367 wgmd = mtod(m, struct wg_msg_data *); 2394 wgmd = mtod(m, struct wg_msg_data *);
2368 2395
2369 KASSERT(wgmd->wgmd_type == htole32(WG_MSG_TYPE_DATA)); 2396 KASSERT(wgmd->wgmd_type == htole32(WG_MSG_TYPE_DATA));
2370 WG_TRACE("data"); 2397 WG_TRACE("data");
2371 2398
 2399 /* Find the putative session, or drop. */
2372 wgs = wg_lookup_session_by_index(wg, wgmd->wgmd_receiver, &psref); 2400 wgs = wg_lookup_session_by_index(wg, wgmd->wgmd_receiver, &psref);
2373 if (wgs == NULL) { 2401 if (wgs == NULL) {
2374 WG_TRACE("No session found"); 2402 WG_TRACE("No session found");
2375 m_freem(m); 2403 m_freem(m);
2376 return; 2404 return;
2377 } 2405 }
 2406
 2407 /*
 2408 * We are only ready to handle data when in INIT_PASSIVE,
 2409 * ESTABLISHED, or DESTROYING. All transitions out of that
 2410 * state dissociate the session index and drain psrefs.
 2411 */
 2412 state = atomic_load_relaxed(&wgs->wgs_state);
 2413 switch (state) {
 2414 case WGS_STATE_UNKNOWN:
 2415 panic("wg session %p in unknown state has session index %u",
 2416 wgs, wgmd->wgmd_receiver);
 2417 case WGS_STATE_INIT_ACTIVE:
 2418 WG_TRACE("not yet ready for data");
 2419 goto out;
 2420 case WGS_STATE_INIT_PASSIVE:
 2421 case WGS_STATE_ESTABLISHED:
 2422 case WGS_STATE_DESTROYING:
 2423 break;
 2424 }
 2425
 2426 /*
 2427 * Get the peer, for rate-limited logs (XXX MPSAFE, dtrace) and
 2428 * to update the endpoint if authentication succeeds.
 2429 */
2378 wgp = wgs->wgs_peer; 2430 wgp = wgs->wgs_peer;
2379 2431
 2432 /*
 2433 * Reject outrageously wrong sequence numbers before doing any
 2434 * crypto work or taking any locks.
 2435 */
2380 error = sliwin_check_fast(&wgs->wgs_recvwin->window, 2436 error = sliwin_check_fast(&wgs->wgs_recvwin->window,
2381 le64toh(wgmd->wgmd_counter)); 2437 le64toh(wgmd->wgmd_counter));
2382 if (error) { 2438 if (error) {
2383 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2439 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2384 "out-of-window packet: %"PRIu64"\n", 2440 "out-of-window packet: %"PRIu64"\n",
2385 le64toh(wgmd->wgmd_counter)); 2441 le64toh(wgmd->wgmd_counter));
2386 goto out; 2442 goto out;
2387 } 2443 }
2388 2444
 2445 /* Ensure the payload and authenticator are contiguous. */
2389 mlen = m_length(m); 2446 mlen = m_length(m);
2390 encrypted_len = mlen - sizeof(*wgmd); 2447 encrypted_len = mlen - sizeof(*wgmd);
2391 
2392 if (encrypted_len < WG_AUTHTAG_LEN) { 2448 if (encrypted_len < WG_AUTHTAG_LEN) {
2393 WG_DLOG("Short encrypted_len: %lu\n", encrypted_len); 2449 WG_DLOG("Short encrypted_len: %lu\n", encrypted_len);
2394 goto out; 2450 goto out;
2395 } 2451 }
2396 
2397 success = m_ensure_contig(&m, sizeof(*wgmd) + encrypted_len); 2452 success = m_ensure_contig(&m, sizeof(*wgmd) + encrypted_len);
2398 if (success) { 2453 if (success) {
2399 encrypted_buf = mtod(m, char *) + sizeof(*wgmd); 2454 encrypted_buf = mtod(m, char *) + sizeof(*wgmd);
2400 } else { 2455 } else {
2401 encrypted_buf = kmem_intr_alloc(encrypted_len, KM_NOSLEEP); 2456 encrypted_buf = kmem_intr_alloc(encrypted_len, KM_NOSLEEP);
2402 if (encrypted_buf == NULL) { 2457 if (encrypted_buf == NULL) {
2403 WG_DLOG("failed to allocate encrypted_buf\n"); 2458 WG_DLOG("failed to allocate encrypted_buf\n");
2404 goto out; 2459 goto out;
2405 } 2460 }
2406 m_copydata(m, sizeof(*wgmd), encrypted_len, encrypted_buf); 2461 m_copydata(m, sizeof(*wgmd), encrypted_len, encrypted_buf);
2407 free_encrypted_buf = true; 2462 free_encrypted_buf = true;
2408 } 2463 }
2409 /* m_ensure_contig may change m regardless of its result */ 2464 /* m_ensure_contig may change m regardless of its result */
2410 KASSERT(m->m_len >= sizeof(*wgmd)); 2465 KASSERT(m->m_len >= sizeof(*wgmd));
2411 wgmd = mtod(m, struct wg_msg_data *); 2466 wgmd = mtod(m, struct wg_msg_data *);
2412 2467
 2468 /*
 2469 * Get a buffer for the plaintext. Add WG_AUTHTAG_LEN to avoid
 2470 * a zero-length buffer (XXX). Drop if plaintext is longer
 2471 * than MCLBYTES (XXX).
 2472 */
2413 decrypted_len = encrypted_len - WG_AUTHTAG_LEN; 2473 decrypted_len = encrypted_len - WG_AUTHTAG_LEN;
2414 if (decrypted_len > MCLBYTES) { 2474 if (decrypted_len > MCLBYTES) {
2415 /* FIXME handle larger data than MCLBYTES */ 2475 /* FIXME handle larger data than MCLBYTES */
2416 WG_DLOG("couldn't handle larger data than MCLBYTES\n"); 2476 WG_DLOG("couldn't handle larger data than MCLBYTES\n");
2417 goto out; 2477 goto out;
2418 } 2478 }
2419 
2420 /* To avoid zero length */ 
2421 n = wg_get_mbuf(0, decrypted_len + WG_AUTHTAG_LEN); 2479 n = wg_get_mbuf(0, decrypted_len + WG_AUTHTAG_LEN);
2422 if (n == NULL) { 2480 if (n == NULL) {
2423 WG_DLOG("wg_get_mbuf failed\n"); 2481 WG_DLOG("wg_get_mbuf failed\n");
2424 goto out; 2482 goto out;
2425 } 2483 }
2426 decrypted_buf = mtod(n, char *); 2484 decrypted_buf = mtod(n, char *);
2427 2485
 2486 /* Decrypt and verify the packet. */
2428 WG_DLOG("mlen=%lu, encrypted_len=%lu\n", mlen, encrypted_len); 2487 WG_DLOG("mlen=%lu, encrypted_len=%lu\n", mlen, encrypted_len);
2429 error = wg_algo_aead_dec(decrypted_buf, 2488 error = wg_algo_aead_dec(decrypted_buf,
2430 encrypted_len - WG_AUTHTAG_LEN /* can be 0 */, 2489 encrypted_len - WG_AUTHTAG_LEN /* can be 0 */,
2431 wgs->wgs_tkey_recv, le64toh(wgmd->wgmd_counter), encrypted_buf, 2490 wgs->wgs_tkey_recv, le64toh(wgmd->wgmd_counter), encrypted_buf,
2432 encrypted_len, NULL, 0); 2491 encrypted_len, NULL, 0);
2433 if (error != 0) { 2492 if (error != 0) {
2434 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2493 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2435 "failed to wg_algo_aead_dec\n"); 2494 "failed to wg_algo_aead_dec\n");
2436 m_freem(n); 2495 m_freem(n);
2437 goto out; 2496 goto out;
2438 } 2497 }
2439 WG_DLOG("outsize=%u\n", (u_int)decrypted_len); 2498 WG_DLOG("outsize=%u\n", (u_int)decrypted_len);
2440 2499
 2500 /* Packet is genuine. Reject it if a replay or just too old. */
2441 mutex_enter(&wgs->wgs_recvwin->lock); 2501 mutex_enter(&wgs->wgs_recvwin->lock);
2442 error = sliwin_update(&wgs->wgs_recvwin->window, 2502 error = sliwin_update(&wgs->wgs_recvwin->window,
2443 le64toh(wgmd->wgmd_counter)); 2503 le64toh(wgmd->wgmd_counter));
2444 mutex_exit(&wgs->wgs_recvwin->lock); 2504 mutex_exit(&wgs->wgs_recvwin->lock);
2445 if (error) { 2505 if (error) {
2446 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2506 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2447 "replay or out-of-window packet: %"PRIu64"\n", 2507 "replay or out-of-window packet: %"PRIu64"\n",
2448 le64toh(wgmd->wgmd_counter)); 2508 le64toh(wgmd->wgmd_counter));
2449 m_freem(n); 2509 m_freem(n);
2450 goto out; 2510 goto out;
2451 } 2511 }
2452 2512
 2513 /* We're done with m now; free it and chuck the pointers. */
2453 m_freem(m); 2514 m_freem(m);
2454 m = NULL; 2515 m = NULL;
2455 wgmd = NULL; 2516 wgmd = NULL;
2456 2517
 2518 /*
 2519 * Validate the encapsulated packet header and get the address
 2520 * family, or drop.
 2521 */
2457 ok = wg_validate_inner_packet(decrypted_buf, decrypted_len, &af); 2522 ok = wg_validate_inner_packet(decrypted_buf, decrypted_len, &af);
2458 if (!ok) { 2523 if (!ok) {
2459 /* something wrong... */ 
2460 m_freem(n); 2524 m_freem(n);
2461 goto out; 2525 goto out;
2462 } 2526 }
2463 2527
 2528 /*
 2529 * The packet is genuine. Update the peer's endpoint if the
 2530 * source address changed.
 2531 *
 2532 * XXX How to prevent DoS by replaying genuine packets from the
 2533 * wrong source address?
 2534 */
2464 wg_update_endpoint_if_necessary(wgp, src); 2535 wg_update_endpoint_if_necessary(wgp, src);
2465 2536
 2537 /* Submit it into our network stack if routable. */
2466 ok = wg_validate_route(wg, wgp, af, decrypted_buf); 2538 ok = wg_validate_route(wg, wgp, af, decrypted_buf);
2467 if (ok) { 2539 if (ok) {
2468 wg->wg_ops->input(&wg->wg_if, n, af); 2540 wg->wg_ops->input(&wg->wg_if, n, af);
2469 } else { 2541 } else {
2470 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2542 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2471 "invalid source address\n"); 2543 "invalid source address\n");
2472 m_freem(n); 2544 m_freem(n);
2473 /* 2545 /*
2474 * The inner address is invalid however the session is valid 2546 * The inner address is invalid however the session is valid
2475 * so continue the session processing below. 2547 * so continue the session processing below.
2476 */ 2548 */
2477 } 2549 }
2478 n = NULL; 2550 n = NULL;
2479 2551
2480 if (wgs->wgs_state == WGS_STATE_INIT_PASSIVE) { 2552 /* Update the state machine if necessary. */
2481 struct wg_session *wgs_prev; 2553 if (__predict_false(state == WGS_STATE_INIT_PASSIVE)) {
2482 2554 /*
2483 KASSERT(wgs == wgp->wgp_session_unstable); 2555 * We were waiting for the initiator to send their
2484 wgs->wgs_state = WGS_STATE_ESTABLISHED; 2556 * first data transport message, and that has happened.
2485 wgs->wgs_time_established = time_uptime; 2557 * Schedule a task to establish this session.
2486 wgs->wgs_time_last_data_sent = 0; 2558 */
2487 wgs->wgs_is_initiator = false; 2559 wg_schedule_peer_task(wgp, WGP_TASK_ESTABLISH_SESSION);
2488 WG_TRACE("WGS_STATE_ESTABLISHED"); 
2489 
2490 mutex_enter(wgp->wgp_lock); 
2491 wg_swap_sessions(wgp); 
2492 wgs_prev = wgp->wgp_session_unstable; 
2493 mutex_enter(wgs_prev->wgs_lock); 
2494 getnanotime(&wgp->wgp_last_handshake_time); 
2495 wgp->wgp_handshake_start_time = 0; 
2496 wgp->wgp_last_sent_mac1_valid = false; 
2497 wgp->wgp_last_sent_cookie_valid = false; 
2498 mutex_exit(wgp->wgp_lock); 
2499 
2500 if (wgs_prev->wgs_state == WGS_STATE_ESTABLISHED) { 
2501 wgs_prev->wgs_state = WGS_STATE_DESTROYING; 
2502 /* We can't destroy the old session immediately */ 
2503 wg_schedule_session_dtor_timer(wgp); 
2504 } else { 
2505 wg_clear_states(wgs_prev); 
2506 wgs_prev->wgs_state = WGS_STATE_UNKNOWN; 
2507 } 
2508 mutex_exit(wgs_prev->wgs_lock); 
2509 
2510 /* Anyway run a softint to flush pending packets */ 
2511 kpreempt_disable(); 
2512 softint_schedule(wgp->wgp_si); 
2513 kpreempt_enable(); 
2514 } else { 2560 } else {
2515 if (__predict_false(wg_need_to_send_init_message(wgs))) { 2561 if (__predict_false(wg_need_to_send_init_message(wgs))) {
2516 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 2562 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
2517 } 2563 }
2518 /* 2564 /*
2519 * [W] 6.5 Passive Keepalive 2565 * [W] 6.5 Passive Keepalive
2520 * "If a peer has received a validly-authenticated transport 2566 * "If a peer has received a validly-authenticated transport
2521 * data message (section 5.4.6), but does not have any packets 2567 * data message (section 5.4.6), but does not have any packets
2522 * itself to send back for KEEPALIVE-TIMEOUT seconds, it sends 2568 * itself to send back for KEEPALIVE-TIMEOUT seconds, it sends
2523 * a keepalive message." 2569 * a keepalive message."
2524 */ 2570 */
2525 WG_DLOG("time_uptime=%lu wgs_time_last_data_sent=%lu\n", 2571 WG_DLOG("time_uptime=%lu wgs_time_last_data_sent=%lu\n",
2526 time_uptime, wgs->wgs_time_last_data_sent); 2572 time_uptime, wgs->wgs_time_last_data_sent);
@@ -2545,58 +2591,65 @@ out: @@ -2545,58 +2591,65 @@ out:
2545} 2591}
2546 2592
2547static void 2593static void
2548wg_handle_msg_cookie(struct wg_softc *wg, const struct wg_msg_cookie *wgmc) 2594wg_handle_msg_cookie(struct wg_softc *wg, const struct wg_msg_cookie *wgmc)
2549{ 2595{
2550 struct wg_session *wgs; 2596 struct wg_session *wgs;
2551 struct wg_peer *wgp; 2597 struct wg_peer *wgp;
2552 struct psref psref; 2598 struct psref psref;
2553 int error; 2599 int error;
2554 uint8_t key[WG_HASH_LEN]; 2600 uint8_t key[WG_HASH_LEN];
2555 uint8_t cookie[WG_COOKIE_LEN]; 2601 uint8_t cookie[WG_COOKIE_LEN];
2556 2602
2557 WG_TRACE("cookie msg received"); 2603 WG_TRACE("cookie msg received");
 2604
 2605 /* Find the putative session. */
2558 wgs = wg_lookup_session_by_index(wg, wgmc->wgmc_receiver, &psref); 2606 wgs = wg_lookup_session_by_index(wg, wgmc->wgmc_receiver, &psref);
2559 if (wgs == NULL) { 2607 if (wgs == NULL) {
2560 WG_TRACE("No session found"); 2608 WG_TRACE("No session found");
2561 return; 2609 return;
2562 } 2610 }
 2611
 2612 /* Lock the peer so we can update the cookie state. */
2563 wgp = wgs->wgs_peer; 2613 wgp = wgs->wgs_peer;
 2614 mutex_enter(wgp->wgp_lock);
2564 2615
2565 if (!wgp->wgp_last_sent_mac1_valid) { 2616 if (!wgp->wgp_last_sent_mac1_valid) {
2566 WG_TRACE("No valid mac1 sent (or expired)"); 2617 WG_TRACE("No valid mac1 sent (or expired)");
2567 goto out; 2618 goto out;
2568 } 2619 }
2569 2620
 2621 /* Decrypt the cookie and store it for later handshake retry. */
2570 wg_algo_mac_cookie(key, sizeof(key), wgp->wgp_pubkey, 2622 wg_algo_mac_cookie(key, sizeof(key), wgp->wgp_pubkey,
2571 sizeof(wgp->wgp_pubkey)); 2623 sizeof(wgp->wgp_pubkey));
2572 error = wg_algo_xaead_dec(cookie, sizeof(cookie), key, 2624 error = wg_algo_xaead_dec(cookie, sizeof(cookie), key,
2573 wgmc->wgmc_cookie, sizeof(wgmc->wgmc_cookie), 2625 wgmc->wgmc_cookie, sizeof(wgmc->wgmc_cookie),
2574 wgp->wgp_last_sent_mac1, sizeof(wgp->wgp_last_sent_mac1), 2626 wgp->wgp_last_sent_mac1, sizeof(wgp->wgp_last_sent_mac1),
2575 wgmc->wgmc_salt); 2627 wgmc->wgmc_salt);
2576 if (error != 0) { 2628 if (error != 0) {
2577 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2629 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2578 "wg_algo_aead_dec for cookie failed: error=%d\n", error); 2630 "wg_algo_aead_dec for cookie failed: error=%d\n", error);
2579 goto out; 2631 goto out;
2580 } 2632 }
2581 /* 2633 /*
2582 * [W] 6.6: Interaction with Cookie Reply System 2634 * [W] 6.6: Interaction with Cookie Reply System
2583 * "it should simply store the decrypted cookie value from the cookie 2635 * "it should simply store the decrypted cookie value from the cookie
2584 * reply message, and wait for the expiration of the REKEY-TIMEOUT 2636 * reply message, and wait for the expiration of the REKEY-TIMEOUT
2585 * timer for retrying a handshake initiation message." 2637 * timer for retrying a handshake initiation message."
2586 */ 2638 */
2587 wgp->wgp_latest_cookie_time = time_uptime; 2639 wgp->wgp_latest_cookie_time = time_uptime;
2588 memcpy(wgp->wgp_latest_cookie, cookie, sizeof(wgp->wgp_latest_cookie)); 2640 memcpy(wgp->wgp_latest_cookie, cookie, sizeof(wgp->wgp_latest_cookie));
2589out: 2641out:
 2642 mutex_exit(wgp->wgp_lock);
2590 wg_put_session(wgs, &psref); 2643 wg_put_session(wgs, &psref);
2591} 2644}
2592 2645
2593static struct mbuf * 2646static struct mbuf *
2594wg_validate_msg_header(struct wg_softc *wg, struct mbuf *m) 2647wg_validate_msg_header(struct wg_softc *wg, struct mbuf *m)
2595{ 2648{
2596 struct wg_msg wgm; 2649 struct wg_msg wgm;
2597 size_t mbuflen; 2650 size_t mbuflen;
2598 size_t msglen; 2651 size_t msglen;
2599 2652
2600 /* 2653 /*
2601 * Get the mbuf chain length. It is already guaranteed, by 2654 * Get the mbuf chain length. It is already guaranteed, by
2602 * wg_overudp_cb, to be large enough for a struct wg_msg. 2655 * wg_overudp_cb, to be large enough for a struct wg_msg.
@@ -2720,135 +2773,224 @@ wg_get_peer(struct wg_peer *wgp, struct  @@ -2720,135 +2773,224 @@ wg_get_peer(struct wg_peer *wgp, struct
2720 psref_acquire(psref, &wgp->wgp_psref, wg_psref_class); 2773 psref_acquire(psref, &wgp->wgp_psref, wg_psref_class);
2721} 2774}
2722 2775
2723static void 2776static void
2724wg_put_peer(struct wg_peer *wgp, struct psref *psref) 2777wg_put_peer(struct wg_peer *wgp, struct psref *psref)
2725{ 2778{
2726 2779
2727 psref_release(psref, &wgp->wgp_psref, wg_psref_class); 2780 psref_release(psref, &wgp->wgp_psref, wg_psref_class);
2728} 2781}
2729 2782
2730static void 2783static void
2731wg_task_send_init_message(struct wg_softc *wg, struct wg_peer *wgp) 2784wg_task_send_init_message(struct wg_softc *wg, struct wg_peer *wgp)
2732{ 2785{
2733 struct psref psref; 
2734 struct wg_session *wgs; 2786 struct wg_session *wgs;
2735 2787
2736 WG_TRACE("WGP_TASK_SEND_INIT_MESSAGE"); 2788 WG_TRACE("WGP_TASK_SEND_INIT_MESSAGE");
2737 2789
2738 if (!wgp->wgp_endpoint_available) { 2790 KASSERT(mutex_owned(wgp->wgp_lock));
 2791
 2792 if (!atomic_load_acquire(&wgp->wgp_endpoint_available)) {
2739 WGLOG(LOG_DEBUG, "No endpoint available\n"); 2793 WGLOG(LOG_DEBUG, "No endpoint available\n");
2740 /* XXX should do something? */ 2794 /* XXX should do something? */
2741 return; 2795 return;
2742 } 2796 }
2743 2797
2744 wgs = wg_get_stable_session(wgp, &psref); 2798 wgs = wgp->wgp_session_stable;
2745 if (wgs->wgs_state == WGS_STATE_UNKNOWN) { 2799 if (wgs->wgs_state == WGS_STATE_UNKNOWN) {
2746 wg_put_session(wgs, &psref); 2800 /* XXX What if the unstable session is already INIT_ACTIVE? */
2747 wg_send_handshake_msg_init(wg, wgp); 2801 wg_send_handshake_msg_init(wg, wgp);
2748 } else { 2802 } else {
2749 wg_put_session(wgs, &psref); 
2750 /* rekey */ 2803 /* rekey */
2751 wgs = wg_get_unstable_session(wgp, &psref); 2804 wgs = wgp->wgp_session_unstable;
2752 if (wgs->wgs_state != WGS_STATE_INIT_ACTIVE) 2805 if (wgs->wgs_state != WGS_STATE_INIT_ACTIVE)
2753 wg_send_handshake_msg_init(wg, wgp); 2806 wg_send_handshake_msg_init(wg, wgp);
2754 wg_put_session(wgs, &psref); 
2755 } 2807 }
2756} 2808}
2757 2809
2758static void 2810static void
 2811wg_task_retry_handshake(struct wg_softc *wg, struct wg_peer *wgp)
 2812{
 2813 struct wg_session *wgs;
 2814
 2815 WG_TRACE("WGP_TASK_RETRY_HANDSHAKE");
 2816
 2817 KASSERT(mutex_owned(wgp->wgp_lock));
 2818 KASSERT(wgp->wgp_handshake_start_time != 0);
 2819
 2820 wgs = wgp->wgp_session_unstable;
 2821 if (wgs->wgs_state != WGS_STATE_INIT_ACTIVE)
 2822 return;
 2823
 2824 /*
 2825 * XXX no real need to assign a new index here, but we do need
 2826 * to transition to UNKNOWN temporarily
 2827 */
 2828 wg_put_session_index(wg, wgs);
 2829
 2830 /* [W] 6.4 Handshake Initiation Retransmission */
 2831 if ((time_uptime - wgp->wgp_handshake_start_time) >
 2832 wg_rekey_attempt_time) {
 2833 /* Give up handshaking */
 2834 wgp->wgp_handshake_start_time = 0;
 2835 WG_TRACE("give up");
 2836
 2837 /*
 2838 * If a new data packet comes, handshaking will be retried
 2839 * and a new session would be established at that time,
 2840 * however we don't want to send pending packets then.
 2841 */
 2842 wg_purge_pending_packets(wgp);
 2843 return;
 2844 }
 2845
 2846 wg_task_send_init_message(wg, wgp);
 2847}
 2848
 2849static void
 2850wg_task_establish_session(struct wg_softc *wg, struct wg_peer *wgp)
 2851{
 2852 struct wg_session *wgs, *wgs_prev;
 2853
 2854 KASSERT(mutex_owned(wgp->wgp_lock));
 2855
 2856 wgs = wgp->wgp_session_unstable;
 2857 if (wgs->wgs_state != WGS_STATE_INIT_PASSIVE)
 2858 /* XXX Can this happen? */
 2859 return;
 2860
 2861 wgs->wgs_state = WGS_STATE_ESTABLISHED;
 2862 wgs->wgs_time_established = time_uptime;
 2863 wgs->wgs_time_last_data_sent = 0;
 2864 wgs->wgs_is_initiator = false;
 2865 WG_TRACE("WGS_STATE_ESTABLISHED");
 2866
 2867 wg_swap_sessions(wgp);
 2868 KASSERT(wgs == wgp->wgp_session_stable);
 2869 wgs_prev = wgp->wgp_session_unstable;
 2870 getnanotime(&wgp->wgp_last_handshake_time);
 2871 wgp->wgp_handshake_start_time = 0;
 2872 wgp->wgp_last_sent_mac1_valid = false;
 2873 wgp->wgp_last_sent_cookie_valid = false;
 2874
 2875 if (wgs_prev->wgs_state == WGS_STATE_ESTABLISHED) {
 2876 /* Wait for wg_get_stable_session to drain. */
 2877 pserialize_perform(wgp->wgp_psz);
 2878
 2879 /* Transition ESTABLISHED->DESTROYING. */
 2880 wgs_prev->wgs_state = WGS_STATE_DESTROYING;
 2881
 2882 /* We can't destroy the old session immediately */
 2883 wg_schedule_session_dtor_timer(wgp);
 2884 } else {
 2885 KASSERTMSG(wgs_prev->wgs_state == WGS_STATE_UNKNOWN,
 2886 "state=%d", wgs_prev->wgs_state);
 2887 wg_clear_states(wgs_prev);
 2888 wgs_prev->wgs_state = WGS_STATE_UNKNOWN;
 2889 }
 2890
 2891 /* Anyway run a softint to flush pending packets */
 2892 kpreempt_disable();
 2893 softint_schedule(wgp->wgp_si);
 2894 kpreempt_enable();
 2895}
 2896
 2897static void
2759wg_task_endpoint_changed(struct wg_softc *wg, struct wg_peer *wgp) 2898wg_task_endpoint_changed(struct wg_softc *wg, struct wg_peer *wgp)
2760{ 2899{
2761 2900
2762 WG_TRACE("WGP_TASK_ENDPOINT_CHANGED"); 2901 WG_TRACE("WGP_TASK_ENDPOINT_CHANGED");
2763 2902
2764 mutex_enter(wgp->wgp_lock); 2903 KASSERT(mutex_owned(wgp->wgp_lock));
2765 if (wgp->wgp_endpoint_changing) { 2904
 2905 if (atomic_load_relaxed(&wgp->wgp_endpoint_changing)) {
2766 pserialize_perform(wgp->wgp_psz); 2906 pserialize_perform(wgp->wgp_psz);
2767 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref, 2907 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref,
2768 wg_psref_class); 2908 wg_psref_class);
2769 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref, 2909 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref,
2770 wg_psref_class); 2910 wg_psref_class);
2771 wgp->wgp_endpoint_changing = false; 2911 atomic_store_release(&wgp->wgp_endpoint_changing, 0);
2772 } 2912 }
2773 mutex_exit(wgp->wgp_lock); 
2774} 2913}
2775 2914
2776static void 2915static void
2777wg_task_send_keepalive_message(struct wg_softc *wg, struct wg_peer *wgp) 2916wg_task_send_keepalive_message(struct wg_softc *wg, struct wg_peer *wgp)
2778{ 2917{
2779 struct psref psref; 
2780 struct wg_session *wgs; 2918 struct wg_session *wgs;
2781 2919
2782 WG_TRACE("WGP_TASK_SEND_KEEPALIVE_MESSAGE"); 2920 WG_TRACE("WGP_TASK_SEND_KEEPALIVE_MESSAGE");
2783 2921
2784 wgs = wg_get_stable_session(wgp, &psref); 2922 KASSERT(mutex_owned(wgp->wgp_lock));
 2923
 2924 wgs = wgp->wgp_session_stable;
 2925 if (wgs->wgs_state != WGS_STATE_ESTABLISHED)
 2926 return;
 2927
2785 wg_send_keepalive_msg(wgp, wgs); 2928 wg_send_keepalive_msg(wgp, wgs);
2786 wg_put_session(wgs, &psref); 
2787} 2929}
2788 2930
2789static void 2931static void
2790wg_task_destroy_prev_session(struct wg_softc *wg, struct wg_peer *wgp) 2932wg_task_destroy_prev_session(struct wg_softc *wg, struct wg_peer *wgp)
2791{ 2933{
2792 struct wg_session *wgs; 2934 struct wg_session *wgs;
2793 2935
2794 WG_TRACE("WGP_TASK_DESTROY_PREV_SESSION"); 2936 WG_TRACE("WGP_TASK_DESTROY_PREV_SESSION");
2795 2937
2796 mutex_enter(wgp->wgp_lock); 2938 KASSERT(mutex_owned(wgp->wgp_lock));
 2939
2797 wgs = wgp->wgp_session_unstable; 2940 wgs = wgp->wgp_session_unstable;
2798 mutex_enter(wgs->wgs_lock); 
2799 if (wgs->wgs_state == WGS_STATE_DESTROYING) { 2941 if (wgs->wgs_state == WGS_STATE_DESTROYING) {
2800 pserialize_perform(wgp->wgp_psz); 2942 wg_put_session_index(wg, wgs);
2801 psref_target_destroy(&wgs->wgs_psref, wg_psref_class); 
2802 psref_target_init(&wgs->wgs_psref, wg_psref_class); 
2803 wg_clear_states(wgs); 
2804 wgs->wgs_state = WGS_STATE_UNKNOWN; 
2805 } 2943 }
2806 mutex_exit(wgs->wgs_lock); 
2807 mutex_exit(wgp->wgp_lock); 
2808} 2944}
2809 2945
2810static void 2946static void
2811wg_process_peer_tasks(struct wg_softc *wg) 2947wg_process_peer_tasks(struct wg_softc *wg)
2812{ 2948{
2813 struct wg_peer *wgp; 2949 struct wg_peer *wgp;
2814 int s; 2950 int s;
2815 2951
2816 /* XXX should avoid checking all peers */ 2952 /* XXX should avoid checking all peers */
2817 s = pserialize_read_enter(); 2953 s = pserialize_read_enter();
2818 WG_PEER_READER_FOREACH(wgp, wg) { 2954 WG_PEER_READER_FOREACH(wgp, wg) {
2819 struct psref psref; 2955 struct psref psref;
2820 unsigned int tasks; 2956 unsigned int tasks;
2821 2957
2822 if (wgp->wgp_tasks == 0) 2958 if (wgp->wgp_tasks == 0)
2823 continue; 2959 continue;
2824 2960
2825 wg_get_peer(wgp, &psref); 2961 wg_get_peer(wgp, &psref);
2826 pserialize_read_exit(s); 2962 pserialize_read_exit(s);
2827 2963
2828 restart: 2964 restart:
2829 tasks = atomic_swap_uint(&wgp->wgp_tasks, 0); 2965 tasks = atomic_swap_uint(&wgp->wgp_tasks, 0);
2830 KASSERT(tasks != 0); 2966 KASSERT(tasks != 0);
2831 2967
2832 WG_DLOG("tasks=%x\n", tasks); 2968 WG_DLOG("tasks=%x\n", tasks);
2833 2969
 2970 mutex_enter(wgp->wgp_lock);
2834 if (ISSET(tasks, WGP_TASK_SEND_INIT_MESSAGE)) 2971 if (ISSET(tasks, WGP_TASK_SEND_INIT_MESSAGE))
2835 wg_task_send_init_message(wg, wgp); 2972 wg_task_send_init_message(wg, wgp);
 2973 if (ISSET(tasks, WGP_TASK_RETRY_HANDSHAKE))
 2974 wg_task_retry_handshake(wg, wgp);
 2975 if (ISSET(tasks, WGP_TASK_ESTABLISH_SESSION))
 2976 wg_task_establish_session(wg, wgp);
2836 if (ISSET(tasks, WGP_TASK_ENDPOINT_CHANGED)) 2977 if (ISSET(tasks, WGP_TASK_ENDPOINT_CHANGED))
2837 wg_task_endpoint_changed(wg, wgp); 2978 wg_task_endpoint_changed(wg, wgp);
2838 if (ISSET(tasks, WGP_TASK_SEND_KEEPALIVE_MESSAGE)) 2979 if (ISSET(tasks, WGP_TASK_SEND_KEEPALIVE_MESSAGE))
2839 wg_task_send_keepalive_message(wg, wgp); 2980 wg_task_send_keepalive_message(wg, wgp);
2840 if (ISSET(tasks, WGP_TASK_DESTROY_PREV_SESSION)) 2981 if (ISSET(tasks, WGP_TASK_DESTROY_PREV_SESSION))
2841 wg_task_destroy_prev_session(wg, wgp); 2982 wg_task_destroy_prev_session(wg, wgp);
 2983 mutex_exit(wgp->wgp_lock);
2842 2984
2843 /* New tasks may be scheduled during processing tasks */ 2985 /* New tasks may be scheduled during processing tasks */
2844 WG_DLOG("wgp_tasks=%d\n", wgp->wgp_tasks); 2986 WG_DLOG("wgp_tasks=%d\n", wgp->wgp_tasks);
2845 if (wgp->wgp_tasks != 0) 2987 if (wgp->wgp_tasks != 0)
2846 goto restart; 2988 goto restart;
2847 2989
2848 s = pserialize_read_enter(); 2990 s = pserialize_read_enter();
2849 wg_put_peer(wgp, &psref); 2991 wg_put_peer(wgp, &psref);
2850 } 2992 }
2851 pserialize_read_exit(s); 2993 pserialize_read_exit(s);
2852} 2994}
2853 2995
2854static void 2996static void
@@ -3026,27 +3168,27 @@ wg_worker_socreate(struct wg_softc *wg,  @@ -3026,27 +3168,27 @@ wg_worker_socreate(struct wg_softc *wg,
3026 return 0; 3168 return 0;
3027} 3169}
3028 3170
3029static int 3171static int
3030wg_worker_init(struct wg_softc *wg) 3172wg_worker_init(struct wg_softc *wg)
3031{ 3173{
3032 int error; 3174 int error;
3033 struct wg_worker *wgw; 3175 struct wg_worker *wgw;
3034 const char *ifname = wg->wg_if.if_xname; 3176 const char *ifname = wg->wg_if.if_xname;
3035 struct socket *so; 3177 struct socket *so;
3036 3178
3037 wgw = kmem_zalloc(sizeof(struct wg_worker), KM_SLEEP); 3179 wgw = kmem_zalloc(sizeof(struct wg_worker), KM_SLEEP);
3038 3180
3039 mutex_init(&wgw->wgw_lock, MUTEX_DEFAULT, IPL_NONE); 3181 mutex_init(&wgw->wgw_lock, MUTEX_DEFAULT, IPL_SOFTNET);
3040 cv_init(&wgw->wgw_cv, ifname); 3182 cv_init(&wgw->wgw_cv, ifname);
3041 wgw->wgw_todie = false; 3183 wgw->wgw_todie = false;
3042 wgw->wgw_wakeup_reasons = 0; 3184 wgw->wgw_wakeup_reasons = 0;
3043 3185
3044 error = wg_worker_socreate(wg, wgw, AF_INET, &so); 3186 error = wg_worker_socreate(wg, wgw, AF_INET, &so);
3045 if (error != 0) 3187 if (error != 0)
3046 goto error; 3188 goto error;
3047 wgw->wgw_so4 = so; 3189 wgw->wgw_so4 = so;
3048#ifdef INET6 3190#ifdef INET6
3049 error = wg_worker_socreate(wg, wgw, AF_INET6, &so); 3191 error = wg_worker_socreate(wg, wgw, AF_INET6, &so);
3050 if (error != 0) 3192 if (error != 0)
3051 goto error; 3193 goto error;
3052 wgw->wgw_so6 = so; 3194 wgw->wgw_so6 = so;
@@ -3119,123 +3261,80 @@ wg_session_hit_limits(struct wg_session  @@ -3119,123 +3261,80 @@ wg_session_hit_limits(struct wg_session
3119 } 3261 }
3120 3262
3121 return false; 3263 return false;
3122} 3264}
3123 3265
3124static void 3266static void
3125wg_peer_softint(void *arg) 3267wg_peer_softint(void *arg)
3126{ 3268{
3127 struct wg_peer *wgp = arg; 3269 struct wg_peer *wgp = arg;
3128 struct wg_session *wgs; 3270 struct wg_session *wgs;
3129 struct mbuf *m; 3271 struct mbuf *m;
3130 struct psref psref; 3272 struct psref psref;
3131 3273
3132 wgs = wg_get_stable_session(wgp, &psref); 3274 if ((wgs = wg_get_stable_session(wgp, &psref)) == NULL) {
3133 if (wgs->wgs_state != WGS_STATE_ESTABLISHED) { 
3134 /* XXX how to treat? */ 3275 /* XXX how to treat? */
3135 WG_TRACE("skipped"); 3276 WG_TRACE("skipped");
3136 goto out; 3277 return;
3137 } 3278 }
3138 if (wg_session_hit_limits(wgs)) { 3279 if (wg_session_hit_limits(wgs)) {
3139 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3280 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3140 goto out; 3281 goto out;
3141 } 3282 }
3142 WG_TRACE("running"); 3283 WG_TRACE("running");
3143 3284
3144 while ((m = pcq_get(wgp->wgp_q)) != NULL) { 3285 while ((m = pcq_get(wgp->wgp_q)) != NULL) {
3145 wg_send_data_msg(wgp, wgs, m); 3286 wg_send_data_msg(wgp, wgs, m);
3146 } 3287 }
3147out: 3288out:
3148 wg_put_session(wgs, &psref); 3289 wg_put_session(wgs, &psref);
3149} 3290}
3150 3291
3151static void 3292static void
3152wg_rekey_timer(void *arg) 3293wg_rekey_timer(void *arg)
3153{ 3294{
3154 struct wg_peer *wgp = arg; 3295 struct wg_peer *wgp = arg;
3155 3296
3156 mutex_enter(wgp->wgp_lock); 3297 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3157 if (__predict_true(wgp->wgp_state != WGP_STATE_DESTROYING)) { 
3158 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 
3159 } 
3160 mutex_exit(wgp->wgp_lock); 
3161} 3298}
3162 3299
3163static void 3300static void
3164wg_purge_pending_packets(struct wg_peer *wgp) 3301wg_purge_pending_packets(struct wg_peer *wgp)
3165{ 3302{
3166 struct mbuf *m; 3303 struct mbuf *m;
3167 3304
3168 while ((m = pcq_get(wgp->wgp_q)) != NULL) { 3305 while ((m = pcq_get(wgp->wgp_q)) != NULL) {
3169 m_freem(m); 3306 m_freem(m);
3170 } 3307 }
3171} 3308}
3172 3309
3173static void 3310static void
3174wg_handshake_timeout_timer(void *arg) 3311wg_handshake_timeout_timer(void *arg)
3175{ 3312{
3176 struct wg_peer *wgp = arg; 3313 struct wg_peer *wgp = arg;
3177 struct wg_session *wgs; 
3178 struct psref psref; 
3179 3314
3180 WG_TRACE("enter"); 3315 WG_TRACE("enter");
3181 3316
3182 mutex_enter(wgp->wgp_lock); 3317 wg_schedule_peer_task(wgp, WGP_TASK_RETRY_HANDSHAKE);
3183 if (__predict_false(wgp->wgp_state == WGP_STATE_DESTROYING)) { 
3184 mutex_exit(wgp->wgp_lock); 
3185 return; 
3186 } 
3187 mutex_exit(wgp->wgp_lock); 
3188 
3189 KASSERT(wgp->wgp_handshake_start_time != 0); 
3190 wgs = wg_get_unstable_session(wgp, &psref); 
3191 KASSERT(wgs->wgs_state == WGS_STATE_INIT_ACTIVE); 
3192 
3193 /* [W] 6.4 Handshake Initiation Retransmission */ 
3194 if ((time_uptime - wgp->wgp_handshake_start_time) > 
3195 wg_rekey_attempt_time) { 
3196 /* Give up handshaking */ 
3197 wgs->wgs_state = WGS_STATE_UNKNOWN; 
3198 wg_clear_states(wgs); 
3199 wgp->wgp_state = WGP_STATE_GIVEUP; 
3200 wgp->wgp_handshake_start_time = 0; 
3201 wg_put_session(wgs, &psref); 
3202 WG_TRACE("give up"); 
3203 /* 
3204 * If a new data packet comes, handshaking will be retried 
3205 * and a new session would be established at that time, 
3206 * however we don't want to send pending packets then. 
3207 */ 
3208 wg_purge_pending_packets(wgp); 
3209 return; 
3210 } 
3211 
3212 /* No response for an initiation message sent, retry handshaking */ 
3213 wgs->wgs_state = WGS_STATE_UNKNOWN; 
3214 wg_clear_states(wgs); 
3215 wg_put_session(wgs, &psref); 
3216 
3217 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 
3218} 3318}
3219 3319
3220static struct wg_peer * 3320static struct wg_peer *
3221wg_alloc_peer(struct wg_softc *wg) 3321wg_alloc_peer(struct wg_softc *wg)
3222{ 3322{
3223 struct wg_peer *wgp; 3323 struct wg_peer *wgp;
3224 3324
3225 wgp = kmem_zalloc(sizeof(*wgp), KM_SLEEP); 3325 wgp = kmem_zalloc(sizeof(*wgp), KM_SLEEP);
3226 3326
3227 wgp->wgp_sc = wg; 3327 wgp->wgp_sc = wg;
3228 wgp->wgp_state = WGP_STATE_INIT; 
3229 wgp->wgp_q = pcq_create(1024, KM_SLEEP); 3328 wgp->wgp_q = pcq_create(1024, KM_SLEEP);
3230 wgp->wgp_si = softint_establish(SOFTINT_NET, wg_peer_softint, wgp); 3329 wgp->wgp_si = softint_establish(SOFTINT_NET, wg_peer_softint, wgp);
3231 callout_init(&wgp->wgp_rekey_timer, CALLOUT_MPSAFE); 3330 callout_init(&wgp->wgp_rekey_timer, CALLOUT_MPSAFE);
3232 callout_setfunc(&wgp->wgp_rekey_timer, wg_rekey_timer, wgp); 3331 callout_setfunc(&wgp->wgp_rekey_timer, wg_rekey_timer, wgp);
3233 callout_init(&wgp->wgp_handshake_timeout_timer, CALLOUT_MPSAFE); 3332 callout_init(&wgp->wgp_handshake_timeout_timer, CALLOUT_MPSAFE);
3234 callout_setfunc(&wgp->wgp_handshake_timeout_timer, 3333 callout_setfunc(&wgp->wgp_handshake_timeout_timer,
3235 wg_handshake_timeout_timer, wgp); 3334 wg_handshake_timeout_timer, wgp);
3236 callout_init(&wgp->wgp_session_dtor_timer, CALLOUT_MPSAFE); 3335 callout_init(&wgp->wgp_session_dtor_timer, CALLOUT_MPSAFE);
3237 callout_setfunc(&wgp->wgp_session_dtor_timer, 3336 callout_setfunc(&wgp->wgp_session_dtor_timer,
3238 wg_session_dtor_timer, wgp); 3337 wg_session_dtor_timer, wgp);
3239 PSLIST_ENTRY_INIT(wgp, wgp_peerlist_entry); 3338 PSLIST_ENTRY_INIT(wgp, wgp_peerlist_entry);
3240 wgp->wgp_endpoint_changing = false; 3339 wgp->wgp_endpoint_changing = false;
3241 wgp->wgp_endpoint_available = false; 3340 wgp->wgp_endpoint_available = false;
@@ -3247,54 +3346,50 @@ wg_alloc_peer(struct wg_softc *wg) @@ -3247,54 +3346,50 @@ wg_alloc_peer(struct wg_softc *wg)
3247 wgp->wgp_endpoint0 = kmem_zalloc(sizeof(*wgp->wgp_endpoint0), KM_SLEEP); 3346 wgp->wgp_endpoint0 = kmem_zalloc(sizeof(*wgp->wgp_endpoint0), KM_SLEEP);
3248 psref_target_init(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class); 3347 psref_target_init(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class);
3249 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class); 3348 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class);
3250 3349
3251 struct wg_session *wgs; 3350 struct wg_session *wgs;
3252 wgp->wgp_session_stable = 3351 wgp->wgp_session_stable =
3253 kmem_zalloc(sizeof(*wgp->wgp_session_stable), KM_SLEEP); 3352 kmem_zalloc(sizeof(*wgp->wgp_session_stable), KM_SLEEP);
3254 wgp->wgp_session_unstable = 3353 wgp->wgp_session_unstable =
3255 kmem_zalloc(sizeof(*wgp->wgp_session_unstable), KM_SLEEP); 3354 kmem_zalloc(sizeof(*wgp->wgp_session_unstable), KM_SLEEP);
3256 wgs = wgp->wgp_session_stable; 3355 wgs = wgp->wgp_session_stable;
3257 wgs->wgs_peer = wgp; 3356 wgs->wgs_peer = wgp;
3258 wgs->wgs_state = WGS_STATE_UNKNOWN; 3357 wgs->wgs_state = WGS_STATE_UNKNOWN;
3259 psref_target_init(&wgs->wgs_psref, wg_psref_class); 3358 psref_target_init(&wgs->wgs_psref, wg_psref_class);
3260 wgs->wgs_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 
3261#ifndef __HAVE_ATOMIC64_LOADSTORE 3359#ifndef __HAVE_ATOMIC64_LOADSTORE
3262 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET); 3360 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET);
3263#endif 3361#endif
3264 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP); 3362 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP);
3265 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_NONE); 3363 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_SOFTNET);
3266 3364
3267 wgs = wgp->wgp_session_unstable; 3365 wgs = wgp->wgp_session_unstable;
3268 wgs->wgs_peer = wgp; 3366 wgs->wgs_peer = wgp;
3269 wgs->wgs_state = WGS_STATE_UNKNOWN; 3367 wgs->wgs_state = WGS_STATE_UNKNOWN;
3270 psref_target_init(&wgs->wgs_psref, wg_psref_class); 3368 psref_target_init(&wgs->wgs_psref, wg_psref_class);
3271 wgs->wgs_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 
3272#ifndef __HAVE_ATOMIC64_LOADSTORE 3369#ifndef __HAVE_ATOMIC64_LOADSTORE
3273 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET); 3370 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET);
3274#endif 3371#endif
3275 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP); 3372 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP);
3276 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_NONE); 3373 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_SOFTNET);
3277 3374
3278 return wgp; 3375 return wgp;
3279} 3376}
3280 3377
3281static void 3378static void
3282wg_destroy_peer(struct wg_peer *wgp) 3379wg_destroy_peer(struct wg_peer *wgp)
3283{ 3380{
3284 struct wg_session *wgs; 3381 struct wg_session *wgs;
3285 struct wg_softc *wg = wgp->wgp_sc; 3382 struct wg_softc *wg = wgp->wgp_sc;
3286 uint32_t index; 
3287 void *garbage; 
3288 3383
3289 /* Prevent new packets from this peer on any source address. */ 3384 /* Prevent new packets from this peer on any source address. */
3290 rw_enter(wg->wg_rwlock, RW_WRITER); 3385 rw_enter(wg->wg_rwlock, RW_WRITER);
3291 for (int i = 0; i < wgp->wgp_n_allowedips; i++) { 3386 for (int i = 0; i < wgp->wgp_n_allowedips; i++) {
3292 struct wg_allowedip *wga = &wgp->wgp_allowedips[i]; 3387 struct wg_allowedip *wga = &wgp->wgp_allowedips[i];
3293 struct radix_node_head *rnh = wg_rnh(wg, wga->wga_family); 3388 struct radix_node_head *rnh = wg_rnh(wg, wga->wga_family);
3294 struct radix_node *rn; 3389 struct radix_node *rn;
3295 3390
3296 KASSERT(rnh != NULL); 3391 KASSERT(rnh != NULL);
3297 rn = rnh->rnh_deladdr(&wga->wga_sa_addr, 3392 rn = rnh->rnh_deladdr(&wga->wga_sa_addr,
3298 &wga->wga_sa_mask, rnh); 3393 &wga->wga_sa_mask, rnh);
3299 if (rn == NULL) { 3394 if (rn == NULL) {
3300 char addrstr[128]; 3395 char addrstr[128];
@@ -3304,56 +3399,45 @@ wg_destroy_peer(struct wg_peer *wgp) @@ -3304,56 +3399,45 @@ wg_destroy_peer(struct wg_peer *wgp)
3304 } 3399 }
3305 } 3400 }
3306 rw_exit(wg->wg_rwlock); 3401 rw_exit(wg->wg_rwlock);
3307 3402
3308 /* Purge pending packets. */ 3403 /* Purge pending packets. */
3309 wg_purge_pending_packets(wgp); 3404 wg_purge_pending_packets(wgp);
3310 3405
3311 /* Halt all packet processing and timeouts. */ 3406 /* Halt all packet processing and timeouts. */
3312 softint_disestablish(wgp->wgp_si); 3407 softint_disestablish(wgp->wgp_si);
3313 callout_halt(&wgp->wgp_rekey_timer, NULL); 3408 callout_halt(&wgp->wgp_rekey_timer, NULL);
3314 callout_halt(&wgp->wgp_handshake_timeout_timer, NULL); 3409 callout_halt(&wgp->wgp_handshake_timeout_timer, NULL);
3315 callout_halt(&wgp->wgp_session_dtor_timer, NULL); 3410 callout_halt(&wgp->wgp_session_dtor_timer, NULL);
3316 3411
3317 /* Remove the sessions by index. */ 
3318 if ((index = wgp->wgp_session_stable->wgs_sender_index) != 0) { 
3319 thmap_del(wg->wg_sessions_byindex, &index, sizeof index); 
3320 wgp->wgp_session_stable->wgs_sender_index = 0; 
3321 } 
3322 if ((index = wgp->wgp_session_unstable->wgs_sender_index) != 0) { 
3323 thmap_del(wg->wg_sessions_byindex, &index, sizeof index); 
3324 wgp->wgp_session_unstable->wgs_sender_index = 0; 
3325 } 
3326 
3327 /* Wait for all thmap_gets to complete, and GC. */ 
3328 garbage = thmap_stage_gc(wg->wg_sessions_byindex); 
3329 mutex_enter(wgp->wgp_lock); 
3330 pserialize_perform(wgp->wgp_psz); 
3331 mutex_exit(wgp->wgp_lock); 
3332 thmap_gc(wg->wg_sessions_byindex, garbage); 
3333 
3334 wgs = wgp->wgp_session_unstable; 3412 wgs = wgp->wgp_session_unstable;
3335 psref_target_destroy(&wgs->wgs_psref, wg_psref_class); 3413 if (wgs->wgs_state != WGS_STATE_UNKNOWN) {
3336 mutex_obj_free(wgs->wgs_lock); 3414 mutex_enter(wgp->wgp_lock);
 3415 wg_destroy_session(wg, wgs);
 3416 mutex_exit(wgp->wgp_lock);
 3417 }
3337 mutex_destroy(&wgs->wgs_recvwin->lock); 3418 mutex_destroy(&wgs->wgs_recvwin->lock);
3338 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin)); 3419 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin));
3339#ifndef __HAVE_ATOMIC64_LOADSTORE 3420#ifndef __HAVE_ATOMIC64_LOADSTORE
3340 mutex_destroy(&wgs->wgs_send_counter_lock); 3421 mutex_destroy(&wgs->wgs_send_counter_lock);
3341#endif 3422#endif
3342 kmem_free(wgs, sizeof(*wgs)); 3423 kmem_free(wgs, sizeof(*wgs));
3343 3424
3344 wgs = wgp->wgp_session_stable; 3425 wgs = wgp->wgp_session_stable;
3345 psref_target_destroy(&wgs->wgs_psref, wg_psref_class); 3426 if (wgs->wgs_state != WGS_STATE_UNKNOWN) {
3346 mutex_obj_free(wgs->wgs_lock); 3427 mutex_enter(wgp->wgp_lock);
 3428 wg_destroy_session(wg, wgs);
 3429 mutex_exit(wgp->wgp_lock);
 3430 }
3347 mutex_destroy(&wgs->wgs_recvwin->lock); 3431 mutex_destroy(&wgs->wgs_recvwin->lock);
3348 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin)); 3432 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin));
3349#ifndef __HAVE_ATOMIC64_LOADSTORE 3433#ifndef __HAVE_ATOMIC64_LOADSTORE
3350 mutex_destroy(&wgs->wgs_send_counter_lock); 3434 mutex_destroy(&wgs->wgs_send_counter_lock);
3351#endif 3435#endif
3352 kmem_free(wgs, sizeof(*wgs)); 3436 kmem_free(wgs, sizeof(*wgs));
3353 3437
3354 psref_target_destroy(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class); 3438 psref_target_destroy(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class);
3355 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class); 3439 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class);
3356 kmem_free(wgp->wgp_endpoint, sizeof(*wgp->wgp_endpoint)); 3440 kmem_free(wgp->wgp_endpoint, sizeof(*wgp->wgp_endpoint));
3357 kmem_free(wgp->wgp_endpoint0, sizeof(*wgp->wgp_endpoint0)); 3441 kmem_free(wgp->wgp_endpoint0, sizeof(*wgp->wgp_endpoint0));
3358 3442
3359 pserialize_destroy(wgp->wgp_psz); 3443 pserialize_destroy(wgp->wgp_psz);
@@ -3376,27 +3460,26 @@ restart: @@ -3376,27 +3460,26 @@ restart:
3376 if (wgp->wgp_name[0]) { 3460 if (wgp->wgp_name[0]) {
3377 wgp0 = thmap_del(wg->wg_peers_byname, wgp->wgp_name, 3461 wgp0 = thmap_del(wg->wg_peers_byname, wgp->wgp_name,
3378 strlen(wgp->wgp_name)); 3462 strlen(wgp->wgp_name));
3379 KASSERT(wgp0 == wgp); 3463 KASSERT(wgp0 == wgp);
3380 garbage_byname = thmap_stage_gc(wg->wg_peers_byname); 3464 garbage_byname = thmap_stage_gc(wg->wg_peers_byname);
3381 } 3465 }
3382 wgp0 = thmap_del(wg->wg_peers_bypubkey, wgp->wgp_pubkey, 3466 wgp0 = thmap_del(wg->wg_peers_bypubkey, wgp->wgp_pubkey,
3383 sizeof(wgp->wgp_pubkey)); 3467 sizeof(wgp->wgp_pubkey));
3384 KASSERT(wgp0 == wgp); 3468 KASSERT(wgp0 == wgp);
3385 garbage_bypubkey = thmap_stage_gc(wg->wg_peers_bypubkey); 3469 garbage_bypubkey = thmap_stage_gc(wg->wg_peers_bypubkey);
3386 WG_PEER_WRITER_REMOVE(wgp); 3470 WG_PEER_WRITER_REMOVE(wgp);
3387 wg->wg_npeers--; 3471 wg->wg_npeers--;
3388 mutex_enter(wgp->wgp_lock); 3472 mutex_enter(wgp->wgp_lock);
3389 wgp->wgp_state = WGP_STATE_DESTROYING; 
3390 pserialize_perform(wgp->wgp_psz); 3473 pserialize_perform(wgp->wgp_psz);
3391 mutex_exit(wgp->wgp_lock); 3474 mutex_exit(wgp->wgp_lock);
3392 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry); 3475 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry);
3393 break; 3476 break;
3394 } 3477 }
3395 mutex_exit(wg->wg_lock); 3478 mutex_exit(wg->wg_lock);
3396 3479
3397 if (wgp == NULL) 3480 if (wgp == NULL)
3398 return; 3481 return;
3399 3482
3400 psref_target_destroy(&wgp->wgp_psref, wg_psref_class); 3483 psref_target_destroy(&wgp->wgp_psref, wg_psref_class);
3401 3484
3402 wg_destroy_peer(wgp); 3485 wg_destroy_peer(wgp);
@@ -3413,27 +3496,26 @@ wg_destroy_peer_name(struct wg_softc *wg @@ -3413,27 +3496,26 @@ wg_destroy_peer_name(struct wg_softc *wg
3413 void *garbage_byname, *garbage_bypubkey; 3496 void *garbage_byname, *garbage_bypubkey;
3414 3497
3415 mutex_enter(wg->wg_lock); 3498 mutex_enter(wg->wg_lock);
3416 wgp = thmap_del(wg->wg_peers_byname, name, strlen(name)); 3499 wgp = thmap_del(wg->wg_peers_byname, name, strlen(name));
3417 if (wgp != NULL) { 3500 if (wgp != NULL) {
3418 wgp0 = thmap_del(wg->wg_peers_bypubkey, wgp->wgp_pubkey, 3501 wgp0 = thmap_del(wg->wg_peers_bypubkey, wgp->wgp_pubkey,
3419 sizeof(wgp->wgp_pubkey)); 3502 sizeof(wgp->wgp_pubkey));
3420 KASSERT(wgp0 == wgp); 3503 KASSERT(wgp0 == wgp);
3421 garbage_byname = thmap_stage_gc(wg->wg_peers_byname); 3504 garbage_byname = thmap_stage_gc(wg->wg_peers_byname);
3422 garbage_bypubkey = thmap_stage_gc(wg->wg_peers_bypubkey); 3505 garbage_bypubkey = thmap_stage_gc(wg->wg_peers_bypubkey);
3423 WG_PEER_WRITER_REMOVE(wgp); 3506 WG_PEER_WRITER_REMOVE(wgp);
3424 wg->wg_npeers--; 3507 wg->wg_npeers--;
3425 mutex_enter(wgp->wgp_lock); 3508 mutex_enter(wgp->wgp_lock);
3426 wgp->wgp_state = WGP_STATE_DESTROYING; 
3427 pserialize_perform(wgp->wgp_psz); 3509 pserialize_perform(wgp->wgp_psz);
3428 mutex_exit(wgp->wgp_lock); 3510 mutex_exit(wgp->wgp_lock);
3429 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry); 3511 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry);
3430 } 3512 }
3431 mutex_exit(wg->wg_lock); 3513 mutex_exit(wg->wg_lock);
3432 3514
3433 if (wgp == NULL) 3515 if (wgp == NULL)
3434 return ENOENT; 3516 return ENOENT;
3435 3517
3436 psref_target_destroy(&wgp->wgp_psref, wg_psref_class); 3518 psref_target_destroy(&wgp->wgp_psref, wg_psref_class);
3437 3519
3438 wg_destroy_peer(wgp); 3520 wg_destroy_peer(wgp);
3439 thmap_gc(wg->wg_peers_byname, garbage_byname); 3521 thmap_gc(wg->wg_peers_byname, garbage_byname);
@@ -3597,95 +3679,93 @@ wg_pick_peer_by_sa(struct wg_softc *wg,  @@ -3597,95 +3679,93 @@ wg_pick_peer_by_sa(struct wg_softc *wg,
3597 3679
3598out: 3680out:
3599 rw_exit(wg->wg_rwlock); 3681 rw_exit(wg->wg_rwlock);
3600 return wgp; 3682 return wgp;
3601} 3683}
3602 3684
3603static void 3685static void
3604wg_fill_msg_data(struct wg_softc *wg, struct wg_peer *wgp, 3686wg_fill_msg_data(struct wg_softc *wg, struct wg_peer *wgp,
3605 struct wg_session *wgs, struct wg_msg_data *wgmd) 3687 struct wg_session *wgs, struct wg_msg_data *wgmd)
3606{ 3688{
3607 3689
3608 memset(wgmd, 0, sizeof(*wgmd)); 3690 memset(wgmd, 0, sizeof(*wgmd));
3609 wgmd->wgmd_type = htole32(WG_MSG_TYPE_DATA); 3691 wgmd->wgmd_type = htole32(WG_MSG_TYPE_DATA);
3610 wgmd->wgmd_receiver = wgs->wgs_receiver_index; 3692 wgmd->wgmd_receiver = wgs->wgs_remote_index;
3611 /* [W] 5.4.6: msg.counter := Nm^send */ 3693 /* [W] 5.4.6: msg.counter := Nm^send */
3612 /* [W] 5.4.6: Nm^send := Nm^send + 1 */ 3694 /* [W] 5.4.6: Nm^send := Nm^send + 1 */
3613 wgmd->wgmd_counter = htole64(wg_session_inc_send_counter(wgs)); 3695 wgmd->wgmd_counter = htole64(wg_session_inc_send_counter(wgs));
3614 WG_DLOG("counter=%"PRIu64"\n", le64toh(wgmd->wgmd_counter)); 3696 WG_DLOG("counter=%"PRIu64"\n", le64toh(wgmd->wgmd_counter));
3615} 3697}
3616 3698
3617static int 3699static int
3618wg_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 3700wg_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
3619 const struct rtentry *rt) 3701 const struct rtentry *rt)
3620{ 3702{
3621 struct wg_softc *wg = ifp->if_softc; 3703 struct wg_softc *wg = ifp->if_softc;
3622 int error = 0; 3704 struct wg_peer *wgp = NULL;
 3705 struct wg_session *wgs = NULL;
 3706 struct psref wgp_psref, wgs_psref;
3623 int bound; 3707 int bound;
3624 struct psref psref; 3708 int error;
 3709
 3710 bound = curlwp_bind();
3625 3711
3626 /* TODO make the nest limit configurable via sysctl */ 3712 /* TODO make the nest limit configurable via sysctl */
3627 error = if_tunnel_check_nesting(ifp, m, 1); 3713 error = if_tunnel_check_nesting(ifp, m, 1);
3628 if (error != 0) { 3714 if (error) {
3629 m_freem(m); 
3630 WGLOG(LOG_ERR, "tunneling loop detected and packet dropped\n"); 3715 WGLOG(LOG_ERR, "tunneling loop detected and packet dropped\n");
3631 return error; 3716 goto out;
3632 } 3717 }
3633 3718
3634 bound = curlwp_bind(); 
3635 
3636 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family); 3719 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
3637 3720
3638 bpf_mtap_af(ifp, dst->sa_family, m, BPF_D_OUT); 3721 bpf_mtap_af(ifp, dst->sa_family, m, BPF_D_OUT);
3639 3722
3640 m->m_flags &= ~(M_BCAST|M_MCAST); 3723 m->m_flags &= ~(M_BCAST|M_MCAST);
3641 3724
3642 struct wg_peer *wgp = wg_pick_peer_by_sa(wg, dst, &psref); 3725 wgp = wg_pick_peer_by_sa(wg, dst, &wgp_psref);
3643 if (wgp == NULL) { 3726 if (wgp == NULL) {
3644 WG_TRACE("peer not found"); 3727 WG_TRACE("peer not found");
3645 error = EHOSTUNREACH; 3728 error = EHOSTUNREACH;
3646 goto error; 3729 goto out;
3647 } 3730 }
3648 3731
3649 /* Clear checksum-offload flags. */ 3732 /* Clear checksum-offload flags. */
3650 m->m_pkthdr.csum_flags = 0; 3733 m->m_pkthdr.csum_flags = 0;
3651 m->m_pkthdr.csum_data = 0; 3734 m->m_pkthdr.csum_data = 0;
3652 3735
3653 if (!pcq_put(wgp->wgp_q, m)) { 3736 if (!pcq_put(wgp->wgp_q, m)) {
3654 error = ENOBUFS; 3737 error = ENOBUFS;
3655 goto error; 3738 goto out;
3656 } 3739 }
 3740 m = NULL; /* consumed */
3657 3741
3658 struct psref psref_wgs; 3742 wgs = wg_get_stable_session(wgp, &wgs_psref);
3659 struct wg_session *wgs; 3743 if (wgs != NULL && !wg_session_hit_limits(wgs)) {
3660 wgs = wg_get_stable_session(wgp, &psref_wgs); 
3661 if (wgs->wgs_state == WGS_STATE_ESTABLISHED && 
3662 !wg_session_hit_limits(wgs)) { 
3663 kpreempt_disable(); 3744 kpreempt_disable();
3664 softint_schedule(wgp->wgp_si); 3745 softint_schedule(wgp->wgp_si);
3665 kpreempt_enable(); 3746 kpreempt_enable();
3666 WG_TRACE("softint scheduled"); 3747 WG_TRACE("softint scheduled");
3667 } else { 3748 } else {
3668 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3749 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3669 WG_TRACE("softint NOT scheduled"); 3750 WG_TRACE("softint NOT scheduled");
3670 } 3751 }
3671 wg_put_session(wgs, &psref_wgs); 3752 error = 0;
3672 wg_put_peer(wgp, &psref); 
3673 
3674 return 0; 
3675 3753
3676error: 3754out:
 3755 if (wgs != NULL)
 3756 wg_put_session(wgs, &wgs_psref);
3677 if (wgp != NULL) 3757 if (wgp != NULL)
3678 wg_put_peer(wgp, &psref); 3758 wg_put_peer(wgp, &wgp_psref);
3679 if (m != NULL) 3759 if (m != NULL)
3680 m_freem(m); 3760 m_freem(m);
3681 curlwp_bindx(bound); 3761 curlwp_bindx(bound);
3682 return error; 3762 return error;
3683} 3763}
3684 3764
3685static int 3765static int
3686wg_send_udp(struct wg_peer *wgp, struct mbuf *m) 3766wg_send_udp(struct wg_peer *wgp, struct mbuf *m)
3687{ 3767{
3688 struct psref psref; 3768 struct psref psref;
3689 struct wg_sockaddr *wgsa; 3769 struct wg_sockaddr *wgsa;
3690 int error; 3770 int error;
3691 struct socket *so; 3771 struct socket *so;