Download raw body.
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);
wg(4): don't start timers if peer has no endpoint