From: Felix Fietkau Date: Mon, 21 Aug 2023 20:27:37 +0000 (+0200) Subject: pex: track indirect hosts (reachable via gateway) as peers without adding them to wg X-Git-Url: http://git.openwrt.org/feed/routing.git;lede-17.01?a=commitdiff_plain;h=29aacb9386e058408ed8a835bad37d58d3c9d57f;p=project%2Funetd.git pex: track indirect hosts (reachable via gateway) as peers without adding them to wg This allows other hosts to respond to them via global PEX, in order to help them find their gateway Signed-off-by: Felix Fietkau --- diff --git a/host.c b/host.c index e4e38d3..2bfc500 100644 --- a/host.c +++ b/host.c @@ -40,6 +40,9 @@ network_peer_update(struct vlist_tree *tree, return; } + if ((h_new ? h_new : h_old)->indirect) + return; + if (h_new) ret = wg_peer_update(net, h_new, h_old ? WG_PEER_UPDATE : WG_PEER_CREATE); else @@ -335,10 +338,11 @@ __network_hosts_update_done(struct network *net, bool free_net) avl_for_each_element(&net->hosts, host, node) { if (host == local) continue; + host->peer.indirect = false; if (host->gateway && strcmp(host->gateway, local_name) != 0) - continue; + host->peer.indirect = true; if (local->gateway && strcmp(local->gateway, network_host_name(host)) != 0) - continue; + host->peer.indirect = true; vlist_add(&net->peers, &host->peer.node, host->peer.key); } @@ -407,7 +411,7 @@ network_hosts_connect_cb(struct uloop_timeout *t) wg_peer_refresh(net); vlist_for_each_element(&net->peers, peer, node) { - if (peer->state.connected) + if (peer->state.connected || peer->indirect) continue; ep = network_peer_next_endpoint(peer); diff --git a/host.h b/host.h index cb4085e..56d359c 100644 --- a/host.h +++ b/host.h @@ -23,6 +23,7 @@ struct network_peer { int port; int pex_port; bool dynamic; + bool indirect; struct { int connect_attempt; diff --git a/pex-stun.c b/pex-stun.c index 444612b..0be3160 100644 --- a/pex-stun.c +++ b/pex-stun.c @@ -22,7 +22,7 @@ static bool has_connected_peer(struct network *net, bool pex) if (pex && !peer->pex_port) continue; - if (peer->state.connected) + if (peer->state.connected || peer->indirect) return true; } diff --git a/pex.c b/pex.c index 7db9ab8..61977cc 100644 --- a/pex.c +++ b/pex.c @@ -39,7 +39,7 @@ pex_msg_init_ext(struct network *net, uint8_t opcode, bool ext) } static struct network_peer * -pex_msg_peer(struct network *net, const uint8_t *id) +pex_msg_peer(struct network *net, const uint8_t *id, bool allow_indirect) { struct network_peer *peer; uint8_t key[WG_KEY_LEN] = {}; @@ -50,6 +50,8 @@ pex_msg_peer(struct network *net, const uint8_t *id) D_NET(net, "can't find peer %s", pex_peer_id_str(id)); return NULL; } + if (peer->indirect && !allow_indirect) + return NULL; return peer; } @@ -154,7 +156,7 @@ network_pex_handle_endpoint_change(struct network *net, struct network_peer *pee struct network_peer *cur; vlist_for_each_element(&net->peers, cur, node) { - if (cur == peer || !cur->state.connected) + if (cur == peer || !cur->state.connected || cur->indirect) continue; pex_msg_init(net, PEX_MSG_NOTIFY_PEERS); @@ -483,7 +485,7 @@ network_pex_recv_peers(struct network *net, struct network_peer *peer, continue; } - cur = pex_msg_peer(net, data->peer_id); + cur = pex_msg_peer(net, data->peer_id, false); if (!cur || cur == peer) continue; @@ -507,7 +509,7 @@ network_pex_recv_query(struct network *net, struct network_peer *peer, pex_msg_init(net, PEX_MSG_NOTIFY_PEERS); for (; len >= 8; data += 8, len -= 8) { - cur = pex_msg_peer(net, data); + cur = pex_msg_peer(net, data, false); if (!cur || !cur->state.connected) continue; @@ -717,7 +719,7 @@ network_pex_fd_cb(struct uloop_fd *fd, unsigned int events) if (!hdr) continue; - peer = pex_msg_peer(net, hdr->id); + peer = pex_msg_peer(net, hdr->id, false); if (!peer) continue; @@ -958,7 +960,7 @@ global_pex_recv(void *msg, size_t msg_len, struct sockaddr_in6 *addr) case PEX_MSG_PONG: break; case PEX_MSG_UPDATE_REQUEST: - peer = pex_msg_peer(net, hdr->id); + peer = pex_msg_peer(net, hdr->id, true); network_pex_recv_update_request(net, peer, data, hdr->len, addr); break; @@ -974,7 +976,7 @@ global_pex_recv(void *msg, size_t msg_len, struct sockaddr_in6 *addr) ep_idx = ENDPOINT_TYPE_ENDPOINT_PORT_NOTIFY; fallthrough; case PEX_MSG_ENDPOINT_NOTIFY: - peer = pex_msg_peer(net, hdr->id); + peer = pex_msg_peer(net, hdr->id, true); if (!peer) break; diff --git a/wg.c b/wg.c index 64687f1..1f80e00 100644 --- a/wg.c +++ b/wg.c @@ -47,7 +47,7 @@ struct network_peer *wg_peer_update_start(struct network *net, const uint8_t *ke struct network_peer *peer; peer = vlist_find(&net->peers, key, peer, node); - if (!peer) + if (!peer || peer->indirect) return NULL; peer->state.handshake = false;