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 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);