Index | Thread | Search

From:
ido@wireplug.org
Subject:
wg(4): don't start timers if peer has no endpoint
To:
tech@openbsd.org
Date:
Tue, 23 Dec 2025 19:14:19 +0000

Download raw body.

Thread
  • ido@wireplug.org:

    wg(4): don't start timers if peer has no endpoint

Currently, if a wg(4) interface is configured with a peer that has no wgendpoint but does have a wgpka value,
that peer's timers are still started, resulting in pointless attempts to perform a handshake
while increasing its tx counter, even though nothing is actually being sent.

There are two ways to assign an endpoint to such a peer: through an ioctl (e.g., ifconfig)
or by receiving a valid handshake initiation packet.

The patch below postpones calling wg_timers_enable() until either of these events occurs.

I've been running this against current on amd64 for many weeks with no issues.

---
Ido


diff --git sys/net/if_wg.c sys/net/if_wg.c
index 79f0e2ad639..c0488a9a25a 100644
--- sys/net/if_wg.c
+++ sys/net/if_wg.c
@@ -555,6 +555,7 @@ wg_peer_set_endpoint_from_tag(struct wg_peer *peer, struct wg_tag *t)
 	mtx_enter(&peer->p_endpoint_mtx);
 	peer->p_endpoint = t->t_endpoint;
 	mtx_leave(&peer->p_endpoint_mtx);
+	wg_timers_enable(&peer->p_timers);
 }
 
 void
@@ -565,6 +566,7 @@ wg_peer_set_sockaddr(struct wg_peer *peer, struct sockaddr *remote)
 	       sizeof(peer->p_endpoint.e_remote));
 	bzero(&peer->p_endpoint.e_local, sizeof(peer->p_endpoint.e_local));
 	mtx_leave(&peer->p_endpoint_mtx);
+	wg_timers_enable(&peer->p_timers);
 }
 
 int
@@ -582,6 +584,18 @@ wg_peer_get_sockaddr(struct wg_peer *peer, struct sockaddr *remote)
 	return ret;
 }
 
+int
+wg_peer_has_endpoint(struct wg_peer *peer)
+{
+	int	ret = 0;
+
+	mtx_enter(&peer->p_endpoint_mtx);
+	if (peer->p_endpoint.e_remote.r_sa.sa_family != AF_UNSPEC)
+		ret = 1;
+	mtx_leave(&peer->p_endpoint_mtx);
+	return ret;
+}
+
 void
 wg_peer_clear_src(struct wg_peer *peer)
 {
@@ -958,6 +972,7 @@ void
 wg_timers_init(struct wg_timers *t)
 {
 	bzero(t, sizeof(*t));
+	t->t_disabled = 1;
 	mtx_init_flags(&t->t_mtx, IPL_NET, "wg_timers", 0);
 	mtx_init(&t->t_handshake_mtx, IPL_NET);
 
@@ -998,8 +1013,8 @@ void
 wg_timers_set_persistent_keepalive(struct wg_timers *t, uint16_t interval)
 {
 	mtx_enter(&t->t_mtx);
+	t->t_persistent_keepalive_interval = interval;
 	if (!t->t_disabled) {
-		t->t_persistent_keepalive_interval = interval;
 		wg_timers_run_persistent_keepalive(t);
 	}
 	mtx_leave(&t->t_mtx);
@@ -2630,8 +2645,10 @@ wg_up(struct wg_softc *sc)
 		ret = wg_bind(sc, &sc->sc_udp_port, &sc->sc_udp_rtable);
 		if (ret == 0) {
 			TAILQ_FOREACH(peer, &sc->sc_peer_seq, p_seq_entry) {
-				wg_timers_enable(&peer->p_timers);
-				wg_queue_out(sc, peer);
+				if (wg_peer_has_endpoint(peer)) {
+					wg_timers_enable(&peer->p_timers);
+					wg_queue_out(sc, peer);
+				}
 			}
 		}
 		rw_exit_write(&sc->sc_lock);