From 4363a424d042f0858356c2dc7077cff82ee2ff7f Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 24 Oct 2026 15:47:28 +0200 Subject: [PATCH] Reject incomplete groups and refresh BGP subnet ownership --- src/radio/radio.c | 8 +++++--- src/routing_layer/topo_group.c | 29 +++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/radio/radio.c b/src/radio/radio.c index 89526f92..4cd6d35e 100644 --- a/src/radio/radio.c +++ b/src/radio/radio.c @@ -90,10 +90,12 @@ int radio_init(struct TOPO_GROUP* group) { if (!ctx) { DEBUG_ERROR(DEBUG_CATEGORY_RADIO, "%s: alloc failed", RADIO_ID); return -1; } ctx->group = group; ctx->stream_id = (uint16_t)(get_time_tb() & 0xFFFF); - group->radio = ctx; - ctx->talker_timer = uasync_set_timeout(group->instance->ua, RADIO_TALKER_TIMEOUT_TB, ctx, radio_talker_timer_cb, "radio_talker"); - if (!ctx->talker_timer) DEBUG_ERROR(DEBUG_CATEGORY_RADIO, "%s: init talker_timer failed grp=%016llx", RADIO_ID, (unsigned long long)group->group_id); + if (!ctx->talker_timer) { + DEBUG_ERROR(DEBUG_CATEGORY_RADIO, "%s: init talker_timer failed grp=%016llx", RADIO_ID, (unsigned long long)group->group_id); + u_free(ctx); return -1; + } + group->radio = ctx; DEBUG_INFO(DEBUG_CATEGORY_RADIO, "%s: init ok grp=%016llx", RADIO_ID, (unsigned long long)group->group_id); return 0; diff --git a/src/routing_layer/topo_group.c b/src/routing_layer/topo_group.c index f9a679b2..a8e4c543 100644 --- a/src/routing_layer/topo_group.c +++ b/src/routing_layer/topo_group.c @@ -56,6 +56,7 @@ static void topo_group_routes_changed(struct TOPO_GROUP* group, struct TOPO_GROU static void topo_group_prune_paths(struct TOPO_GROUP_CONN_ITEM* peer, int all); static void topo_exchange_watch(void* arg); static void topo_tx_fail(struct TOPO_GROUP_CONN_ITEM* peer); +static void topo_group_destroy(struct TOPO_GROUP* group); static void topo_exchange_cancel(struct TOPO_GROUP_CONN_ITEM* peer) { if (peer->exchange_timer) uasync_cancel_timeout(peer->group->instance->ua, peer->exchange_timer); @@ -602,7 +603,10 @@ static struct TOPO_GROUP* topo_group_create(struct UTUN_INSTANCE* instance, uint group->group_type = group_type; group->instance = instance; - sc_derive_ed25519_pubkey(instance->my_keys.private_key, group->ed25519_public_key); + if (sc_derive_ed25519_pubkey(instance->my_keys.private_key, group->ed25519_public_key) != SC_OK) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "cannot derive group identity group=%016llx", (unsigned long long)group_id); + queue_entry_free(qe); return NULL; + } DEBUG_INFO(DEBUG_CATEGORY_BGP, "Ed25519 pubkey derived from X25519 private key"); group->nodes = queue_new(instance->ua, BGP_NODES_HASH_SIZE, offsetof(struct TOPO_GROUP_NODE, node_id) - sizeof(struct ll_entry), 8, "group_nodes"); @@ -612,15 +616,20 @@ static struct TOPO_GROUP* topo_group_create(struct UTUN_INSTANCE* instance, uint if (!group->senders_list) { queue_free(group->nodes); queue_entry_free(qe); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "senders_list queue creation failed"); return NULL; } group->local_node = NULL; - topo_group_update_my_nodeinfo(instance, group); + if (topo_group_update_my_nodeinfo(instance, group) < 0) goto fail; group->conn_mgr = conn_mgr_init(group); + if (!group->conn_mgr) goto fail; - broadcast_init(group); - radio_init(group); + if (broadcast_init(group) < 0 || radio_init(group) < 0) goto fail; DEBUG_INFO(DEBUG_CATEGORY_BGP, "TOPO group created: group_id=%016llx", (unsigned long long)group_id); return group; +fail: + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "group creation rolled back group=%016llx local_node=%p conn_mgr=%p broadcast=%p radio=%p", + (unsigned long long)group_id, (void*)group->local_node, (void*)group->conn_mgr, + (void*)group->broadcast, (void*)group->radio); + topo_group_destroy(group); queue_entry_free(qe); return NULL; } /* Полностью разрушает группу: recovery, connect, broadcast, conn_mgr, узлы. */ @@ -920,14 +929,16 @@ void topo_group_set_radio(struct TOPO_GROUP* group, int on) { (unsigned long long)group->group_id, group->channel_id); return; } + uint8_t previous = group->radio_active; group->radio_active = v; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "set_radio: %s grp=%016llx ch=%s", - v ? "ON" : "OFF", (unsigned long long)group->group_id, group->channel_id); if (topo_group_update_my_nodeinfo(group->instance, group) < 0) { + group->radio_active = previous; DEBUG_ERROR(DEBUG_CATEGORY_BGP, "set_radio: cannot update local NODEINFO grp=%016llx ch=%s radio=%u", (unsigned long long)group->group_id, group->channel_id, v); return; } + DEBUG_INFO(DEBUG_CATEGORY_BGP, "set_radio: %s grp=%016llx ch=%s", + v ? "ON" : "OFF", (unsigned long long)group->group_id, group->channel_id); /* Свой мембер обновляется через те же подписки, что и удалённые BGP-узлы. */ for (struct topo_node_cbk_entry* cb = group->node_cbks; cb; cb = cb->next) cb->fn(group, group->instance->node_id, TOPO_NODE_EVENT_UPDATE, cb->arg); @@ -1191,8 +1202,10 @@ static void topo_group_routes_changed(struct TOPO_GROUP* group, struct TOPO_GROU node->paths ? queue_entry_count(node->paths) : 0, (unsigned long long)(best ? best->conn->peer_node_id : 0), best ? best->hop_count : 0); if (group->group_type != TOPO_GROUP_TYPE_CHAT && group->instance->rt) { - if (best && node->subnets) route_insert(group->instance->rt, node); - else route_delete(group->instance->rt, node); + route_delete(group->instance->rt, node); + if (best && node->subnets && node->subnets->v4_subnets && !route_insert(group->instance->rt, node)) + DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "BGP IPv4 routes rejected: group=%016llx node=%016llx; previous routes removed", + (unsigned long long)group->group_id, (unsigned long long)id); } topo_fire_nodeinfo_cbk(group->instance, group, node); if (!node->paths) {