Browse Source

TOPO_BGP -> TOPO_GROUP: multi-group support

- Renamed TOPO_BGP to TOPO_GROUP with topo_group_id (64bit)
- Added TOPO_GROUPS container (ll_queue group_list) in UTUN_INSTANCE
- Memory pools moved from TOPO_GROUP to TOPO_GROUPS (instance-level)
- Default group: TOPO_GROUP_UTUN = 0x8000000000000000
- topo_groups_get_default() searches by group_id, not just first entry
- All topo_bgp_* renamed to topo_group_*; function signatures updated
- Files: topo_bgp.h/c -> topo_group.h/c
chatgui
Evgeny 3 months ago
parent
commit
28e5950d29
  1. 4
      src/Makefile.am
  2. 78
      src/conn_mgr.c
  3. 2
      src/conn_mgr.h
  4. 25
      src/control_server.c
  5. 10
      src/db_sync.c
  6. 6
      src/etcp.c
  7. 37
      src/etcp_connections.c
  8. 52
      src/etcp_router.c
  9. 8
      src/msg_transport.c
  10. 7
      src/route_connectivity.c
  11. 50
      src/route_ping.c
  12. 14
      src/route_ping.h
  13. 465
      src/topo_group.c
  14. 75
      src/topo_group.h
  15. 124
      src/topo_node.c
  16. 18
      src/topo_node.h
  17. 10
      src/topo_node_lmdb.c
  18. 10
      src/topo_node_lmdb.h
  19. 16
      src/utun_instance.c
  20. 5
      src/utun_instance.h
  21. 2
      tests/test_bgp_route_exchange.c
  22. 12
      tests/test_bgp_triangle.c
  23. 6
      tests/test_conn_mgr.c
  24. 12
      tests/test_etcp_connect.c
  25. 2
      tests/test_etcp_router.c
  26. 6
      tests/test_etcp_router_reconnect.c
  27. 39
      tests/test_etcp_router_unit.c
  28. 16
      tests/test_ipv6_sockets.c
  29. 30
      tests/test_nat_detection.c
  30. 6
      tests/test_nat_transport.c
  31. 2
      tests/test_route_lib.c
  32. 10
      tests/test_route_ping.c
  33. 4
      tests/test_stcp_traffic.c
  34. 2
      tools/chatgui/libutun/CMakeLists.txt
  35. 10
      tools/chatgui/transport/chat_core.c

4
src/Makefile.am

@ -9,7 +9,7 @@ utun_CORE_SOURCES = \
config_updater.c \ config_updater.c \
route_lib.c \ route_lib.c \
route6_lib.c \ route6_lib.c \
topo_bgp.c \ topo_group.c \
route_ping.c \ route_ping.c \
topo_node.c \ topo_node.c \
topo_node_lmdb.c \ topo_node_lmdb.c \
@ -62,7 +62,7 @@ libutun_a_SOURCES = \
config_updater.c \ config_updater.c \
route_lib.c \ route_lib.c \
route6_lib.c \ route6_lib.c \
topo_bgp.c \ topo_group.c \
route_ping.c \ route_ping.c \
topo_node.c \ topo_node.c \
topo_node_lmdb.c \ topo_node_lmdb.c \

78
src/conn_mgr.c

@ -18,7 +18,7 @@
#include "config_parser.h" #include "config_parser.h"
#include "secure_channel.h" #include "secure_channel.h"
#include "topo_node.h" #include "topo_node.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "route_ping.h" #include "route_ping.h"
#include "route_connectivity.h" #include "route_connectivity.h"
#include "conn_mgr.h" #include "conn_mgr.h"
@ -157,9 +157,9 @@ static void cm_deliver_result(struct CONN_MGR_ENTRY* entry, int result) {
} }
static void cm_update_nodeinfo(struct CONN_MGR_ENTRY* entry) { static void cm_update_nodeinfo(struct CONN_MGR_ENTRY* entry) {
struct TOPO_BGP* bgp = entry->mgr->instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(entry->mgr->instance->topo_groups);
if (!bgp) return; if (!group) return;
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, entry->node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(group, entry->node_id);
if (!nq) return; if (!nq) return;
nq->conn_mgr_type = entry->conn_type; nq->conn_mgr_type = entry->conn_type;
memcpy(nq->conn_mgr_intermediaries, entry->intermediaries, sizeof(entry->intermediaries)); memcpy(nq->conn_mgr_intermediaries, entry->intermediaries, sizeof(entry->intermediaries));
@ -167,7 +167,7 @@ static void cm_update_nodeinfo(struct CONN_MGR_ENTRY* entry) {
} }
static void cm_clear_nodeinfo(struct CONN_MGR* mgr, uint64_t node_id) { static void cm_clear_nodeinfo(struct CONN_MGR* mgr, uint64_t node_id) {
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->instance->bgp, node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(mgr->instance->topo_groups), node_id);
if (!nq) return; if (!nq) return;
nq->conn_mgr_type = CONN_TYPE_NONE; nq->conn_mgr_type = CONN_TYPE_NONE;
nq->conn_mgr_intermediariy_count = 0; nq->conn_mgr_intermediariy_count = 0;
@ -176,9 +176,9 @@ static void cm_clear_nodeinfo(struct CONN_MGR* mgr, uint64_t node_id) {
int conn_mgr_connect_node(struct CONN_MGR* mgr, uint64_t node_id, uint32_t idle_timeout_ms, int conn_mgr_connect_node(struct CONN_MGR* mgr, uint64_t node_id, uint32_t idle_timeout_ms,
conn_mgr_connect_callback_t cb, void* cb_arg) { conn_mgr_connect_callback_t cb, void* cb_arg) {
if (!mgr) return CONN_MGR_ERR_INTERNAL; if (!mgr) return CONN_MGR_ERR_INTERNAL;
struct TOPO_BGP* bgp = mgr->instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(mgr->instance->topo_groups);
if (!bgp) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "conn_mgr_connect: BGP not initialized"); return CONN_MGR_ERR_INTERNAL; } if (!group) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "conn_mgr_connect: BGP not initialized"); return CONN_MGR_ERR_INTERNAL; }
struct TOPO_NODEQ* target = topo_node_find_by_id(bgp, node_id); struct TOPO_NODEQ* target = topo_node_find_by_id(group, node_id);
if (!target) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "conn_mgr_connect: node 0x%016llx not found", (unsigned long long)node_id); return CONN_MGR_ERR_NOT_FOUND; } if (!target) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "conn_mgr_connect: node 0x%016llx not found", (unsigned long long)node_id); return CONN_MGR_ERR_NOT_FOUND; }
struct CONN_MGR_ENTRY* entry = cm_find_entry(mgr, node_id); struct CONN_MGR_ENTRY* entry = cm_find_entry(mgr, node_id);
if (entry && entry->state == CONN_MGR_STATE_CONNECTED) { if (entry && entry->state == CONN_MGR_STATE_CONNECTED) {
@ -191,7 +191,7 @@ int conn_mgr_connect_node(struct CONN_MGR* mgr, uint64_t node_id, uint32_t idle_
if (cn) { cn->cb = cb; cn->arg = cb_arg; cn->next = entry->cb_list; entry->cb_list = cn; } if (cn) { cn->cb = cb; cn->arg = cb_arg; cn->next = entry->cb_list; entry->cb_list = cn; }
return CONN_MGR_OK; return CONN_MGR_OK;
} }
struct ETCP_CONN* existing = topo_bgp_find_conn_for_node(bgp, node_id); struct ETCP_CONN* existing = topo_group_find_conn_for_node(group, node_id);
if (existing && existing->peer_node_id == node_id && existing->links) { if (existing && existing->peer_node_id == node_id && existing->links) {
struct ETCP_LINK* l = existing->links; struct ETCP_LINK* l = existing->links;
while (l) { if (l->link_status && l->initialized) break; l = l->next; } while (l) { if (l->link_status && l->initialized) break; l = l->next; }
@ -223,7 +223,7 @@ int conn_mgr_connect_node(struct CONN_MGR* mgr, uint64_t node_id, uint32_t idle_
entry->main.phase = 0; entry->main.phase = 0;
entry->main.timer = NULL; entry->main.timer = NULL;
entry->main.request_id = 0; entry->main.request_id = 0;
int has_our_local = cm_has_local_addr(bgp->local_node); int has_our_local = cm_has_local_addr(group->local_node);
int has_target_local = cm_has_local_addr(target); int has_target_local = cm_has_local_addr(target);
if (has_our_local && has_target_local) { entry->local_scan_state = CM_TRY_PENDING; cm_start_local_scan(entry); } if (has_our_local && has_target_local) { entry->local_scan_state = CM_TRY_PENDING; cm_start_local_scan(entry); }
entry->main_connect_state = CM_TRY_PENDING; entry->main_connect_state = CM_TRY_PENDING;
@ -271,11 +271,11 @@ int conn_mgr_get_status(struct CONN_MGR* mgr, uint64_t node_id, uint8_t* out_sta
int conn_mgr_add_alien_node(struct CONN_MGR* mgr, const uint8_t* nodeinfo_data, size_t len) { int conn_mgr_add_alien_node(struct CONN_MGR* mgr, const uint8_t* nodeinfo_data, size_t len) {
if (!mgr || !nodeinfo_data || len < sizeof(struct TOPO_NODE)) return CONN_MGR_ERR_INTERNAL; if (!mgr || !nodeinfo_data || len < sizeof(struct TOPO_NODE)) return CONN_MGR_ERR_INTERNAL;
struct TOPO_BGP* bgp = mgr->instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(mgr->instance->topo_groups);
if (!bgp) return CONN_MGR_ERR_INTERNAL; if (!group) return CONN_MGR_ERR_INTERNAL;
const struct TOPO_NODE* src = (const struct TOPO_NODE*)nodeinfo_data; const struct TOPO_NODE* src = (const struct TOPO_NODE*)nodeinfo_data;
uint64_t node_id = src->node_id; uint64_t node_id = src->node_id;
struct TOPO_NODEQ* existing = topo_node_find_by_id(bgp, node_id); struct TOPO_NODEQ* existing = topo_node_find_by_id(group, node_id);
if (existing) { DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: alien node 0x%016llx already exists, ignoring", (unsigned long long)node_id); return CONN_MGR_OK; } if (existing) { DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: alien node 0x%016llx already exists, ignoring", (unsigned long long)node_id); return CONN_MGR_OK; }
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE)); struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
if (!ni) return CONN_MGR_ERR_INTERNAL; if (!ni) return CONN_MGR_ERR_INTERNAL;
@ -287,7 +287,7 @@ int conn_mgr_add_alien_node(struct CONN_MGR* mgr, const uint8_t* nodeinfo_data,
nq->hash_node_id = ni->node_id; nq->hash_node_id = ni->node_id;
nq->alien = 1; nq->dirty = 0; nq->last_ver = ni->ver; nq->alien = 1; nq->dirty = 0; nq->last_ver = ni->ver;
nq->connectivity.ping_req_time = 0; nq->connectivity.ping_req_time = 0;
if (bgp->nodes) queue_data_put_with_index(bgp->nodes, &nq->ll); if (group->nodes) queue_data_put_with_index(group->nodes, &nq->ll);
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: added alien node 0x%016llx", (unsigned long long)node_id); DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: added alien node 0x%016llx", (unsigned long long)node_id);
return CONN_MGR_OK; return CONN_MGR_OK;
} }
@ -426,8 +426,8 @@ struct cm_ping_ctx {
}; };
static void cm_start_local_scan(struct CONN_MGR_ENTRY* entry) { static void cm_start_local_scan(struct CONN_MGR_ENTRY* entry) {
struct TOPO_BGP* bgp = entry->mgr->instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(entry->mgr->instance->topo_groups);
struct TOPO_NODEQ* target = topo_node_find_by_id(bgp, entry->node_id); struct TOPO_NODEQ* target = topo_node_find_by_id(group, entry->node_id);
if (!target || !target->node) { entry->local_scan_state = CM_TRY_FAILED; return; } if (!target || !target->node) { entry->local_scan_state = CM_TRY_FAILED; return; }
for (const struct TOPO_ADDR4* a = target->node->v4_addrs; a; a = a->next) { for (const struct TOPO_ADDR4* a = target->node->v4_addrs; a; a = a->next) {
if (a->type != TOPO_ADDR_INTERFACE) continue; if (a->type != TOPO_ADDR_INTERFACE) continue;
@ -454,8 +454,8 @@ static void cm_start_local_scan(struct CONN_MGR_ENTRY* entry) {
static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) { static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) {
if (entry->main_connect_state == CM_TRY_OK) return; if (entry->main_connect_state == CM_TRY_OK) return;
if (entry->local_scan_state == CM_TRY_OK) return; if (entry->local_scan_state == CM_TRY_OK) return;
struct TOPO_BGP* bgp = entry->mgr->instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(entry->mgr->instance->topo_groups);
struct TOPO_NODEQ* target = topo_node_find_by_id(bgp, entry->node_id); struct TOPO_NODEQ* target = topo_node_find_by_id(group, entry->node_id);
if (!target || !target->node) { cm_deliver_result(entry, CONN_MGR_ERR_NOT_FOUND); return; } if (!target || !target->node) { cm_deliver_result(entry, CONN_MGR_ERR_NOT_FOUND); return; }
uint8_t priority_order[] = { TOPO_ADDR_REAL, TOPO_ADDR_NAT, TOPO_ADDR_INTERFACE }; uint8_t priority_order[] = { TOPO_ADDR_REAL, TOPO_ADDR_NAT, TOPO_ADDR_INTERFACE };
for (int pri = 0; pri < 3; pri++) { for (int pri = 0; pri < 3; pri++) {
@ -484,7 +484,7 @@ static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) {
} }
} }
} }
int has_our = cm_has_direct_ip(bgp->local_node); int has_our = cm_has_direct_ip(group->local_node);
int has_target = cm_has_direct_ip(target); int has_target = cm_has_direct_ip(target);
if (has_our && !has_target) { cm_start_phase_reverse(entry); return; } if (has_our && !has_target) { cm_start_phase_reverse(entry); return; }
cm_start_phase_indirect(entry); cm_start_phase_indirect(entry);
@ -493,9 +493,9 @@ static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) {
static void cm_direct_timeout_cb(void* arg) { static void cm_direct_timeout_cb(void* arg) {
struct CONN_MGR_ENTRY* entry = (struct CONN_MGR_ENTRY*)arg; struct CONN_MGR_ENTRY* entry = (struct CONN_MGR_ENTRY*)arg;
entry->main.timer = NULL; entry->main.timer = NULL;
struct TOPO_BGP* bgp = entry->mgr->instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(entry->mgr->instance->topo_groups);
struct TOPO_NODEQ* target = topo_node_find_by_id(bgp, entry->node_id); struct TOPO_NODEQ* target = topo_node_find_by_id(group, entry->node_id);
int has_our = cm_has_direct_ip(bgp->local_node); int has_our = cm_has_direct_ip(group->local_node);
int has_target = target ? cm_has_direct_ip(target) : 0; int has_target = target ? cm_has_direct_ip(target) : 0;
if (entry->local_scan_state != CM_TRY_OK) { if (entry->local_scan_state != CM_TRY_OK) {
if (has_our && !has_target) { cm_start_phase_reverse(entry); return; } if (has_our && !has_target) { cm_start_phase_reverse(entry); return; }
@ -542,7 +542,7 @@ static void cm_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce,
ctx->attempt++; ctx->attempt++;
if (ctx->attempt < CONN_MGR_LOCAL_SCAN_ATTEMPTS && ctx->phase == 0) { if (ctx->attempt < CONN_MGR_LOCAL_SCAN_ATTEMPTS && ctx->phase == 0) {
etcp_send_ping_to_socket(entry->mgr->instance, ctx->sock, etcp_send_ping_to_socket(entry->mgr->instance, ctx->sock,
topo_node_find_by_id(entry->mgr->instance->bgp, entry->node_id)->node->public_key, topo_node_find_by_id(topo_groups_get_default(entry->mgr->instance->topo_groups), entry->node_id)->node->public_key,
&ctx->addr, CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0); &ctx->addr, CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0);
return; return;
} }
@ -553,8 +553,8 @@ static void cm_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce,
} }
static void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry) { static void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry) {
struct TOPO_BGP* bgp = entry->mgr->instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(entry->mgr->instance->topo_groups);
struct TOPO_NODEQ* local = bgp->local_node; struct TOPO_NODEQ* local = group->local_node;
if (!local || !local->node) { cm_deliver_result(entry, CONN_MGR_ERR_INTERNAL); return; } if (!local || !local->node) { cm_deliver_result(entry, CONN_MGR_ERR_INTERNAL); return; }
uint32_t req_id = ++entry->mgr->next_request_id; uint32_t req_id = ++entry->mgr->next_request_id;
entry->main.request_id = req_id; entry->main.phase = 2; entry->main.request_id = req_id; entry->main.phase = 2;
@ -686,7 +686,7 @@ static void cm_compute_intermediaries(struct CONN_MGR_ENTRY* entry, struct CONN_
} }
for (uint8_t i = 0; i < resp->my_count && count < 8; i++) { for (uint8_t i = 0; i < resp->my_count && count < 8; i++) {
uint64_t id = resp->my_candidates[i].node_id; uint64_t id = resp->my_candidates[i].node_id;
struct TOPO_NODEQ* nq = topo_node_find_by_id(entry->mgr->instance->bgp, id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(entry->mgr->instance->topo_groups), id);
uint16_t our_rtt = nq ? cm_get_node_min_rtt(nq) : 0; uint16_t our_rtt = nq ? cm_get_node_min_rtt(nq) : 0;
if (our_rtt == 0xFFFF) our_rtt = 0; if (our_rtt == 0xFFFF) our_rtt = 0;
all[count].node_id = id; all[count].node_id = id;
@ -712,7 +712,7 @@ static void cm_compute_intermediaries(struct CONN_MGR_ENTRY* entry, struct CONN_
for (uint8_t i = 0; i < sel; i++) { for (uint8_t i = 0; i < sel; i++) {
pkt.selected[i].node_id = all[i].node_id; pkt.selected[i].node_id = all[i].node_id;
pkt.selected[i].rtt = 0; pkt.selected[i].rtt = 0;
struct TOPO_NODEQ* nq = topo_node_find_by_id(entry->mgr->instance->bgp, all[i].node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(entry->mgr->instance->topo_groups), all[i].node_id);
if (nq) pkt.selected[i].rtt = cm_get_node_min_rtt(nq); if (nq) pkt.selected[i].rtt = cm_get_node_min_rtt(nq);
} }
struct ll_entry* qe = queue_entry_new(sizeof(pkt)); struct ll_entry* qe = queue_entry_new(sizeof(pkt));
@ -733,7 +733,7 @@ static void cm_exchange_probe_retry_cb(void* arg) {
uint8_t need_probe = 0; uint8_t need_probe = 0;
uint64_t now_tb = get_time_tb(); uint64_t now_tb = get_time_tb();
for (uint8_t i = 0; i < ep->cached_resp.my_count && i < 4; i++) { for (uint8_t i = 0; i < ep->cached_resp.my_count && i < 4; i++) {
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->instance->bgp, ep->cached_resp.my_candidates[i].node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(mgr->instance->topo_groups), ep->cached_resp.my_candidates[i].node_id);
if (!nq || !cm_is_rtt_fresh(nq, now_tb)) { need_probe++; break; } if (!nq || !cm_is_rtt_fresh(nq, now_tb)) { need_probe++; break; }
} }
if (need_probe == 0) { if (need_probe == 0) {
@ -763,7 +763,7 @@ static void cm_handle_interm_exchange_resp(struct CONN_MGR* mgr, const uint8_t*
uint8_t need_probe = 0; uint8_t need_probe = 0;
uint64_t now_tb = get_time_tb(); uint64_t now_tb = get_time_tb();
for (uint8_t i = 0; i < ep->cached_resp.my_count && i < 4; i++) { for (uint8_t i = 0; i < ep->cached_resp.my_count && i < 4; i++) {
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->instance->bgp, ep->cached_resp.my_candidates[i].node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(mgr->instance->topo_groups), ep->cached_resp.my_candidates[i].node_id);
if (!nq || !cm_is_rtt_fresh(nq, now_tb)) { need_probe++; route_connectivity_probe_node(mgr->instance, nq); } if (!nq || !cm_is_rtt_fresh(nq, now_tb)) { need_probe++; route_connectivity_probe_node(mgr->instance, nq); }
} }
if (need_probe == 0) { ep->probes_done = 1; cm_compute_intermediaries(ep->entry, &ep->cached_resp); if (need_probe == 0) { ep->probes_done = 1; cm_compute_intermediaries(ep->entry, &ep->cached_resp);
@ -852,7 +852,7 @@ static void cm_handle_direct_req(struct ETCP_CONN* conn, const uint8_t* data, si
memset(&sa, 0, sizeof(sa)); memcpy(&sa, &sin, sizeof(sin)); memset(&sa, 0, sizeof(sa)); memcpy(&sa, &sin, sizeof(sin));
struct ETCP_CONN* new_conn = etcp_connection_create(conn->instance, NULL); struct ETCP_CONN* new_conn = etcp_connection_create(conn->instance, NULL);
if (new_conn) { if (new_conn) {
struct TOPO_NODEQ* nq = topo_node_find_by_id(conn->instance->bgp, src_node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(conn->instance->topo_groups), src_node_id);
if (nq) sc_set_peer_public_key(&new_conn->crypto_ctx, nq->node->public_key, 0); if (nq) sc_set_peer_public_key(&new_conn->crypto_ctx, nq->node->public_key, 0);
struct cm_reverse_pending* rp = u_calloc(1, sizeof(struct cm_reverse_pending)); struct cm_reverse_pending* rp = u_calloc(1, sizeof(struct cm_reverse_pending));
if (rp) { rp->request_id = req->request_id; rp->entry = NULL; rp->next = mgr->reverse_pending; if (rp) { rp->request_id = req->request_id; rp->entry = NULL; rp->next = mgr->reverse_pending;
@ -873,7 +873,7 @@ static void cm_handle_interm_exchange_req(struct ETCP_CONN* conn,
uint64_t now_tb = get_time_tb(); uint64_t now_tb = get_time_tb();
for (uint8_t i = 0; i < req->candidate_count && i < 4; i++) { for (uint8_t i = 0; i < req->candidate_count && i < 4; i++) {
uint64_t cand_id = req->candidates[i].node_id; uint64_t cand_id = req->candidates[i].node_id;
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->instance->bgp, cand_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(mgr->instance->topo_groups), cand_id);
if (nq && cm_is_rtt_fresh(nq, now_tb)) continue; if (nq && cm_is_rtt_fresh(nq, now_tb)) continue;
route_connectivity_probe_node(mgr->instance, nq); route_connectivity_probe_node(mgr->instance, nq);
} }
@ -888,7 +888,7 @@ static void cm_handle_interm_exchange_req(struct ETCP_CONN* conn,
resp.your_count = req->candidate_count > 4 ? 4 : req->candidate_count; resp.your_count = req->candidate_count > 4 ? 4 : req->candidate_count;
for (uint8_t i = 0; i < resp.your_count; i++) { for (uint8_t i = 0; i < resp.your_count; i++) {
resp.your_candidates[i].node_id = req->candidates[i].node_id; resp.your_candidates[i].node_id = req->candidates[i].node_id;
struct TOPO_NODEQ* nq2 = topo_node_find_by_id(mgr->instance->bgp, req->candidates[i].node_id); struct TOPO_NODEQ* nq2 = topo_node_find_by_id(topo_groups_get_default(mgr->instance->topo_groups), req->candidates[i].node_id);
uint16_t rtt = nq2 ? cm_get_node_min_rtt(nq2) : 0; uint16_t rtt = nq2 ? cm_get_node_min_rtt(nq2) : 0;
resp.your_candidates[i].rtt = rtt; resp.your_candidates[i].rtt = rtt;
} }
@ -913,13 +913,13 @@ static void cm_handle_disconnect(struct CONN_MGR* mgr, uint64_t node_id) {
static void cm_bg_ping_timer_cb(void* arg) { static void cm_bg_ping_timer_cb(void* arg) {
struct CONN_MGR* mgr = (struct CONN_MGR*)arg; struct CONN_MGR* mgr = (struct CONN_MGR*)arg;
struct TOPO_BGP* bgp = mgr->instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(mgr->instance->topo_groups);
if (!bgp || !bgp->nodes) { if (!group || !group->nodes) {
mgr->bg_ping_timer = uasync_set_timeout(mgr->instance->ua, CONN_MGR_BG_PING_INTERVAL_TB, mgr, cm_bg_ping_timer_cb, "conn_mgr_bg_ping"); mgr->bg_ping_timer = uasync_set_timeout(mgr->instance->ua, CONN_MGR_BG_PING_INTERVAL_TB, mgr, cm_bg_ping_timer_cb, "conn_mgr_bg_ping");
return; return;
} }
uint64_t now_tb = get_time_tb(); uint64_t now_tb = get_time_tb();
struct ll_entry* e = bgp->nodes->head; struct ll_entry* e = group->nodes->head;
size_t total = 0; size_t total = 0;
while (e) { total++; e = e->next; } while (e) { total++; e = e->next; }
if (total == 0) { if (total == 0) {
@ -936,13 +936,13 @@ static void cm_bg_ping_timer_cb(void* arg) {
mgr->bg_ping_cycle_start_tb = now_tb; mgr->bg_ping_cycle_start_tb = now_tb;
} }
size_t cursor = 0; size_t cursor = 0;
e = bgp->nodes->head; e = group->nodes->head;
while (e && cursor < mgr->bg_ping_cursor) { cursor++; e = e->next; } while (e && cursor < mgr->bg_ping_cursor) { cursor++; e = e->next; }
if (e) { if (e) {
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e; struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
uint64_t node_id = nq->node->node_id; uint64_t node_id = nq->node->node_id;
if (node_id != mgr->instance->node_id) { if (node_id != mgr->instance->node_id) {
struct ETCP_CONN* dconn = topo_bgp_find_conn_for_node(bgp, node_id); struct ETCP_CONN* dconn = topo_group_find_conn_for_node(group, node_id);
int has_active = 0; int has_active = 0;
if (dconn && dconn->links) { if (dconn && dconn->links) {
struct ETCP_LINK* l = dconn->links; struct ETCP_LINK* l = dconn->links;
@ -963,7 +963,7 @@ static void cm_candidate_ping_timer_cb(void* arg) {
uint64_t now_tb = get_time_tb(); uint64_t now_tb = get_time_tb();
for (uint8_t i = 0; i < mgr->best_candidate_count; i++) { for (uint8_t i = 0; i < mgr->best_candidate_count; i++) {
uint64_t cand_id = mgr->best_candidates[i].node_id; uint64_t cand_id = mgr->best_candidates[i].node_id;
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->instance->bgp, cand_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(mgr->instance->topo_groups), cand_id);
if (!nq) { if (!nq) {
memmove(&mgr->best_candidates[i], &mgr->best_candidates[i+1], (mgr->best_candidate_count - i - 1) * sizeof(mgr->best_candidates[0])); memmove(&mgr->best_candidates[i], &mgr->best_candidates[i+1], (mgr->best_candidate_count - i - 1) * sizeof(mgr->best_candidates[0]));
mgr->best_candidate_count--; i--; continue; mgr->best_candidate_count--; i--; continue;
@ -974,7 +974,7 @@ static void cm_candidate_ping_timer_cb(void* arg) {
memmove(&mgr->best_candidates[i], &mgr->best_candidates[i+1], (mgr->best_candidate_count - i - 1) * sizeof(mgr->best_candidates[0])); memmove(&mgr->best_candidates[i], &mgr->best_candidates[i+1], (mgr->best_candidate_count - i - 1) * sizeof(mgr->best_candidates[0]));
mgr->best_candidate_count--; i--; continue; mgr->best_candidate_count--; i--; continue;
} }
struct ETCP_CONN* dconn = topo_bgp_find_conn_for_node(mgr->instance->bgp, cand_id); struct ETCP_CONN* dconn = topo_group_find_conn_for_node(topo_groups_get_default(mgr->instance->topo_groups), cand_id);
int has_active = 0; int has_active = 0;
if (dconn && dconn->links) { if (dconn && dconn->links) {
struct ETCP_LINK* l = dconn->links; struct ETCP_LINK* l = dconn->links;

2
src/conn_mgr.h

@ -16,7 +16,7 @@ extern "C" {
struct UTUN_INSTANCE; struct UTUN_INSTANCE;
struct ETCP_CONN; struct ETCP_CONN;
struct TOPO_NODEQ; struct TOPO_NODEQ;
struct TOPO_BGP; struct TOPO_GROUP;
/** /**
* @file conn_mgr.h * @file conn_mgr.h

25
src/control_server.c

@ -10,7 +10,7 @@
#include "etcp_connections.h" #include "etcp_connections.h"
#include "tun_if.h" #include "tun_if.h"
#include "route_lib.h" #include "route_lib.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "etcp_router.h" #include "etcp_router.h"
#include "topo_node.h" #include "topo_node.h"
#include "pkt_normalizer.h" #include "pkt_normalizer.h"
@ -784,13 +784,13 @@ static void handle_client_data(struct control_server* server, struct control_cli
struct etcpmon_cmd_action* cmd = (struct etcpmon_cmd_action*)payload; struct etcpmon_cmd_action* cmd = (struct etcpmon_cmd_action*)payload;
if (strncmp(cmd->action, "nat", 3) == 0) { if (strncmp(cmd->action, "nat", 3) == 0) {
DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Action 'nat' received, requesting NAT check for all links"); DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Action 'nat' received, requesting NAT check for all links");
topo_bgp_request_nat_check_all(server->instance->bgp); topo_group_request_nat_check_all(topo_groups_get_default(server->instance->topo_groups));
} else if (strncmp(cmd->action, "nodes", 5) == 0) { } else if (strncmp(cmd->action, "nodes", 5) == 0) {
DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Action 'nodes' received, dumping all BGP nodes"); DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Action 'nodes' received, dumping all BGP nodes");
uint16_t text_max = (ETCPMON_MAX_MSG_SIZE > 1024) ? ETCPMON_MAX_MSG_SIZE - 512 : 1024; uint16_t text_max = (ETCPMON_MAX_MSG_SIZE > 1024) ? ETCPMON_MAX_MSG_SIZE - 512 : 1024;
char* text = (char*)u_malloc(text_max); char* text = (char*)u_malloc(text_max);
if (text) { if (text) {
int text_len = topo_node_format_all(server->instance->bgp, text, text_max); int text_len = topo_node_format_all(topo_groups_get_default(server->instance->topo_groups), text, text_max);
if (text_len < 0) text_len = 0; if (text_len < 0) text_len = 0;
text[text_len] = '\0'; text[text_len] = '\0';
uint16_t rsp_size = ETCPMON_ACTION_RESULT_SIZE(text_len); uint16_t rsp_size = ETCPMON_ACTION_RESULT_SIZE(text_len);
@ -1188,13 +1188,14 @@ static void send_metrics(struct control_server* server, struct control_client* c
} }
/* BGP routing */ /* BGP routing */
if (instance->bgp) { { struct TOPO_GROUP* g = topo_groups_get_default(instance->topo_groups);
rsp->tun.rt_bgp_senders = (uint32_t)queue_entry_count(instance->bgp->senders_list); if (g) {
rsp->tun.rt_bgp_nodes = (uint32_t)queue_entry_count(instance->bgp->nodes); rsp->tun.rt_bgp_senders = (uint32_t)queue_entry_count(g->senders_list);
rsp->tun.rt_bgp_nodes = (uint32_t)queue_entry_count(g->nodes);
} else { } else {
rsp->tun.rt_bgp_senders = 0; rsp->tun.rt_bgp_senders = 0;
rsp->tun.rt_bgp_nodes = 0; rsp->tun.rt_bgp_nodes = 0;
} } }
} else { } else {
memset(&rsp->tun, 0, sizeof(rsp->tun)); memset(&rsp->tun, 0, sizeof(rsp->tun));
} }
@ -1388,7 +1389,7 @@ static struct ETCP_CONN* find_connection_by_peer_id(struct UTUN_INSTANCE* instan
static void send_single_node_info(struct control_server* server, struct control_client* client, struct TOPO_NODEQ* nq) { static void send_single_node_info(struct control_server* server, struct control_client* client, struct TOPO_NODEQ* nq) {
if (!server || !nq || !nq->node) return; if (!server || !nq || !nq->node) return;
uint8_t buf[8192]; uint8_t buf[8192];
int ser_len = topo_node_serialize(server->instance->bgp, nq, buf + 2, sizeof(buf) - 2); int ser_len = topo_node_serialize(topo_groups_get_default(server->instance->topo_groups), nq, buf + 2, sizeof(buf) - 2);
if (ser_len < 0) { DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Failed to serialize node info"); return; } if (ser_len < 0) { DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Failed to serialize node info"); return; }
buf[0] = CTRL_BGP_CMD; buf[1] = CTRL_BGP_SUBCMD; buf[0] = CTRL_BGP_CMD; buf[1] = CTRL_BGP_SUBCMD;
size_t data_size = 2 + (size_t)ser_len; size_t data_size = 2 + (size_t)ser_len;
@ -1405,14 +1406,14 @@ static void send_single_node_info(struct control_server* server, struct control_
} }
static void control_server_send_node_list(struct control_server* server, struct control_client* client, uint8_t seq_id) { static void control_server_send_node_list(struct control_server* server, struct control_client* client, uint8_t seq_id) {
struct TOPO_BGP* bgp = server->instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(server->instance->topo_groups);
if (!bgp) { send_error(client, ETCPMON_ERR_SERVER_BUSY, "BGP not available", seq_id); return; } if (!group) { send_error(client, ETCPMON_ERR_SERVER_BUSY, "BGP not available", seq_id); return; }
/* Send local node first */ /* Send local node first */
if (bgp->local_node) send_single_node_info(server, client, bgp->local_node); if (group->local_node) send_single_node_info(server, client, group->local_node);
/* Send all known remote nodes */ /* Send all known remote nodes */
struct ll_entry* e = bgp->nodes ? bgp->nodes->head : NULL; struct ll_entry* e = group->nodes ? group->nodes->head : NULL;
while (e) { while (e) {
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e; struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
send_single_node_info(server, client, nq); send_single_node_info(server, client, nq);

10
src/db_sync.c

@ -5,7 +5,7 @@
#include "etcp.h" #include "etcp.h"
#include "etcp_router.h" #include "etcp_router.h"
#include "utun_instance.h" #include "utun_instance.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "../lib/debug_config.h" #include "../lib/debug_config.h"
#include "../lib/mem.h" #include "../lib/mem.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
@ -778,13 +778,13 @@ static void db_sync_initiate_sync(struct DB_SYNC* db, uint64_t peer_node_id) {
static void db_sync_peer_check_cb(void* arg) { static void db_sync_peer_check_cb(void* arg) {
struct DB_SYNC* db = (struct DB_SYNC*)arg; struct DB_SYNC* db = (struct DB_SYNC*)arg;
if (!db || !db->enabled) return; if (!db || !db->enabled) return;
struct TOPO_BGP* bgp = db->inst->bgp; struct TOPO_GROUP* group = topo_groups_get_default(db->inst->topo_groups);
if (!bgp) { db->peer_check_timer = uasync_set_timeout(db->inst->ua, DB_SYNC_PEER_CHECK_INTERVAL * 10000u, db, db_sync_peer_check_cb, "db_sync_peer"); return; } if (!group) { db->peer_check_timer = uasync_set_timeout(db->inst->ua, DB_SYNC_PEER_CHECK_INTERVAL * 10000u, db, db_sync_peer_check_cb, "db_sync_peer"); return; }
// Check all known peers with active connections // Check all known peers with active connections
struct ll_entry* e = bgp->senders_list->head; struct ll_entry* e = group->senders_list->head;
while (e) { while (e) {
struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)e->data; struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)e->data;
if (item->conn && item->conn->peer_node_id != 0 && item->conn->links_up) { if (item->conn && item->conn->peer_node_id != 0 && item->conn->links_up) {
uint64_t pid = item->conn->peer_node_id; uint64_t pid = item->conn->peer_node_id;
if (pid != db->inst->node_id) { if (pid != db->inst->node_id) {

6
src/etcp.c

@ -5,7 +5,7 @@
#include "etcp_loadbalancer.h" #include "etcp_loadbalancer.h"
#include "etcp_router.h" #include "etcp_router.h"
#include "routing.h" #include "routing.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "route_ping.h" #include "route_ping.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
#include "../lib/ll_queue.h" #include "../lib/ll_queue.h"
@ -506,8 +506,8 @@ void etcp_conn_reinit(struct ETCP_CONN* etcp) {// Если сбой в обме
etcp->initialized = 0;// еще раз придёт conn_ready_callback etcp->initialized = 0;// еще раз придёт conn_ready_callback
// Отменяем висящие NAT-ping'и для этого соединения // Отменяем висящие NAT-ping'и для этого соединения
if (etcp->instance && etcp->instance->bgp) { if (etcp->instance && etcp->instance->topo_groups) {
route_ping_cancel_for_conn(etcp->instance->bgp, etcp); route_ping_cancel_for_conn(topo_groups_get_default(etcp->instance->topo_groups), etcp);
} }
// Сбрасываем NAT-статус у всех линков этого соединения // Сбрасываем NAT-статус у всех линков этого соединения

37
src/etcp_connections.c

@ -18,7 +18,7 @@
#include "etcp.h" #include "etcp.h"
#include "stcp_link.h" #include "stcp_link.h"
#include "topo_node.h" #include "topo_node.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "route_ping.h" #include "route_ping.h"
#include "../lib/memory_pool.h" #include "../lib/memory_pool.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
@ -1288,8 +1288,8 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk
{ {
link->nat_type = NAT_TYPE_DIRECT; link->nat_type = NAT_TYPE_DIRECT;
link->nat_check_status = NAT_CHECK_EIM; link->nat_check_status = NAT_CHECK_EIM;
if (link->etcp->instance->bgp) { if (link->etcp->instance->topo_groups) {
topo_bgp_send_nat_info(link->etcp, link->remote_socket_id, topo_group_send_nat_info(link->etcp, link->remote_socket_id,
link->nat_ip, link->nat_port, NAT_TYPE_DIRECT); link->nat_ip, link->nat_port, NAT_TYPE_DIRECT);
} }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "DIRECT IP: %s:%u for %s", DEBUG_INFO(DEBUG_CATEGORY_BGP, "DIRECT IP: %s:%u for %s",
@ -1310,20 +1310,21 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk
nat_sin->sin_family = AF_INET; nat_sin->sin_family = AF_INET;
nat_sin->sin_addr.s_addr = my_ip; nat_sin->sin_addr.s_addr = my_ip;
nat_sin->sin_port = ((struct sockaddr_in*)&e_sock->interface_addr)->sin_port; nat_sin->sin_port = ((struct sockaddr_in*)&e_sock->interface_addr)->sin_port;
if (link->etcp->instance->bgp) { { struct TOPO_GROUP* g = topo_groups_get_default(link->etcp->instance->topo_groups);
topo_bgp_update_my_nodeinfo(link->etcp->instance->bgp->instance, link->etcp->instance->bgp); if (g) {
struct TOPO_BGP* bgp = link->etcp->instance->bgp; topo_group_update_my_nodeinfo(g->instance, g);
if (bgp->local_node && bgp->senders_list) { if (g->local_node && g->senders_list) {
bgp->local_node->node->ver = (bgp->local_node->node->ver % 255) + 1; g->local_node->node->ver = (g->local_node->node->ver % 255) + 1;
bgp->local_node->dirty = 1; g->local_node->dirty = 1;
struct ll_entry* se = bgp->senders_list->head; struct ll_entry* se = g->senders_list->head;
while (se) { while (se) {
struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)se->data; struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)se->data;
if (item && item->conn) topo_bgp_send_nodeinfo(bgp->local_node, item->conn); if (item && item->conn) topo_group_send_nodeinfo(g, g->local_node, item->conn);
se = se->next; se = se->next;
} }
} }
} }
}
DEBUG_INFO(DEBUG_CATEGORY_NAT, "Self-detected PUBLIC: socket=%s ip=%s port=%u sock_id=%d", DEBUG_INFO(DEBUG_CATEGORY_NAT, "Self-detected PUBLIC: socket=%s ip=%s port=%u sock_id=%d",
e_sock->name, ip_to_str(&my_ip, AF_INET).str, e_sock->name, ip_to_str(&my_ip, AF_INET).str,
ntohs(nat_sin->sin_port), e_sock->sock_id); ntohs(nat_sin->sin_port), e_sock->sock_id);
@ -1368,9 +1369,8 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk
start_keepalive_timer(link); start_keepalive_timer(link);
loadbalancer_link_ready(link); loadbalancer_link_ready(link);
// Restart NAT check after link is up (e.g. after address change or reinit) // Restart NAT check after link is up (e.g. after address change or reinit)
if (link->etcp->instance->bgp) { { struct TOPO_GROUP* g = topo_groups_get_default(link->etcp->instance->topo_groups);
if (link->nat_check_status < NAT_CHECK_IN_PROGRESS) topo_bgp_start_link_nat_check(link->etcp->instance->bgp, link); if (g && link->nat_check_status < NAT_CHECK_IN_PROGRESS) topo_group_start_link_nat_check(g, link); }
}
} }
static int handle_init_response_client(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, struct ETCP_LINK* link, uint8_t pkt_code, size_t pkt_len) { static int handle_init_response_client(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, struct ETCP_LINK* link, uint8_t pkt_code, size_t pkt_len) {
@ -1697,9 +1697,8 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
goto ec_fr; goto ec_fr;
} }
// Cancel pending NAT check and reset status // Cancel pending NAT check and reset status
if (link->etcp->instance->bgp) { { struct TOPO_GROUP* g = topo_groups_get_default(link->etcp->instance->topo_groups);
route_ping_cancel_for_conn(link->etcp->instance->bgp, link->etcp); if (g) route_ping_cancel_for_conn(g, link->etcp); }
}
link->nat_check_status = NAT_CHECK_NONE; link->nat_check_status = NAT_CHECK_NONE;
link->nat_type = NAT_TYPE_UNKNOWN; link->nat_type = NAT_TYPE_UNKNOWN;
} }
@ -1839,7 +1838,7 @@ ec_fr:
} }
// Initialize only sockets (servers for incoming connections) // Initialize only sockets (servers for incoming connections)
// Called before topo_bgp_init() to populate etcp_sockets for nodeinfo // Called before topo_group_init() to populate etcp_sockets for nodeinfo
// Returns: 0 = all OK, 1 = partial success (some sockets failed), -1 = fatal error (no sockets) // Returns: 0 = all OK, 1 = partial success (some sockets failed), -1 = fatal error (no sockets)
int init_sockets(struct UTUN_INSTANCE* instance) { int init_sockets(struct UTUN_INSTANCE* instance) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, ""); DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");

52
src/etcp_router.c

@ -14,7 +14,7 @@ in ---> {Q} -> [src, etcp] --> ... --> [dst,etcp] -> {asm_q} -> {buf q} ---> out
#include "etcp_router.h" #include "etcp_router.h"
#include "etcp.h" #include "etcp.h"
#include "utun_instance.h" #include "utun_instance.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "../lib/debug_config.h" #include "../lib/debug_config.h"
#include "../lib/mem.h" #include "../lib/mem.h"
#include "../lib/ll_queue.h" #include "../lib/ll_queue.h"
@ -178,17 +178,17 @@ static int router_send_one_flags(struct ETCP_ROUTER_CONN* rconn, const uint8_t*
if (pl_len > 0) memcpy(dgram + SVC_ROUTE_HDR_SIZE, payload, pl_len); if (pl_len > 0) memcpy(dgram + SVC_ROUTE_HDR_SIZE, payload, pl_len);
struct ETCP_CONN* conn = NULL; struct ETCP_CONN* conn = NULL;
struct TOPO_BGP* bgp = inst->bgp; struct TOPO_GROUP* group = topo_groups_get_default(inst->topo_groups);
if (bgp) { if (group) {
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, rconn->remote_node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(group, rconn->remote_node_id);
if (nq && nq->conn_mgr_type == CONN_TYPE_INDIRECT && nq->conn_mgr_intermediariy_count > 0) { if (nq && nq->conn_mgr_type == CONN_TYPE_INDIRECT && nq->conn_mgr_intermediariy_count > 0) {
for (uint8_t i = 0; i < nq->conn_mgr_intermediariy_count; i++) { for (uint8_t i = 0; i < nq->conn_mgr_intermediariy_count; i++) {
conn = topo_bgp_find_conn_for_node(bgp, nq->conn_mgr_intermediaries[i]); conn = topo_group_find_conn_for_node(group, nq->conn_mgr_intermediaries[i]);
if (conn) break; if (conn) break;
} }
} }
} }
if (!conn) conn = topo_bgp_find_conn_for_node(bgp, rconn->remote_node_id); if (!conn) conn = topo_group_find_conn_for_node(group, rconn->remote_node_id);
if (!conn) { if (!conn) {
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_send_one: no route to %016llx svc_id=%u", DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_send_one: no route to %016llx svc_id=%u",
(unsigned long long)rconn->remote_node_id, rconn->svc_id); (unsigned long long)rconn->remote_node_id, rconn->svc_id);
@ -259,7 +259,7 @@ static int router_send_one_flags(struct ETCP_ROUTER_CONN* rconn, const uint8_t*
// Отправка без conn (RST для неизвестного src) // Отправка без conn (RST для неизвестного src)
static void router_send_to(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t svc_id, uint8_t flag_bits) { static void router_send_to(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t svc_id, uint8_t flag_bits) {
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, dst); struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), dst);
if (!conn) return; if (!conn) return;
struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)u_malloc(SVC_ROUTE_HDR_SIZE); struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)u_malloc(SVC_ROUTE_HDR_SIZE);
if (!hdr) return; if (!hdr) return;
@ -314,7 +314,7 @@ static void router_close_and_notify(struct ETCP_ROUTER_CONN* rconn) {
rconn->closed = 1; rconn->closed = 1;
router_send_close_to_service(rconn); router_send_close_to_service(rconn);
// Отправляем CLOSE удалённой стороне // Отправляем CLOSE удалённой стороне
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, rconn->remote_node_id); struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), rconn->remote_node_id);
if (conn) router_send_one_flags(rconn, NULL, 0, ROUTER_FLAG_CLOSE, 0); if (conn) router_send_one_flags(rconn, NULL, 0, ROUTER_FLAG_CLOSE, 0);
// Таймеры // Таймеры
if (rconn->ack_timer) { uasync_cancel_timeout(inst->ua, rconn->ack_timer); rconn->ack_timer = NULL; } if (rconn->ack_timer) { uasync_cancel_timeout(inst->ua, rconn->ack_timer); rconn->ack_timer = NULL; }
@ -389,7 +389,7 @@ static void router_no_route_retry_cb(void* arg) {
struct ETCP_ROUTER_CONN* rconn = (struct ETCP_ROUTER_CONN*)arg; struct ETCP_ROUTER_CONN* rconn = (struct ETCP_ROUTER_CONN*)arg;
if (rconn->closed) return; if (rconn->closed) return;
rconn->no_route_timer = NULL; rconn->no_route_timer = NULL;
struct ETCP_CONN* c = topo_bgp_find_conn_for_node(rconn->inst->bgp, rconn->remote_node_id); struct ETCP_CONN* c = topo_group_find_conn_for_node(topo_groups_get_default(rconn->inst->topo_groups), rconn->remote_node_id);;
if (c) { if (c) {
DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router: route appeared for %016llx svc_id=%u, draining send_q=%d", DEBUG_INFO(DEBUG_CATEGORY_ETCPROUTE, "router: route appeared for %016llx svc_id=%u, draining send_q=%d",
(unsigned long long)rconn->remote_node_id, rconn->svc_id, queue_entry_count(rconn->send_q)); (unsigned long long)rconn->remote_node_id, rconn->svc_id, queue_entry_count(rconn->send_q));
@ -420,17 +420,17 @@ static void router_retransmit_one(struct ETCP_ROUTER_CONN* rconn, struct ROUTER_
hdr->timestamp = get_current_timestamp(); hdr->timestamp = get_current_timestamp();
struct ETCP_CONN* conn = NULL; struct ETCP_CONN* conn = NULL;
struct TOPO_BGP* bgp = inst->bgp; struct TOPO_GROUP* group = topo_groups_get_default(inst->topo_groups);
if (bgp) { if (group) {
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, rconn->remote_node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(group, rconn->remote_node_id);
if (nq && nq->conn_mgr_type == CONN_TYPE_INDIRECT && nq->conn_mgr_intermediariy_count > 0) { if (nq && nq->conn_mgr_type == CONN_TYPE_INDIRECT && nq->conn_mgr_intermediariy_count > 0) {
for (uint8_t i = 0; i < nq->conn_mgr_intermediariy_count; i++) { for (uint8_t i = 0; i < nq->conn_mgr_intermediariy_count; i++) {
conn = topo_bgp_find_conn_for_node(bgp, nq->conn_mgr_intermediaries[i]); conn = topo_group_find_conn_for_node(group, nq->conn_mgr_intermediaries[i]);
if (conn) break; if (conn) break;
} }
} }
} }
if (!conn) conn = topo_bgp_find_conn_for_node(bgp, rconn->remote_node_id); if (!conn) conn = topo_group_find_conn_for_node(group, rconn->remote_node_id);
if (!conn) { if (!conn) {
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_retransmit: no route to %016llx svc_id=%u", DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_retransmit: no route to %016llx svc_id=%u",
(unsigned long long)rconn->remote_node_id, rconn->svc_id); (unsigned long long)rconn->remote_node_id, rconn->svc_id);
@ -618,7 +618,7 @@ static void router_ack_do_send(struct ETCP_ROUTER_CONN* rconn) {
static void router_send_ack(struct ETCP_ROUTER_CONN* rconn) { static void router_send_ack(struct ETCP_ROUTER_CONN* rconn) {
struct UTUN_INSTANCE* inst = rconn->inst; struct UTUN_INSTANCE* inst = rconn->inst;
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, rconn->remote_node_id); struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), rconn->remote_node_id);
if (!conn) { if (!conn) {
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_ack: no route to %016llx svc_id=%u", DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_ack: no route to %016llx svc_id=%u",
(unsigned long long)rconn->remote_node_id, rconn->svc_id); (unsigned long long)rconn->remote_node_id, rconn->svc_id);
@ -768,7 +768,7 @@ static void router_incoming_q_cb(struct ll_queue* q, void* arg) {
queue_data_put_with_index(rconn->recv_q, rq); queue_data_put_with_index(rconn->recv_q, rq);
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(rconn->inst->bgp, rconn->remote_node_id); struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(rconn->inst->topo_groups), rconn->remote_node_id);;
if (seq == rconn->rx_seq) router_try_assembly(rconn, conn); if (seq == rconn->rx_seq) router_try_assembly(rconn, conn);
router_schedule_ack(rconn); router_schedule_ack(rconn);
queue_resume_callback(q); queue_resume_callback(q);
@ -788,8 +788,8 @@ static int router_verify_signature(struct UTUN_INSTANCE* inst, struct ll_entry*
} }
size_t actual_payload = *pl_len - SC_SIGN_SIZE; size_t actual_payload = *pl_len - SC_SIGN_SIZE;
uint8_t* sig = (uint8_t*)entry->dgram + SVC_ROUTE_HDR_SIZE + actual_payload; uint8_t* sig = (uint8_t*)entry->dgram + SVC_ROUTE_HDR_SIZE + actual_payload;
struct TOPO_BGP* bgp = inst->bgp; struct TOPO_GROUP* group = topo_groups_get_default(inst->topo_groups);
struct TOPO_NODEQ* nq = bgp ? topo_node_find_by_id(bgp, hdr->src_node_id) : NULL; struct TOPO_NODEQ* nq = group ? topo_node_find_by_id(group, hdr->src_node_id) : NULL;
if (!nq) { if (!nq) {
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router: SIGNED packet from unknown node %016llx — dropping", DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router: SIGNED packet from unknown node %016llx — dropping",
(unsigned long long)hdr->src_node_id); (unsigned long long)hdr->src_node_id);
@ -875,7 +875,7 @@ static void router_handle_ack(struct UTUN_INSTANCE* inst, struct ETCP_ROUTER_CON
static void router_forward_transit(struct UTUN_INSTANCE* inst, struct ll_entry* entry, static void router_forward_transit(struct UTUN_INSTANCE* inst, struct ll_entry* entry,
struct SVC_ROUTE_HDR* hdr) { struct SVC_ROUTE_HDR* hdr) {
struct ETCP_CONN* next = topo_bgp_find_conn_for_node(inst->bgp, hdr->dst_node_id); struct ETCP_CONN* next = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), hdr->dst_node_id);
if (!next) { if (!next) {
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "etcp_router: no route to %016llx svc_id=%u, dropping", DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "etcp_router: no route to %016llx svc_id=%u, dropping",
(unsigned long long)hdr->dst_node_id, hdr->svc_id); (unsigned long long)hdr->dst_node_id, hdr->svc_id);
@ -1088,7 +1088,7 @@ int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_
return 0; return 0;
} }
struct ETCP_CONN* etcp_conn = topo_bgp_find_conn_for_node(inst->bgp, dst_node_id); struct ETCP_CONN* etcp_conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), dst_node_id);
if (!etcp_conn) { if (!etcp_conn) {
struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(inst, dst_node_id, svc_id); struct ETCP_ROUTER_CONN* rconn = etcp_router_conn_get(inst, dst_node_id, svc_id);
if (!rconn) { queue_dgram_free(entry); queue_entry_free(entry); return -1; } if (!rconn) { queue_dgram_free(entry); queue_entry_free(entry); return -1; }
@ -1119,8 +1119,8 @@ int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_
} }
int etcp_router_input_q_count(struct UTUN_INSTANCE* inst, uint64_t node_id) { int etcp_router_input_q_count(struct UTUN_INSTANCE* inst, uint64_t node_id) {
if (!inst || !inst->bgp) return -1; if (!inst || !topo_groups_get_default(inst->topo_groups)) return -1;
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, node_id); struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), node_id);
if (!conn || !conn->normalizer || !conn->normalizer->input) return -1; if (!conn || !conn->normalizer || !conn->normalizer->input) return -1;
return queue_entry_count(conn->normalizer->input); return queue_entry_count(conn->normalizer->input);
} }
@ -1128,16 +1128,16 @@ int etcp_router_input_q_count(struct UTUN_INSTANCE* inst, uint64_t node_id) {
void etcp_router_waiter_register(struct UTUN_INSTANCE* inst, uint64_t peer_node_id, void etcp_router_waiter_register(struct UTUN_INSTANCE* inst, uint64_t peer_node_id,
struct queue_waiter_handle* h, struct queue_waiter_handle* h,
queue_threshold_callback_fn callback, void* arg) { queue_threshold_callback_fn callback, void* arg) {
if (!inst || !inst->bgp || !h) return; if (!inst || !topo_groups_get_default(inst->topo_groups) || !h) return;
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, peer_node_id); struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), peer_node_id);
if (!conn || !conn->normalizer || !conn->normalizer->input) return; if (!conn || !conn->normalizer || !conn->normalizer->input) return;
queue_waiter_wait(conn->normalizer->input, h, callback, arg); queue_waiter_wait(conn->normalizer->input, h, callback, arg);
} }
void etcp_router_waiter_cancel(struct UTUN_INSTANCE* inst, uint64_t peer_node_id, void etcp_router_waiter_cancel(struct UTUN_INSTANCE* inst, uint64_t peer_node_id,
struct queue_waiter_handle* h) { struct queue_waiter_handle* h) {
if (!inst || !inst->bgp || !h) return; if (!inst || !topo_groups_get_default(inst->topo_groups) || !h) return;
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, peer_node_id); struct ETCP_CONN* conn = topo_group_find_conn_for_node(topo_groups_get_default(inst->topo_groups), peer_node_id);
if (!conn || !conn->normalizer || !conn->normalizer->input) return; if (!conn || !conn->normalizer || !conn->normalizer->input) return;
queue_waiter_cancel(conn->normalizer->input, h); queue_waiter_cancel(conn->normalizer->input, h);
} }

8
src/msg_transport.c

@ -10,7 +10,7 @@
#include "etcp_router.h" #include "etcp_router.h"
#include "etcp.h" #include "etcp.h"
#include "secure_channel.h" #include "secure_channel.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
#include "../lib/debug_config.h" #include "../lib/debug_config.h"
#include "../lib/mem.h" #include "../lib/mem.h"
@ -457,12 +457,12 @@ static void handle_client_data(struct msg_transport* t, struct msg_client* clien
case MSG_CTL_GET_PEER_INFO: { case MSG_CTL_GET_PEER_INFO: {
uint64_t peer_id = hdr->id; uint64_t peer_id = hdr->id;
struct TOPO_BGP* bgp = t->instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(t->instance->topo_groups);
if (!bgp) { if (!group) {
send_error(client, MSG_ERR_PEER_NOT_FOUND, "BGP not initialized"); send_error(client, MSG_ERR_PEER_NOT_FOUND, "BGP not initialized");
break; break;
} }
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, peer_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(group, peer_id);
if (!nq) { if (!nq) {
send_error(client, MSG_ERR_PEER_NOT_FOUND, "peer not found"); send_error(client, MSG_ERR_PEER_NOT_FOUND, "peer not found");
DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "GET_PEER_INFO: peer=%016llx not found", DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "GET_PEER_INFO: peer=%016llx not found",

7
src/route_connectivity.c

@ -14,7 +14,7 @@
#include "etcp.h" #include "etcp.h"
#include "etcp_connections.h" #include "etcp_connections.h"
#include "topo_node.h" #include "topo_node.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "route_connectivity.h" #include "route_connectivity.h"
#define CONN_MAX_SOCKET_CANDIDATES 8 #define CONN_MAX_SOCKET_CANDIDATES 8
@ -387,9 +387,10 @@ void route_connectivity_cancel_node(struct UTUN_INSTANCE* instance, struct TOPO_
} }
void route_connectivity_cancel_all(struct UTUN_INSTANCE* instance) { void route_connectivity_cancel_all(struct UTUN_INSTANCE* instance) {
if (!instance || !instance->bgp || !instance->bgp->nodes) return; struct TOPO_GROUP* group = topo_groups_get_default(instance->topo_groups);
if (!instance || !group || !group->nodes) return;
int count = 0; int count = 0;
struct ll_entry* e = instance->bgp->nodes->head; struct ll_entry* e = group->nodes->head;
while (e) { while (e) {
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e; struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
nq->connectivity.probe_status = PROBE_STATUS_NONE; nq->connectivity.probe_status = PROBE_STATUS_NONE;

50
src/route_ping.c

@ -15,7 +15,7 @@
#include "etcp.h" #include "etcp.h"
#include "etcp_connections.h" #include "etcp_connections.h"
#include "topo_node.h" #include "topo_node.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "route_ping.h" #include "route_ping.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
@ -36,7 +36,7 @@ struct route_ping_series_ctx {
struct route_ping_pending { struct route_ping_pending {
struct route_ping_pending* next; struct route_ping_pending* next;
struct TOPO_BGP* bgp; struct TOPO_GROUP* group;
uint32_t request_id; uint32_t request_id;
route_ping_callback_t callback; route_ping_callback_t callback;
void* arg; void* arg;
@ -54,8 +54,8 @@ static void route_ping_pending_timeout(void* arg) {
u_free(p); u_free(p);
return; return;
} }
struct TOPO_BGP* bgp = p->bgp; struct TOPO_GROUP* group = p->group;
struct route_ping_pending** cur = &bgp->ping_pending; struct route_ping_pending** cur = &group->ping_pending;
while (*cur) { while (*cur) {
if (*cur == p) { if (*cur == p) {
*cur = p->next; *cur = p->next;
@ -70,8 +70,8 @@ static void route_ping_pending_timeout(void* arg) {
} }
// прошел ответ "серия пигнов на удаленном узле завершена" // прошел ответ "серия пигнов на удаленном узле завершена"
void route_ping_handle_resp(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) { void route_ping_handle_resp(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
if (!bgp || !from_conn || !data || len < sizeof(struct TOPO_PING_RESP)) { if (!group || !from_conn || !data || len < sizeof(struct TOPO_PING_RESP)) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args"); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args");
return; return;
} }
@ -80,13 +80,13 @@ void route_ping_handle_resp(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, c
from_conn->log_name, (unsigned)resp->request_id, from_conn->log_name, (unsigned)resp->request_id,
(unsigned)resp->count_sent, (unsigned)resp->count_ok, (unsigned)resp->avg_rtt); (unsigned)resp->count_sent, (unsigned)resp->count_ok, (unsigned)resp->avg_rtt);
struct route_ping_pending** cur = &bgp->ping_pending; struct route_ping_pending** cur = &group->ping_pending;
while (*cur) { while (*cur) {
struct route_ping_pending* p = *cur; struct route_ping_pending* p = *cur;
if (p->request_id == resp->request_id) { if (p->request_id == resp->request_id) {
*cur = p->next; *cur = p->next;
if (p->timeout_timer) { if (p->timeout_timer) {
uasync_cancel_timeout(bgp->instance->ua, p->timeout_timer); uasync_cancel_timeout(group->instance->ua, p->timeout_timer);
p->timeout_timer = NULL; p->timeout_timer = NULL;
} }
if (p->callback) { if (p->callback) {
@ -102,10 +102,10 @@ void route_ping_handle_resp(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, c
(unsigned)resp->request_id); (unsigned)resp->request_id);
} }
void route_ping_cancel_for_conn(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) { void route_ping_cancel_for_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!bgp || !conn) return; if (!group || !conn) return;
if (!bgp->ping_pending) { if (!group->ping_pending) {
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "cancel_for_conn: ping_pending is NULL for %s", conn->log_name); DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "cancel_for_conn: ping_pending is NULL for %s", conn->log_name);
return; return;
} }
@ -113,7 +113,7 @@ void route_ping_cancel_for_conn(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) {
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "cancel_for_conn: checking pending for %s", conn->log_name); DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "cancel_for_conn: checking pending for %s", conn->log_name);
int cancelled = 0; int cancelled = 0;
struct route_ping_pending** cur = &bgp->ping_pending; struct route_ping_pending** cur = &group->ping_pending;
while (*cur) { while (*cur) {
struct route_ping_pending* p = *cur; struct route_ping_pending* p = *cur;
struct nat_check_arg* na = (struct nat_check_arg*)p->arg; struct nat_check_arg* na = (struct nat_check_arg*)p->arg;
@ -126,7 +126,7 @@ void route_ping_cancel_for_conn(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) {
if ((na && na->link && na->link->etcp == conn) || p->via_conn == conn) { if ((na && na->link && na->link->etcp == conn) || p->via_conn == conn) {
*cur = p->next; *cur = p->next;
if (p->timeout_timer) { if (p->timeout_timer) {
uasync_cancel_timeout(bgp->instance->ua, p->timeout_timer); uasync_cancel_timeout(group->instance->ua, p->timeout_timer);
p->timeout_timer = NULL; p->timeout_timer = NULL;
} }
p->cancelled = 1; p->cancelled = 1;
@ -148,12 +148,12 @@ void route_ping_cancel_for_conn(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) {
// ======================================================================== // ========================================================================
int route_ping_send_req_addr(struct TOPO_BGP* bgp, struct ETCP_CONN* to_conn, int route_ping_send_req_addr(struct TOPO_GROUP* group, struct ETCP_CONN* to_conn,
uint32_t target_ip, uint16_t target_port, uint32_t target_ip, uint16_t target_port,
uint8_t count, uint16_t interval_ms, uint16_t timeout_ms, uint8_t count, uint16_t interval_ms, uint16_t timeout_ms,
uint16_t wait_timeout_ms, route_ping_callback_t cb, void* arg, uint16_t wait_timeout_ms, route_ping_callback_t cb, void* arg,
const uint8_t* pubkey) { const uint8_t* pubkey) {
if (!bgp || !to_conn || count == 0 || timeout_ms == 0) { if (!group || !to_conn || count == 0 || timeout_ms == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args"); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args");
return -1; return -1;
} }
@ -165,7 +165,7 @@ int route_ping_send_req_addr(struct TOPO_BGP* bgp, struct ETCP_CONN* to_conn,
} }
req_pkt->cmd = ETCP_ID_TOPO_ENTRY; req_pkt->cmd = ETCP_ID_TOPO_ENTRY;
req_pkt->subcmd = TOPO_SUBCMD_PING_REQ; req_pkt->subcmd = TOPO_SUBCMD_PING_REQ;
uint32_t new_req_id = bgp->next_ping_req_id++; uint32_t new_req_id = group->next_ping_req_id++;
req_pkt->request_id = new_req_id; req_pkt->request_id = new_req_id;
req_pkt->count = count; req_pkt->count = count;
req_pkt->interval_ms = interval_ms; req_pkt->interval_ms = interval_ms;
@ -203,15 +203,15 @@ int route_ping_send_req_addr(struct TOPO_BGP* bgp, struct ETCP_CONN* to_conn,
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "pending alloc failed"); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "pending alloc failed");
return -5; return -5;
} }
pending->bgp = bgp; pending->group = group;
pending->request_id = new_req_id; // req_pkt may be freed by etcp_send callback pending->request_id = new_req_id; // req_pkt may be freed by etcp_send callback
pending->callback = cb; pending->callback = cb;
pending->arg = arg; pending->arg = arg;
pending->via_conn = to_conn; pending->via_conn = to_conn;
pending->next = bgp->ping_pending; pending->next = group->ping_pending;
bgp->ping_pending = pending; group->ping_pending = pending;
pending->timeout_timer = uasync_set_timeout(bgp->instance->ua, wait_timeout_ms * 10, pending, route_ping_pending_timeout, "route_ping"); pending->timeout_timer = uasync_set_timeout(group->instance->ua, wait_timeout_ms * 10, pending, route_ping_pending_timeout, "route_ping");
return 0; return 0;
} }
@ -303,11 +303,11 @@ static void route_ping_single_cb(int success,
} }
// Обработчик PING_REQ (нам запросили "пропингуй узел и верни результат") // Обработчик PING_REQ (нам запросили "пропингуй узел и верни результат")
void route_ping_handle_req(struct TOPO_BGP* bgp, void route_ping_handle_req(struct TOPO_GROUP* group,
struct ETCP_CONN* from_conn, struct ETCP_CONN* from_conn,
const uint8_t* data, const uint8_t* data,
size_t len) { size_t len) {
if (!bgp || !from_conn || !data || len < offsetof(struct TOPO_PING_REQ, pubkey)) { if (!group || !from_conn || !data || len < offsetof(struct TOPO_PING_REQ, pubkey)) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "ping req: bad args len=%zu", len); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "ping req: bad args len=%zu", len);
return; return;
} }
@ -327,7 +327,7 @@ void route_ping_handle_req(struct TOPO_BGP* bgp,
ctx->timeout_ms = req_pkt->timeout_ms; ctx->timeout_ms = req_pkt->timeout_ms;
{ {
struct TOPO_NODEQ* req_nq = topo_node_find_by_id(bgp, from_conn->peer_node_id); struct TOPO_NODEQ* req_nq = topo_node_find_by_id(group, from_conn->peer_node_id);
if (req_nq) req_nq->connectivity.ping_req_time = get_time_tb(); if (req_nq) req_nq->connectivity.ping_req_time = get_time_tb();
} }
if (len >= sizeof(struct TOPO_PING_REQ)) { if (len >= sizeof(struct TOPO_PING_REQ)) {
@ -356,7 +356,7 @@ void route_ping_handle_req(struct TOPO_BGP* bgp,
*/ */
/* Ищем первый IPv4-сокет (как в старом коде) */ /* Ищем первый IPv4-сокет (как в старом коде) */
struct ETCP_SOCKET* ls = bgp->instance->etcp_sockets; struct ETCP_SOCKET* ls = group->instance->etcp_sockets;
while (ls) { while (ls) {
if (ls->local_addr.ss_family == AF_INET) { if (ls->local_addr.ss_family == AF_INET) {
ctx->local_sock = ls; ctx->local_sock = ls;
@ -377,7 +377,7 @@ void route_ping_handle_req(struct TOPO_BGP* bgp,
/* Запускаем первый пинг (дальше цепочка через callback) */ /* Запускаем первый пинг (дальше цепочка через callback) */
int ret = etcp_send_ping_to_socket( int ret = etcp_send_ping_to_socket(
bgp->instance, group->instance,
ctx->local_sock, ctx->local_sock,
ctx->pubkey, ctx->pubkey,
&ctx->target_addr, &ctx->target_addr,

14
src/route_ping.h

@ -8,7 +8,7 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include "topo_bgp.h" #include "topo_group.h"
#define TOPO_SUBCMD_PING_REQ 0x07 #define TOPO_SUBCMD_PING_REQ 0x07
#define TOPO_SUBCMD_PING_RESP 0x08 #define TOPO_SUBCMD_PING_RESP 0x08
@ -42,21 +42,21 @@ typedef void (*route_ping_callback_t)(int success, uint16_t avg_rtt, uint8_t cou
// Отправить запрос пинга по произвольному IP:port (используется для NAT-детекции) // Отправить запрос пинга по произвольному IP:port (используется для NAT-детекции)
// Если target_ip == 0, используется node_id из списка известных узлов // Если target_ip == 0, используется node_id из списка известных узлов
// Если pubkey != NULL, он передается в пакете (для пинга без локального nodeinfo) // Если pubkey != NULL, он передается в пакете (для пинга без локального nodeinfo)
int route_ping_send_req_addr(struct TOPO_BGP* bgp, struct ETCP_CONN* to_conn, int route_ping_send_req_addr(struct TOPO_GROUP* group, struct ETCP_CONN* to_conn,
uint32_t target_ip, uint16_t target_port, uint32_t target_ip, uint16_t target_port,
uint8_t count, uint16_t interval_ms, uint16_t timeout_ms, uint8_t count, uint16_t interval_ms, uint16_t timeout_ms,
uint16_t wait_timeout_ms, route_ping_callback_t cb, void* arg, uint16_t wait_timeout_ms, route_ping_callback_t cb, void* arg,
const uint8_t* pubkey); const uint8_t* pubkey);
// Очистить список ожидающих запросов (при уничтожении BGP) // Очистить список ожидающих запросов (при уничтожении BGP)
void route_ping_destroy_pending(struct TOPO_BGP* bgp); void route_ping_destroy_pending(struct TOPO_GROUP* group);
// Отменить pending запросы для указанного соединения (при удалении conn) // Отменить pending запросы для указанного соединения (при удалении conn)
void route_ping_cancel_for_conn(struct TOPO_BGP* bgp, struct ETCP_CONN* conn); void route_ping_cancel_for_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn);
// Обработчики, вызываемые из topo_bgp_receive_cbk // Обработчики, вызываемые из topo_group_receive_cbk
void route_ping_handle_req(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len); void route_ping_handle_req(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
void route_ping_handle_resp(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len); void route_ping_handle_resp(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
#ifdef __cplusplus #ifdef __cplusplus

465
src/topo_bgp.c → src/topo_group.c

@ -1,6 +1,6 @@
/** /**
* @file topo_bgp.c * @file topo_group.c
* @brief BGP-like обмен топологией узлов * @brief BGP-like обмен топологией узлов (группы)
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -18,18 +18,21 @@
#include "topo_node.h" #include "topo_node.h"
#include "topo_node_lmdb.h" #include "topo_node_lmdb.h"
#include "route_lib.h" #include "route_lib.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "route_ping.h" #include "route_ping.h"
#include "route_connectivity.h" #include "route_connectivity.h"
#include "control_server.h" #include "control_server.h"
#define TOPO_GROUP_UTUN 0x8000000000000000ULL
// ============================================================================ // ============================================================================
// Вспомогательные функции // Вспомогательные функции
// ============================================================================ // ============================================================================
static void topo_bgp_send_table_request(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) { static void topo_group_send_table_request(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!bgp || !conn) return; if (!group || !conn) return;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending table request to %s", conn->log_name); DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending table request to %s", conn->log_name);
struct TOPOMSG_TABLE_REQ* req = u_calloc(1, sizeof(struct TOPOMSG_TABLE_REQ)); struct TOPOMSG_TABLE_REQ* req = u_calloc(1, sizeof(struct TOPOMSG_TABLE_REQ));
if (!req) return; if (!req) return;
@ -41,8 +44,8 @@ static void topo_bgp_send_table_request(struct TOPO_BGP* bgp, struct ETCP_CONN*
if (etcp_send(conn, e) != 0) { u_free(req); queue_entry_free(e); } if (etcp_send(conn, e) != 0) { u_free(req); queue_entry_free(e); }
} }
static void topo_bgp_send_table_complete(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) { static void topo_group_send_table_complete(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!bgp || !conn) return; if (!group || !conn) return;
struct TOPOMSG_TABLE_REQ* req = u_calloc(1, sizeof(struct TOPOMSG_TABLE_REQ)); struct TOPOMSG_TABLE_REQ* req = u_calloc(1, sizeof(struct TOPOMSG_TABLE_REQ));
if (!req) return; if (!req) return;
req->cmd = ETCP_ID_TOPO_ENTRY; req->cmd = ETCP_ID_TOPO_ENTRY;
@ -53,10 +56,10 @@ static void topo_bgp_send_table_complete(struct TOPO_BGP* bgp, struct ETCP_CONN*
if (etcp_send(conn, e) != 0) { u_free(req); queue_entry_free(e); } if (etcp_send(conn, e) != 0) { u_free(req); queue_entry_free(e); }
} }
static void topo_bgp_add_to_senders(struct TOPO_BGP* bgp, struct ETCP_CONN* conn); static void topo_group_add_to_senders(struct TOPO_GROUP* group, struct ETCP_CONN* conn);
static bool topo_bgp_should_send_to(const struct TOPO_NODEQ* nq, uint64_t target_id); static bool topo_group_should_send_to(const struct TOPO_NODEQ* nq, uint64_t target_id);
static void topo_bgp_send_full_table(struct TOPO_BGP* bgp, struct ETCP_CONN* conn); static void topo_group_send_full_table(struct TOPO_GROUP* group, struct ETCP_CONN* conn);
static void topo_bgp_handle_request_table(struct TOPO_BGP* bgp, struct ETCP_CONN* conn); static void topo_group_handle_request_table(struct TOPO_GROUP* group, struct ETCP_CONN* conn);
static void nodeinfo_dump_log(const uint8_t* data, size_t len) { static void nodeinfo_dump_log(const uint8_t* data, size_t len) {
if (!data || len < sizeof(struct TOPOMSG_NODEINFO_PKT)) return; if (!data || len < sizeof(struct TOPOMSG_NODEINFO_PKT)) return;
@ -99,7 +102,7 @@ static char* nodeinfo_format(const uint8_t* data, size_t len) {
return buf; return buf;
} }
static const char* bgp_subcmd_name(uint8_t subcmd) { static const char* group_subcmd_name(uint8_t subcmd) {
switch (subcmd) { switch (subcmd) {
case TOPO_SUBCMD_NODEINFO: return "NODEINFO"; case TOPO_SUBCMD_NODEINFO: return "NODEINFO";
case TOPO_SUBCMD_REQUEST_TABLE: return "REQ_TABLE"; case TOPO_SUBCMD_REQUEST_TABLE: return "REQ_TABLE";
@ -118,15 +121,15 @@ static const char* bgp_subcmd_name(uint8_t subcmd) {
// Broadcast / Withdraw // Broadcast / Withdraw
// ============================================================================ // ============================================================================
static void topo_bgp_broadcast_withdraw(struct TOPO_BGP* bgp, uint64_t node_id, uint64_t wd_source, struct ETCP_CONN* exclude) { static void topo_group_broadcast_withdraw(struct TOPO_GROUP* group, uint64_t node_id, uint64_t wd_source, struct ETCP_CONN* exclude) {
if (!bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "bgp is NULL"); return; } if (!group) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "group is NULL"); return; }
struct TOPOMSG_WITHDRAW_PKT* pkt = u_calloc(1, sizeof(struct TOPOMSG_WITHDRAW_PKT)); struct TOPOMSG_WITHDRAW_PKT* pkt = u_calloc(1, sizeof(struct TOPOMSG_WITHDRAW_PKT));
if (!pkt) return; if (!pkt) return;
pkt->cmd = ETCP_ID_TOPO_ENTRY; pkt->subcmd = TOPO_SUBCMD_WITHDRAW; pkt->cmd = ETCP_ID_TOPO_ENTRY; pkt->subcmd = TOPO_SUBCMD_WITHDRAW;
pkt->node_id = node_id; pkt->wd_source = wd_source; pkt->node_id = node_id; pkt->wd_source = wd_source;
struct ll_entry* e = bgp->senders_list ? bgp->senders_list->head : NULL; struct ll_entry* e = group->senders_list ? group->senders_list->head : NULL;
while (e) { while (e) {
struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)e->data; struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)e->data;
if (item && item->conn && item->conn != exclude) { if (item && item->conn && item->conn != exclude) {
struct ll_entry* copy = queue_entry_new(0); struct ll_entry* copy = queue_entry_new(0);
if (copy) { copy->dgram = u_malloc(sizeof(*pkt)); if (copy->dgram) memcpy(copy->dgram, pkt, sizeof(*pkt)); copy->len = sizeof(*pkt); etcp_send(item->conn, copy); } if (copy) { copy->dgram = u_malloc(sizeof(*pkt)); if (copy->dgram) memcpy(copy->dgram, pkt, sizeof(*pkt)); copy->len = sizeof(*pkt); etcp_send(item->conn, copy); }
@ -141,26 +144,27 @@ static void topo_bgp_broadcast_withdraw(struct TOPO_BGP* bgp, uint64_t node_id,
// Приём пакетов // Приём пакетов
// ============================================================================ // ============================================================================
static void topo_bgp_handle_nat_info(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len); static void topo_group_handle_nat_info(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
static void topo_bgp_handle_nat_check_req(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len); static void topo_group_handle_nat_check_req(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
static void topo_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry) { static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry) {
if (!from_conn || !entry || entry->len < 2) { if (entry) { queue_dgram_free(entry); queue_entry_free(entry); } return; } if (!from_conn || !entry || entry->len < 2) { if (entry) { queue_dgram_free(entry); queue_entry_free(entry); } return; }
struct UTUN_INSTANCE* instance = from_conn->instance; struct UTUN_INSTANCE* instance = from_conn->instance;
if (!instance || !instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_receive_cbk: invalid instance/bgp"); queue_dgram_free(entry); queue_entry_free(entry); return; } if (!instance || !instance->topo_groups) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_receive_cbk: invalid instance/topo_groups"); queue_dgram_free(entry); queue_entry_free(entry); return; }
struct TOPO_BGP* bgp = instance->bgp; struct TOPO_GROUP* group = topo_groups_get_default(instance->topo_groups);
if (!group) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_receive_cbk: no default group"); queue_dgram_free(entry); queue_entry_free(entry); return; }
uint8_t* data = entry->dgram; uint8_t cmd = data[0]; uint8_t subcmd = data[1]; uint8_t* data = entry->dgram; uint8_t cmd = data[0]; uint8_t subcmd = data[1];
if (cmd != ETCP_ID_TOPO_ENTRY) { queue_dgram_free(entry); queue_entry_free(entry); return; } if (cmd != ETCP_ID_TOPO_ENTRY) { queue_dgram_free(entry); queue_entry_free(entry); return; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP recv %s from %s len=%zu", bgp_subcmd_name(subcmd), from_conn->log_name, entry->len); DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP recv %s from %s len=%zu", group_subcmd_name(subcmd), from_conn->log_name, entry->len);
if (subcmd == TOPO_SUBCMD_NODEINFO) { nodeinfo_dump_log(data, entry->len); topo_bgp_process_nodeinfo(bgp, from_conn, data, entry->len); } if (subcmd == TOPO_SUBCMD_NODEINFO) { nodeinfo_dump_log(data, entry->len); topo_group_process_nodeinfo(group, from_conn, data, entry->len); }
else if (subcmd == TOPO_SUBCMD_WITHDRAW) topo_bgp_process_withdraw(bgp, from_conn, data, entry->len); else if (subcmd == TOPO_SUBCMD_WITHDRAW) topo_group_process_withdraw(group, from_conn, data, entry->len);
else if (subcmd == TOPO_SUBCMD_REQUEST_TABLE) topo_bgp_handle_request_table(bgp, from_conn); else if (subcmd == TOPO_SUBCMD_REQUEST_TABLE) topo_group_handle_request_table(group, from_conn);
else if (subcmd == TOPO_SUBCMD_PING_REQ) route_ping_handle_req(bgp, from_conn, data, entry->len); else if (subcmd == TOPO_SUBCMD_PING_REQ) route_ping_handle_req(group, from_conn, data, entry->len);
else if (subcmd == TOPO_SUBCMD_PING_RESP) route_ping_handle_resp(bgp, from_conn, data, entry->len); else if (subcmd == TOPO_SUBCMD_PING_RESP) route_ping_handle_resp(group, from_conn, data, entry->len);
else if (subcmd == TOPO_SUBCMD_NAT_INFO) topo_bgp_handle_nat_info(bgp, from_conn, data, entry->len); else if (subcmd == TOPO_SUBCMD_NAT_INFO) topo_group_handle_nat_info(group, from_conn, data, entry->len);
else if (subcmd == TOPO_SUBCMD_NAT_CHECK_REQ) topo_bgp_handle_nat_check_req(bgp, from_conn, data, entry->len); else if (subcmd == TOPO_SUBCMD_NAT_CHECK_REQ) topo_group_handle_nat_check_req(group, from_conn, data, entry->len);
else if (subcmd == TOPO_SUBCMD_TABLE_COMPLETE) { etcp_set_routing_exchange_state(from_conn, 3); DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP initial sync complete with %s", from_conn->log_name); } else if (subcmd == TOPO_SUBCMD_TABLE_COMPLETE) { etcp_set_routing_exchange_state(from_conn, 3); DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP initial sync complete with %s", from_conn->log_name); }
queue_dgram_free(entry); queue_entry_free(entry); queue_dgram_free(entry); queue_entry_free(entry);
@ -171,143 +175,204 @@ static void topo_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* e
// Init / Destroy / New / Remove conn // Init / Destroy / New / Remove conn
// ============================================================================ // ============================================================================
static void topo_bgp_on_conn_up(struct ETCP_CONN* conn, void* arg) { static void topo_group_on_conn_up(struct ETCP_CONN* conn, void* arg) {
(void)arg; if (conn && conn->instance && conn->instance->bgp) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer UP: %s peer=%016llx", conn->log_name, (unsigned long long)conn->peer_node_id); topo_bgp_new_conn(conn); } (void)arg;
if (conn && conn->instance && conn->instance->topo_groups) {
struct TOPO_GROUP* group = topo_groups_get_default(conn->instance->topo_groups);
if (group) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer UP: %s peer=%016llx", conn->log_name, (unsigned long long)conn->peer_node_id); topo_group_new_conn(group, conn); }
}
}
static void topo_group_on_conn_down(struct ETCP_CONN* conn, void* arg) {
(void)arg;
if (conn && conn->instance && conn->instance->topo_groups) {
struct TOPO_GROUP* group = topo_groups_get_default(conn->instance->topo_groups);
if (group) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer DOWN: %s peer=%016llx", conn->log_name, (unsigned long long)conn->peer_node_id); topo_group_remove_conn(group, conn); }
} }
static void topo_bgp_on_conn_down(struct ETCP_CONN* conn, void* arg) {
(void)arg; if (conn && conn->instance && conn->instance->bgp) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer DOWN: %s peer=%016llx", conn->log_name, (unsigned long long)conn->peer_node_id); topo_bgp_remove_conn(conn); }
} }
static void topo_bgp_etcp_conn_cbk(struct ETCP_CONN* conn, void* arg) { static void topo_group_etcp_conn_cbk(struct ETCP_CONN* conn, void* arg) {
(void)arg; if (conn && conn->instance && conn->instance->bgp) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP set callbacks: %s", conn->log_name); etcp_conn_add_up_cbk(conn, topo_bgp_on_conn_up, conn->instance->bgp); etcp_conn_add_down_cbk(conn, topo_bgp_on_conn_down, conn->instance->bgp); } (void)arg;
if (conn && conn->instance && conn->instance->topo_groups) {
struct TOPO_GROUP* group = topo_groups_get_default(conn->instance->topo_groups);
if (group) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP set callbacks: %s", conn->log_name); etcp_conn_add_up_cbk(conn, topo_group_on_conn_up, group); etcp_conn_add_down_cbk(conn, topo_group_on_conn_down, group); }
}
} }
struct TOPO_BGP* topo_bgp_init(struct UTUN_INSTANCE* instance) { static struct TOPO_GROUP* topo_group_create(struct UTUN_INSTANCE* instance, uint64_t group_id) {
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_init: instance is NULL"); return NULL; } if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_create: instance is NULL"); return NULL; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_bgp_init: node_id=%016llx", (unsigned long long)instance->node_id); DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_group_create: group_id=%016llx node_id=%016llx", (unsigned long long)group_id, (unsigned long long)instance->node_id);
struct TOPO_BGP* bgp = u_calloc(1, sizeof(struct TOPO_BGP)); struct TOPO_GROUP* group = u_calloc(1, sizeof(struct TOPO_GROUP));
if (!bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_init: alloc failed"); return NULL; } if (!group) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_create: alloc failed"); return NULL; }
bgp->instance = instance; group->group_id = group_id;
bgp->ping_pending = NULL; bgp->next_ping_req_id = 1; group->instance = instance;
bgp->nodeinfo_env = NULL; bgp->nodeinfo_dbi = 0; group->ping_pending = NULL; group->next_ping_req_id = 1;
group->nodeinfo_env = NULL; group->nodeinfo_dbi = 0;
sc_derive_ed25519_pubkey(instance->my_keys.private_key, bgp->ed25519_public_key); sc_derive_ed25519_pubkey(instance->my_keys.private_key, group->ed25519_public_key);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Ed25519 pubkey derived from X25519 private key"); DEBUG_INFO(DEBUG_CATEGORY_BGP, "Ed25519 pubkey derived from X25519 private key");
if (instance->config && instance->config->global.db_path[0]) topo_node_lmdb_init(bgp, instance->config->global.db_path); if (instance->config && instance->config->global.db_path[0]) topo_node_lmdb_init(group, instance->config->global.db_path);
group->nodes = queue_new(instance->ua, BGP_NODES_HASH_SIZE, offsetof(struct TOPO_NODEQ, hash_node_id) - sizeof(struct ll_entry), 8, "group_nodes");
if (!group->nodes) { u_free(group); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_create: nodes queue creation failed"); return NULL; }
bgp->nodes = queue_new(instance->ua, BGP_NODES_HASH_SIZE, offsetof(struct TOPO_NODEQ, hash_node_id) - sizeof(struct ll_entry), 8, "bgp_nodes"); group->senders_list = queue_new(instance->ua, 0, 0, 0, "group_senders");
if (!bgp->nodes) { u_free(bgp); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_init: nodes queue creation failed"); return NULL; } if (!group->senders_list) { queue_free(group->nodes); u_free(group); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_create: senders_list queue creation failed"); return NULL; }
bgp->senders_list = queue_new(instance->ua, 0, 0, 0, "BGP_senders"); group->local_node = NULL;
if (!bgp->senders_list) { queue_free(bgp->nodes); u_free(bgp); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_init: senders_list queue creation failed"); return NULL; } topo_group_update_my_nodeinfo(instance, group);
bgp->v4_sock_meta_pool = memory_pool_init(sizeof(struct TOPO_SOCKMETA4), "to_v4sock"); DEBUG_INFO(DEBUG_CATEGORY_BGP, "TOPO group created: group_id=%016llx", (unsigned long long)group_id);
bgp->v4_addr_pool = memory_pool_init(sizeof(struct TOPO_ADDR4), "to_v4addr"); return group;
bgp->v6_sock_meta_pool = memory_pool_init(sizeof(struct TOPO_SOCKMETA6), "to_v6sock"); }
bgp->v6_addr_pool = memory_pool_init(sizeof(struct TOPO_ADDR6), "to_v6addr");
bgp->v4_subnet_pool = memory_pool_init(sizeof(struct TOPO_SUBNET4), "to_v4sub");
bgp->v6_subnet_pool = memory_pool_init(sizeof(struct TOPO_SUBNET6), "to_v6sub");
bgp->local_node = NULL; static void topo_group_destroy(struct TOPO_GROUP* group) {
topo_bgp_update_my_nodeinfo(instance, bgp); if (!group) return;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_group_destroy: group_id=%016llx", (unsigned long long)group->group_id);
etcp_bind(instance, ETCP_ID_TOPO_ENTRY, topo_bgp_receive_cbk); struct ll_entry* e;
etcp_add_new_conn_cbk(instance, topo_bgp_etcp_conn_cbk, NULL); while ((e = queue_data_get(group->senders_list)) != NULL) queue_entry_free(e);
queue_free(group->senders_list);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "TOPO BGP module initialized"); if (group->local_node) { topo_node_free_lists(group, group->local_node); u_free(group->local_node); }
return bgp;
topo_node_lmdb_destroy(group);
if (group->nodes) queue_free(group->nodes);
u_free(group);
} }
void topo_bgp_destroy(struct UTUN_INSTANCE* instance) { struct TOPO_GROUPS* topo_groups_init(struct UTUN_INSTANCE* instance) {
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_destroy: instance is NULL"); return; } if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_groups_init: instance is NULL"); return NULL; }
if (!instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_destroy: bgp is NULL"); return; } DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_groups_init: node_id=%016llx", (unsigned long long)instance->node_id);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_bgp_destroy: node_id=%016llx", (unsigned long long)instance->node_id);
struct TOPO_GROUPS* g = u_calloc(1, sizeof(struct TOPO_GROUPS));
if (!g) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_groups_init: alloc failed"); return NULL; }
g->instance = instance;
g->group_list = queue_new(instance->ua, 0, 0, 0, "topo_groups");
if (!g->group_list) { u_free(g); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_groups_init: group_list queue creation failed"); return NULL; }
g->v4_sock_meta_pool = memory_pool_init(sizeof(struct TOPO_SOCKMETA4), "to_v4sock");
g->v4_addr_pool = memory_pool_init(sizeof(struct TOPO_ADDR4), "to_v4addr");
g->v6_sock_meta_pool = memory_pool_init(sizeof(struct TOPO_SOCKMETA6), "to_v6sock");
g->v6_addr_pool = memory_pool_init(sizeof(struct TOPO_ADDR6), "to_v6addr");
g->v4_subnet_pool = memory_pool_init(sizeof(struct TOPO_SUBNET4), "to_v4sub");
g->v6_subnet_pool = memory_pool_init(sizeof(struct TOPO_SUBNET6), "to_v6sub");
instance->topo_groups = g;
struct TOPO_GROUP* default_group = topo_group_create(instance, TOPO_GROUP_UTUN);
if (!default_group) {
memory_pool_destroy(g->v4_sock_meta_pool); memory_pool_destroy(g->v4_addr_pool);
memory_pool_destroy(g->v6_sock_meta_pool); memory_pool_destroy(g->v6_addr_pool);
memory_pool_destroy(g->v4_subnet_pool); memory_pool_destroy(g->v6_subnet_pool);
queue_free(g->group_list); u_free(g);
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_groups_init: failed to create default group");
return NULL;
}
{ struct ll_entry* e = queue_entry_new(sizeof(struct TOPO_GROUP)); if (e) { *(struct TOPO_GROUP**)e->data = default_group; queue_data_put(g->group_list, e); } }
etcp_bind(instance, ETCP_ID_TOPO_ENTRY, topo_group_receive_cbk);
etcp_add_new_conn_cbk(instance, topo_group_etcp_conn_cbk, NULL);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "TOPO groups initialized (with default group)");
return g;
}
void topo_groups_destroy(struct UTUN_INSTANCE* instance) {
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_groups_destroy: instance is NULL"); return; }
if (!instance->topo_groups) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_groups_destroy: topo_groups is NULL"); return; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_groups_destroy: node_id=%016llx", (unsigned long long)instance->node_id);
etcp_unbind(instance, ETCP_ID_TOPO_ENTRY); etcp_unbind(instance, ETCP_ID_TOPO_ENTRY);
route_connectivity_cancel_all(instance); route_connectivity_cancel_all(instance);
struct ll_entry* e; struct TOPO_GROUPS* g = instance->topo_groups;
while ((e = queue_data_get(instance->bgp->senders_list)) != NULL) queue_entry_free(e); struct ll_entry* ge;
queue_free(instance->bgp->senders_list); while ((ge = queue_data_get(g->group_list)) != NULL) { topo_group_destroy(*(struct TOPO_GROUP**)ge->data); queue_entry_free(ge); }
queue_free(g->group_list);
if (instance->bgp->local_node) { topo_node_free_lists(instance->bgp, instance->bgp->local_node); u_free(instance->bgp->local_node); }
topo_node_lmdb_destroy(instance->bgp); memory_pool_destroy(g->v4_sock_meta_pool);
memory_pool_destroy(g->v4_addr_pool);
memory_pool_destroy(g->v6_sock_meta_pool);
memory_pool_destroy(g->v6_addr_pool);
memory_pool_destroy(g->v4_subnet_pool);
memory_pool_destroy(g->v6_subnet_pool);
if (instance->bgp->nodes) queue_free(instance->bgp->nodes); u_free(g); instance->topo_groups = NULL;
}
memory_pool_destroy(instance->bgp->v4_sock_meta_pool); struct TOPO_GROUP* topo_groups_get_default(struct TOPO_GROUPS* g) {
memory_pool_destroy(instance->bgp->v4_addr_pool); return topo_groups_find(g, TOPO_GROUP_UTUN);
memory_pool_destroy(instance->bgp->v6_sock_meta_pool); }
memory_pool_destroy(instance->bgp->v6_addr_pool);
memory_pool_destroy(instance->bgp->v4_subnet_pool);
memory_pool_destroy(instance->bgp->v6_subnet_pool);
u_free(instance->bgp); instance->bgp = NULL; struct TOPO_GROUP* topo_groups_find(struct TOPO_GROUPS* g, uint64_t group_id) {
if (!g || !g->group_list) return NULL;
struct ll_entry* e = g->group_list->head;
while (e) { struct TOPO_GROUP* grp = *(struct TOPO_GROUP**)e->data; if (grp && grp->group_id == group_id) return grp; e = e->next; }
return NULL;
} }
void topo_bgp_set_nat_check_local(struct TOPO_BGP* bgp, int allow) { if (!bgp) return; bgp->allow_nat_check_local = allow ? 1 : 0; } void topo_group_set_nat_check_local(struct TOPO_GROUP* group, int allow) { if (!group) return; group->allow_nat_check_local = allow ? 1 : 0; }
void topo_bgp_new_conn(struct ETCP_CONN* conn) { void topo_group_new_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_new_conn: conn is NULL"); return; } if (!group || !conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_new_conn: invalid args"); return; }
if (!conn->instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_new_conn: conn->instance is NULL"); return; } if (!conn->instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_new_conn: conn->instance is NULL"); return; }
if (!conn->instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_new_conn: conn->instance->bgp is NULL"); return; } if (!conn->instance->rt) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_new_conn: conn->instance->rt is NULL"); return; }
if (!conn->instance->rt) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_new_conn: conn->instance->rt is NULL"); return; }
struct TOPO_BGP* bgp = conn->instance->bgp; struct TOPO_NODEQ* peer_nq = topo_node_find_by_id(group, conn->peer_node_id);
struct TOPO_NODEQ* peer_nq = topo_node_find_by_id(bgp, conn->peer_node_id); topo_group_add_to_senders(group, conn);
topo_bgp_add_to_senders(bgp, conn); if (peer_nq && peer_nq->alien) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_group_new_conn: peer 0x%016llx is alien, skipping route exchange", (unsigned long long)conn->peer_node_id); return; }
if (peer_nq && peer_nq->alien) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_bgp_new_conn: peer 0x%016llx is alien, skipping route exchange", (unsigned long long)conn->peer_node_id); return; }
struct ETCP_CONN* c = conn->instance->connections; struct ETCP_CONN* c = conn->instance->connections;
while (c) { struct ETCP_LINK* l = c->links; while (l) { if (l->initialized && l->conn && l->nat_check_status < NAT_CHECK_IN_PROGRESS) topo_bgp_start_link_nat_check(bgp, l); l = l->next; } c = c->next; } while (c) { struct ETCP_LINK* l = c->links; while (l) { if (l->initialized && l->conn && l->nat_check_status < NAT_CHECK_IN_PROGRESS) topo_group_start_link_nat_check(group, l); l = l->next; } c = c->next; }
topo_bgp_send_table_request(bgp, conn); topo_group_send_table_request(group, conn);
} }
void topo_bgp_remove_conn(struct ETCP_CONN* conn) { void topo_group_remove_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_remove_conn: conn is NULL"); return; } if (!group || !conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_remove_conn: invalid args"); return; }
if (!conn->instance || !conn->instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_remove_conn: invalid instance/bgp"); return; } if (!conn->instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_remove_conn: invalid instance"); return; }
struct TOPO_BGP* bgp = conn->instance->bgp;
bool found_in_list = false; bool found_in_list = false;
struct ll_entry* e = bgp->senders_list->head; struct ll_entry* e = group->senders_list->head;
while (e) { struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)e->data; if (item->conn == conn) { found_in_list = true; break; } e = e->next; } while (e) { struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)e->data; if (item->conn == conn) { found_in_list = true; break; } e = e->next; }
if (!found_in_list) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "topo_bgp_remove_conn: conn already removed or not in list, skipping"); return; } if (!found_in_list) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "topo_group_remove_conn: conn already removed or not in list, skipping"); return; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_bgp_remove_conn: peer=%016llx", (unsigned long long)conn->peer_node_id); DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_group_remove_conn: peer=%016llx", (unsigned long long)conn->peer_node_id);
route_ping_cancel_for_conn(bgp, conn); route_ping_cancel_for_conn(group, conn);
struct ETCP_LINK* lnk = conn->links; while (lnk) { if (lnk->nat_check_status == NAT_CHECK_IN_PROGRESS) lnk->nat_check_status = NAT_CHECK_NONE; lnk = lnk->next; } struct ETCP_LINK* lnk = conn->links; while (lnk) { if (lnk->nat_check_status == NAT_CHECK_IN_PROGRESS) lnk->nat_check_status = NAT_CHECK_NONE; lnk = lnk->next; }
struct ROUTE_TABLE* rt = conn->instance->rt; struct ROUTE_TABLE* rt = conn->instance->rt;
int nodes_removed = 0; int nodes_removed = 0;
struct ll_entry* node_entry = bgp->nodes ? bgp->nodes->head : NULL; struct ll_entry* node_entry = group->nodes ? group->nodes->head : NULL;
while (node_entry) { while (node_entry) {
struct ll_entry* next = node_entry->next; struct ll_entry* next = node_entry->next;
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)node_entry; struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)node_entry;
if (topo_bgp_remove_path(nq, conn) == 1) { if (topo_group_remove_path(nq, conn) == 1) {
if (rt) route_delete(rt, nq); if (rt) route_delete(rt, nq);
if (conn->instance && conn->instance->control_srv) control_server_notify_node_removed(conn->instance->control_srv, nq->hash_node_id); if (conn->instance && conn->instance->control_srv) control_server_notify_node_removed(conn->instance->control_srv, nq->hash_node_id);
nq->dirty = 1; nq->dirty = 1;
route_connectivity_cancel_node(conn->instance, nq); route_connectivity_cancel_node(conn->instance, nq);
if (nq->paths) { queue_free(nq->paths); nq->paths = NULL; } if (nq->paths) { queue_free(nq->paths); nq->paths = NULL; }
uint64_t key = nq->hash_node_id; uint64_t key = nq->hash_node_id;
topo_node_free_lists(bgp, nq); topo_node_free_lists(group, nq);
struct ll_entry* entry = node_entry; struct ll_entry* entry = node_entry;
if (entry) { queue_remove_data(bgp->nodes, entry); queue_entry_free(entry); } if (entry) { queue_remove_data(group->nodes, entry); queue_entry_free(entry); }
nodes_removed++; nodes_removed++;
etcp_router_conn_close_all_for_node(bgp->instance, key); etcp_router_conn_close_all_for_node(group->instance, key);
uint64_t wd_src = (key == conn->peer_node_id) ? conn->instance->node_id : conn->peer_node_id; uint64_t wd_src = (key == conn->peer_node_id) ? conn->instance->node_id : conn->peer_node_id;
topo_bgp_broadcast_withdraw(bgp, key, wd_src, NULL); topo_group_broadcast_withdraw(group, key, wd_src, NULL);
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Removed node %016llx after link down", (unsigned long long)key); DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Removed node %016llx after link down", (unsigned long long)key);
} }
node_entry = next; node_entry = next;
} }
e = bgp->senders_list->head; e = group->senders_list->head;
while (e) { struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)e->data; if (item->conn == conn) { queue_remove_data(bgp->senders_list, e); queue_entry_free(e); break; } e = e->next; } while (e) { struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)e->data; if (item->conn == conn) { queue_remove_data(group->senders_list, e); queue_entry_free(e); break; } e = e->next; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer removed: %s nodes=%d", conn->log_name, nodes_removed); DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer removed: %s nodes=%d", conn->log_name, nodes_removed);
} }
@ -317,9 +382,9 @@ void topo_bgp_remove_conn(struct ETCP_CONN* conn) {
// NODEINFO BASED IMPLEMENTATION // NODEINFO BASED IMPLEMENTATION
// ============================================================================ // ============================================================================
struct ETCP_CONN* topo_bgp_find_conn_for_node(struct TOPO_BGP* bgp, uint64_t node_id) { struct ETCP_CONN* topo_group_find_conn_for_node(struct TOPO_GROUP* group, uint64_t node_id) {
if (!bgp) return NULL; if (!group) return NULL;
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(group, node_id);
if (!nq || !nq->paths || !nq->paths->head) return NULL; if (!nq || !nq->paths || !nq->paths->head) return NULL;
struct ll_entry* e = nq->paths->head; struct ll_entry* e = nq->paths->head;
struct TOPO_NODEPATH* best_live = NULL; uint8_t best_live_hops = 255; struct TOPO_NODEPATH* best_live = NULL; uint8_t best_live_hops = 255;
@ -333,7 +398,7 @@ struct ETCP_CONN* topo_bgp_find_conn_for_node(struct TOPO_BGP* bgp, uint64_t nod
return best_live ? best_live->conn : (best_any ? best_any->conn : NULL); return best_live ? best_live->conn : (best_any ? best_any->conn : NULL);
} }
int topo_bgp_add_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count) { int topo_group_add_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count) {
if (!nq || !conn || hop_count > MAX_HOPS || !hop_list) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "add_path: invalid args"); return -1; } if (!nq || !conn || hop_count > MAX_HOPS || !hop_list) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "add_path: invalid args"); return -1; }
if (!nq->paths) { nq->paths = queue_new(conn->instance->ua, 0, 0, 0, "node_paths"); if (!nq->paths) return -1; } if (!nq->paths) { nq->paths = queue_new(conn->instance->ua, 0, 0, 0, "node_paths"); if (!nq->paths) return -1; }
size_t path_size = sizeof(struct TOPO_NODEPATH) - sizeof(struct ll_entry) + hop_count * 8; size_t path_size = sizeof(struct TOPO_NODEPATH) - sizeof(struct ll_entry) + hop_count * 8;
@ -345,7 +410,7 @@ int topo_bgp_add_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn, uint64_t* h
return 0; return 0;
} }
int topo_bgp_remove_path_by_hop(struct TOPO_NODEQ* nq, uint64_t wd_source) { static int topo_group_remove_path_by_hop(struct TOPO_NODEQ* nq, uint64_t wd_source) {
if (!nq || !nq->paths) return 0; if (!nq || !nq->paths) return 0;
int removed = 0; int removed = 0;
struct ll_entry* e = nq->paths->head; struct ll_entry* e = nq->paths->head;
@ -360,7 +425,7 @@ int topo_bgp_remove_path_by_hop(struct TOPO_NODEQ* nq, uint64_t wd_source) {
return removed; return removed;
} }
int topo_bgp_remove_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn) { int topo_group_remove_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn) {
if (!nq || !conn || !nq->paths) return -1; if (!nq || !conn || !nq->paths) return -1;
struct ll_entry* e = nq->paths->head; struct ll_entry* e = nq->paths->head;
while (e) { struct TOPO_NODEPATH* path = (struct TOPO_NODEPATH*)e; if (path->conn == conn) { queue_remove_data(nq->paths, e); queue_entry_free(e); break; } e = e->next; } while (e) { struct TOPO_NODEPATH* path = (struct TOPO_NODEPATH*)e; if (path->conn == conn) { queue_remove_data(nq->paths, e); queue_entry_free(e); break; } e = e->next; }
@ -378,45 +443,45 @@ static void nat_link_check_cb(int success, uint16_t avg_rtt, uint8_t count_sent,
if (link->nat_check_status != NAT_CHECK_IN_PROGRESS) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "nat check cb: link status=%d, skip (conn down?)", link->nat_check_status); u_free(na); return; } if (link->nat_check_status != NAT_CHECK_IN_PROGRESS) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "nat check cb: link status=%d, skip (conn down?)", link->nat_check_status); u_free(na); return; }
link->nat_type = success ? NAT_TYPE_EIM : NAT_TYPE_STRICT; link->nat_type = success ? NAT_TYPE_EIM : NAT_TYPE_STRICT;
link->nat_check_status = success ? NAT_CHECK_EIM : NAT_CHECK_STRICT; link->nat_check_status = success ? NAT_CHECK_EIM : NAT_CHECK_STRICT;
if (link->etcp) topo_bgp_send_nat_info(link->etcp, link->remote_socket_id, na->nat_ip, na->nat_port, link->nat_type); if (link->etcp) topo_group_send_nat_info(link->etcp, link->remote_socket_id, na->nat_ip, na->nat_port, link->nat_type);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT check result: type=%s for conn=%s nat=%s:%u", success ? "EIM" : "STRICT", link->etcp->log_name, ip_to_str(&na->nat_ip, AF_INET).str, na->nat_port); DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT check result: type=%s for conn=%s nat=%s:%u", success ? "EIM" : "STRICT", link->etcp->log_name, ip_to_str(&na->nat_ip, AF_INET).str, na->nat_port);
u_free(na); u_free(na);
} }
static struct ETCP_CONN* topo_bgp_find_third_node(struct TOPO_BGP* bgp, struct ETCP_CONN* exclude) { static struct ETCP_CONN* topo_group_find_third_node(struct TOPO_GROUP* group, struct ETCP_CONN* exclude) {
if (!bgp || !bgp->senders_list) return NULL; if (!group || !group->senders_list) return NULL;
struct ll_entry* e = bgp->senders_list->head; struct ll_entry* e = group->senders_list->head;
while (e) { struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)e->data; if (item && item->conn && item->conn != exclude && item->conn->links && item->conn->links->remote_only_local==0 && item->conn->links->remote_type != CFG_SERVER_TYPE_PRIVATE && item->conn->links->remote_type != CFG_SERVER_TYPE_LOCAL) return item->conn; e = e->next; } while (e) { struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)e->data; if (item && item->conn && item->conn != exclude && item->conn->links && item->conn->links->remote_only_local==0 && item->conn->links->remote_type != CFG_SERVER_TYPE_PRIVATE && item->conn->links->remote_type != CFG_SERVER_TYPE_LOCAL) return item->conn; e = e->next; }
return NULL; return NULL;
} }
void topo_bgp_start_link_nat_check(struct TOPO_BGP* bgp, struct ETCP_LINK* link) { void topo_group_start_link_nat_check(struct TOPO_GROUP* group, struct ETCP_LINK* link) {
if (!bgp || !link || !link->conn || !link->etcp) return; if (!group || !link || !link->conn || !link->etcp) return;
if (link->nat_type == NAT_TYPE_DIRECT) return; if (link->nat_type == NAT_TYPE_DIRECT) return;
if (link->nat_check_status == NAT_CHECK_IN_PROGRESS) return; if (link->nat_check_status == NAT_CHECK_IN_PROGRESS) return;
if (link->conn->type == CFG_SERVER_TYPE_PRIVATE || link->conn->type == CFG_SERVER_TYPE_LOCAL) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "skip nat check for private/local socket link"); return; } if (link->conn->type == CFG_SERVER_TYPE_PRIVATE || link->conn->type == CFG_SERVER_TYPE_LOCAL) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "skip nat check for private/local socket link"); return; }
struct ETCP_CONN* third_conn = topo_bgp_find_third_node(bgp, link->etcp); struct ETCP_CONN* third_conn = topo_group_find_third_node(group, link->etcp);
if (!third_conn) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "no third node found for link"); return; } if (!third_conn) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "no third node found for link"); return; }
uint32_t target_ip; uint16_t target_port; uint32_t target_ip; uint16_t target_port;
if (link->nat_ip != 0 && link->nat_port != 0) { target_ip = link->nat_ip; target_port = link->nat_port; } if (link->nat_ip != 0 && link->nat_port != 0) { target_ip = link->nat_ip; target_port = link->nat_port; }
else { struct sockaddr_in* sin = (struct sockaddr_in*)&link->remote_addr; target_ip = sin->sin_addr.s_addr; target_port = ntohs(sin->sin_port); } else { struct sockaddr_in* sin = (struct sockaddr_in*)&link->remote_addr; target_ip = sin->sin_addr.s_addr; target_port = ntohs(sin->sin_port); }
if (!bgp->allow_nat_check_local && is_local_subnet(target_ip)) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "local connection: %s, skip nat check", ip_to_str(&target_ip, AF_INET).str); return; } if (!group->allow_nat_check_local && is_local_subnet(target_ip)) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "local connection: %s, skip nat check", ip_to_str(&target_ip, AF_INET).str); return; }
struct nat_check_arg* arg = u_calloc(1, sizeof(struct nat_check_arg)); struct nat_check_arg* arg = u_calloc(1, sizeof(struct nat_check_arg));
if (!arg) return; arg->link = link; arg->nat_ip = target_ip; arg->nat_port = target_port; if (!arg) return; arg->link = link; arg->nat_ip = target_ip; arg->nat_port = target_port;
const uint8_t* pubkey = link->etcp->crypto_ctx.peer_key_set ? link->etcp->crypto_ctx.peer_public_key : NULL; const uint8_t* pubkey = link->etcp->crypto_ctx.peer_key_set ? link->etcp->crypto_ctx.peer_public_key : NULL;
if (!pubkey) { u_free(arg); DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "no peer pubkey for link=%p", (void*)link); return; } if (!pubkey) { u_free(arg); DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "no peer pubkey for link=%p", (void*)link); return; }
int ret = route_ping_send_req_addr(bgp, third_conn, target_ip, target_port, 3, 500, 1000, 5000, nat_link_check_cb, arg, pubkey); int ret = route_ping_send_req_addr(group, third_conn, target_ip, target_port, 3, 500, 1000, 5000, nat_link_check_cb, arg, pubkey);
if (ret == 0) { link->nat_check_status = NAT_CHECK_IN_PROGRESS; DEBUG_INFO(DEBUG_CATEGORY_BGP, "ping remote request via=%s (%s:%d)", third_conn->log_name, ip_to_str(&target_ip, AF_INET).str, target_port); } if (ret == 0) { link->nat_check_status = NAT_CHECK_IN_PROGRESS; DEBUG_INFO(DEBUG_CATEGORY_BGP, "ping remote request via=%s (%s:%d)", third_conn->log_name, ip_to_str(&target_ip, AF_INET).str, target_port); }
else { u_free(arg); DEBUG_WARN(DEBUG_CATEGORY_BGP, "failed to start for link=%s (%s:%d)", third_conn->log_name, ip_to_str(&target_ip, AF_INET).str, target_port); } else { u_free(arg); DEBUG_WARN(DEBUG_CATEGORY_BGP, "failed to start for link=%s (%s:%d)", third_conn->log_name, ip_to_str(&target_ip, AF_INET).str, target_port); }
} }
// ===== NODEINFO process ===== // ===== NODEINFO process =====
int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, const uint8_t* data, size_t len) { int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from, const uint8_t* data, size_t len) {
if (!bgp || !from || len < sizeof(struct TOPOMSG_NODEINFO_PKT)) return -1; if (!group || !from || len < sizeof(struct TOPOMSG_NODEINFO_PKT)) return -1;
struct TOPOMSG_NODEINFO_PKT* pkt = (struct TOPOMSG_NODEINFO_PKT*)data; struct TOPOMSG_NODEINFO_PKT* pkt = (struct TOPOMSG_NODEINFO_PKT*)data;
struct TOPOMSG_NODE* ni = &pkt->node; struct TOPOMSG_NODE* ni = &pkt->node;
@ -425,9 +490,9 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
uint64_t node_id = ni->node_id; uint64_t node_id = ni->node_id;
if (ni->hop_count >= MAX_HOPS) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "NODEINFO from %s dropped: too many hops (%d)", from->log_name, ni->hop_count); return -1; } if (ni->hop_count >= MAX_HOPS) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "NODEINFO from %s dropped: too many hops (%d)", from->log_name, ni->hop_count); return -1; }
if (node_id == bgp->instance->node_id) return 0; if (node_id == group->instance->node_id) return 0;
struct TOPO_NODEQ* nodeinfo1 = topo_node_find_by_id(bgp, node_id); struct TOPO_NODEQ* nodeinfo1 = topo_node_find_by_id(group, node_id);
uint8_t new_ver = ni->ver; uint8_t new_ver = ni->ver;
if (nodeinfo1 && (int8_t)(nodeinfo1->last_ver - new_ver) >= 0) { if (nodeinfo1 && (int8_t)(nodeinfo1->last_ver - new_ver) >= 0) {
@ -437,8 +502,8 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
const uint8_t* hop_src = (const uint8_t*)ni + sizeof(struct TOPOMSG_NODE) + dyn - ni->hop_count * 8; const uint8_t* hop_src = (const uint8_t*)ni + sizeof(struct TOPOMSG_NODE) + dyn - ni->hop_count * 8;
memcpy(hop_list, hop_src, ni->hop_count * 8); memcpy(hop_list, hop_src, ni->hop_count * 8);
hop_list[ni->hop_count] = from->peer_node_id; hop_list[ni->hop_count] = from->peer_node_id;
topo_bgp_remove_path(nodeinfo1, from); topo_group_remove_path(nodeinfo1, from);
topo_bgp_add_path(nodeinfo1, from, hop_list, new_hops); topo_group_add_path(nodeinfo1, from, hop_list, new_hops);
} }
return 0; return 0;
} }
@ -450,20 +515,19 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
struct ll_queue* paths = NULL; struct ll_queue* paths = NULL;
int is_new_node = 0; int is_new_node = 0;
if (nodeinfo1) { if (nodeinfo1) {
topo_node_free_lists(bgp, nodeinfo1); topo_node_free_lists(group, nodeinfo1);
paths = nodeinfo1->paths; nodeinfo1->paths = NULL; paths = nodeinfo1->paths; nodeinfo1->paths = NULL;
} else { is_new_node = 1; } } else { is_new_node = 1; }
// deserialize from protocol
const uint8_t* ser_data = data + 2; const uint8_t* ser_data = data + 2;
size_t ser_len = len - 2; size_t ser_len = len - 2;
struct TOPO_NODE* new_ni = NULL; struct TOPO_NODE* new_ni = NULL;
struct TOPO_NODESUBNETS* new_subnets = NULL; struct TOPO_NODESUBNETS* new_subnets = NULL;
struct TOPOMSG_TRANZIT* new_tranzit = NULL; uint8_t new_tranzit_count = 0; struct TOPOMSG_TRANZIT* new_tranzit = NULL; uint8_t new_tranzit_count = 0;
uint64_t* new_hop_list = NULL; uint8_t new_hop_count = 0; uint64_t* new_hop_list = NULL; uint8_t new_hop_count = 0;
if (topo_node_deserialize(bgp, ser_data, ser_len, &new_ni, &new_subnets, &new_tranzit, &new_tranzit_count, &new_hop_list, &new_hop_count) != 0) { if (topo_node_deserialize(group, ser_data, ser_len, &new_ni, &new_subnets, &new_tranzit, &new_tranzit_count, &new_hop_list, &new_hop_count) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "NODEINFO deserialize failed from %s", from->log_name); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "NODEINFO deserialize failed from %s", from->log_name);
if (nodeinfo1) { queue_remove_data(bgp->nodes, &nodeinfo1->ll); queue_free(paths); queue_entry_free(&nodeinfo1->ll); } if (nodeinfo1) { queue_remove_data(group->nodes, &nodeinfo1->ll); queue_free(paths); queue_entry_free(&nodeinfo1->ll); }
return -1; return -1;
} }
@ -491,12 +555,11 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
nodeinfo1->connectivity.real_status = PROBE_RESULT_UNKNOWN; nodeinfo1->connectivity.real_status = PROBE_RESULT_UNKNOWN;
nodeinfo1->connectivity.ping_req_time = 0; nodeinfo1->connectivity.ping_req_time = 0;
nodeinfo1->alien = 0; nodeinfo1->alien = 0;
queue_data_put_with_index(bgp->nodes, &nodeinfo1->ll); queue_data_put_with_index(group->nodes, &nodeinfo1->ll);
} }
nodeinfo1->paths = paths; nodeinfo1->last_ver = new_ver; nodeinfo1->paths = paths; nodeinfo1->last_ver = new_ver;
// add this hop
uint64_t hop_list[MAX_HOPS]; uint64_t hop_list[MAX_HOPS];
if (nodeinfo1->hop_count > 0) memcpy(hop_list, nodeinfo1->hop_list, nodeinfo1->hop_count * 8); if (nodeinfo1->hop_count > 0) memcpy(hop_list, nodeinfo1->hop_list, nodeinfo1->hop_count * 8);
hop_list[nodeinfo1->hop_count] = from->peer_node_id; hop_list[nodeinfo1->hop_count] = from->peer_node_id;
@ -506,22 +569,22 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
nodeinfo1->hop_list = u_malloc(nodeinfo1->hop_count * 8); nodeinfo1->hop_list = u_malloc(nodeinfo1->hop_count * 8);
memcpy(nodeinfo1->hop_list, hop_list, nodeinfo1->hop_count * 8); memcpy(nodeinfo1->hop_list, hop_list, nodeinfo1->hop_count * 8);
topo_bgp_remove_path_by_hop(nodeinfo1, from->peer_node_id); topo_group_remove_path_by_hop(nodeinfo1, from->peer_node_id);
topo_bgp_add_path(nodeinfo1, from, hop_list, nodeinfo1->hop_count); topo_group_add_path(nodeinfo1, from, hop_list, nodeinfo1->hop_count);
if (bgp->instance->rt) route_insert(bgp->instance->rt, nodeinfo1); if (group->instance->rt) route_insert(group->instance->rt, nodeinfo1);
if (node_id != bgp->instance->node_id) topo_node_lmdb_put(bgp, nodeinfo1); if (node_id != group->instance->node_id) topo_node_lmdb_put(group, nodeinfo1);
if (bgp->instance->control_srv) control_server_notify_node_change(bgp->instance->control_srv, nodeinfo1); if (group->instance->control_srv) control_server_notify_node_change(group->instance->control_srv, nodeinfo1);
int hop_count = nodeinfo1->hop_count; int hop_count = nodeinfo1->hop_count;
struct ll_entry* se = bgp->senders_list ? bgp->senders_list->head : NULL; struct ll_entry* se = group->senders_list ? group->senders_list->head : NULL;
while (se) { while (se) {
struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)se->data; struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)se->data;
if (item->conn) { if (item->conn) {
uint64_t id = item->conn->peer_node_id; uint64_t id = item->conn->peer_node_id;
if (id != node_id) { if (id != node_id) {
int found = 0; for (int i = 0; i < hop_count; i++) if (hop_list[i] == id) found = 1; int found = 0; for (int i = 0; i < hop_count; i++) if (hop_list[i] == id) found = 1;
if (found == 0) topo_bgp_send_nodeinfo(nodeinfo1, item->conn); if (found == 0) topo_group_send_nodeinfo(group, nodeinfo1, item->conn);
} }
} }
se = se->next; se = se->next;
@ -530,39 +593,39 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
int socks_changed = 1; int socks_changed = 1;
if (!is_new_node) socks_changed = 1; if (!is_new_node) socks_changed = 1;
if (node_id != bgp->instance->node_id && (is_new_node || socks_changed)) { if (node_id != group->instance->node_id && (is_new_node || socks_changed)) {
int v4a = topo_list_count((struct _topo_head*)nodeinfo1->node->v4_addrs); int v4a = topo_list_count((struct _topo_head*)nodeinfo1->node->v4_addrs);
int v6a = topo_list_count((struct _topo_head*)nodeinfo1->node->v6_addrs); int v6a = topo_list_count((struct _topo_head*)nodeinfo1->node->v6_addrs);
if (v4a > 0 || v6a > 0) route_connectivity_probe_node(bgp->instance, nodeinfo1); if (v4a > 0 || v6a > 0) route_connectivity_probe_node(group->instance, nodeinfo1);
} }
return 0; return 0;
} }
int topo_bgp_process_withdraw(struct TOPO_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len) { int topo_group_process_withdraw(struct TOPO_GROUP* group, struct ETCP_CONN* sender, const uint8_t* data, size_t len) {
if (!bgp || len < sizeof(struct TOPOMSG_WITHDRAW_PKT)) return -1; if (!group || len < sizeof(struct TOPOMSG_WITHDRAW_PKT)) return -1;
struct TOPOMSG_WITHDRAW_PKT* wp = (struct TOPOMSG_WITHDRAW_PKT*)data; struct TOPOMSG_WITHDRAW_PKT* wp = (struct TOPOMSG_WITHDRAW_PKT*)data;
uint64_t node_id = wp->node_id, wd_source = wp->wd_source; uint64_t node_id = wp->node_id, wd_source = wp->wd_source;
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(group, node_id);
if (!nq) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "node not found"); return 0; } if (!nq) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "node not found"); return 0; }
int ret = topo_bgp_remove_path_by_hop(nq, wd_source); int ret = topo_group_remove_path_by_hop(nq, wd_source);
if (ret == 1) { if (ret == 1) {
if (bgp->instance && bgp->instance->rt) route_delete(bgp->instance->rt, nq); if (group->instance && group->instance->rt) route_delete(group->instance->rt, nq);
if (bgp->instance->control_srv) control_server_notify_node_removed(bgp->instance->control_srv, node_id); if (group->instance->control_srv) control_server_notify_node_removed(group->instance->control_srv, node_id);
nq->dirty = 1; nq->dirty = 1;
route_connectivity_cancel_node(bgp->instance, nq); route_connectivity_cancel_node(group->instance, nq);
if (nq->paths) { queue_free(nq->paths); nq->paths = NULL; } if (nq->paths) { queue_free(nq->paths); nq->paths = NULL; }
topo_node_free_lists(bgp, nq); topo_node_free_lists(group, nq);
struct ll_entry* entry = queue_find_data_by_index(bgp->nodes, &node_id); struct ll_entry* entry = queue_find_data_by_index(group->nodes, &node_id);
if (entry) { queue_remove_data(bgp->nodes, entry); queue_entry_free(entry); } if (entry) { queue_remove_data(group->nodes, entry); queue_entry_free(entry); }
topo_bgp_broadcast_withdraw(bgp, node_id, wd_source, sender); topo_group_broadcast_withdraw(group, node_id, wd_source, sender);
} }
return 0; return 0;
} }
void topo_bgp_send_nodeinfo(struct TOPO_NODEQ* node, struct ETCP_CONN* conn) { void topo_group_send_nodeinfo(struct TOPO_GROUP* group, struct TOPO_NODEQ* node, struct ETCP_CONN* conn) {
if (!node || !conn) return; if (!group || !node || !conn) return;
size_t max_sz = sizeof(struct TOPOMSG_NODEINFO_PKT) + 4096; size_t max_sz = sizeof(struct TOPOMSG_NODEINFO_PKT) + 4096;
uint8_t* p = u_malloc(max_sz); uint8_t* p = u_malloc(max_sz);
@ -570,7 +633,7 @@ void topo_bgp_send_nodeinfo(struct TOPO_NODEQ* node, struct ETCP_CONN* conn) {
p[0] = ETCP_ID_TOPO_ENTRY; p[1] = TOPO_SUBCMD_NODEINFO; p[0] = ETCP_ID_TOPO_ENTRY; p[1] = TOPO_SUBCMD_NODEINFO;
int ser_len = topo_node_serialize(conn->instance->bgp, node, p + 2, max_sz - 2); int ser_len = topo_node_serialize(group, node, p + 2, max_sz - 2);
if (ser_len < 0) { u_free(p); return; } if (ser_len < 0) { u_free(p); return; }
struct ll_entry* e = queue_entry_new(0); struct ll_entry* e = queue_entry_new(0);
@ -580,18 +643,18 @@ void topo_bgp_send_nodeinfo(struct TOPO_NODEQ* node, struct ETCP_CONN* conn) {
if (etcp_send(conn, e) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NODEINFO failed"); u_free(p); queue_entry_free(e); } if (etcp_send(conn, e) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NODEINFO failed"); u_free(p); queue_entry_free(e); }
} }
static void topo_bgp_add_to_senders(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) { static void topo_group_add_to_senders(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!bgp || !conn || !bgp->senders_list) return; if (!group || !conn || !group->senders_list) return;
bool already = false; bool already = false;
struct ll_entry* e = bgp->senders_list->head; struct ll_entry* e = group->senders_list->head;
while (e) { if (((struct TOPO_BGP_CONN_ITEM*)e->data)->conn == conn) { already = true; break; } e = e->next; } while (e) { if (((struct TOPO_GROUP_CONN_ITEM*)e->data)->conn == conn) { already = true; break; } e = e->next; }
if (!already) { if (!already) {
struct ll_entry* item_entry = queue_entry_new(sizeof(struct TOPO_BGP_CONN_ITEM)); struct ll_entry* item_entry = queue_entry_new(sizeof(struct TOPO_GROUP_CONN_ITEM));
if (item_entry) { ((struct TOPO_BGP_CONN_ITEM*)item_entry->data)->conn = conn; queue_data_put(bgp->senders_list, item_entry); } if (item_entry) { ((struct TOPO_GROUP_CONN_ITEM*)item_entry->data)->conn = conn; queue_data_put(group->senders_list, item_entry); }
} }
} }
static bool topo_bgp_should_send_to(const struct TOPO_NODEQ* nq, uint64_t target_id) { static bool topo_group_should_send_to(const struct TOPO_NODEQ* nq, uint64_t target_id) {
if (!nq || !nq->node || !nq->paths) return false; if (!nq || !nq->node || !nq->paths) return false;
if (target_id == nq->node->node_id) return false; if (target_id == nq->node->node_id) return false;
struct ll_entry* e = nq->paths->head; struct ll_entry* e = nq->paths->head;
@ -605,29 +668,29 @@ static bool topo_bgp_should_send_to(const struct TOPO_NODEQ* nq, uint64_t target
return false; return false;
} }
static void topo_bgp_send_full_table(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) { static void topo_group_send_full_table(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!bgp || !conn) return; if (!group || !conn) return;
uint64_t target = conn->peer_node_id; uint64_t target = conn->peer_node_id;
struct ll_entry* e = bgp->nodes ? bgp->nodes->head : NULL; struct ll_entry* e = group->nodes ? group->nodes->head : NULL;
while (e) { while (e) {
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e; struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
if (nq->hop_count == 0) { e = e->next; continue; } if (nq->hop_count == 0) { e = e->next; continue; }
if (!nq->paths) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "node has no paths"); e = e->next; continue; } if (!nq->paths) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "node has no paths"); e = e->next; continue; }
if (topo_bgp_should_send_to(nq, target)) topo_bgp_send_nodeinfo(nq, conn); if (topo_group_should_send_to(nq, target)) topo_group_send_nodeinfo(group, nq, conn);
e = e->next; e = e->next;
} }
} }
static void topo_bgp_handle_request_table(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) { static void topo_group_handle_request_table(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
if (!bgp || !conn) return; if (!group || !conn) return;
topo_bgp_send_nodeinfo(bgp->local_node, conn); topo_group_send_nodeinfo(group, group->local_node, conn);
topo_bgp_send_full_table(bgp, conn); topo_group_send_full_table(group, conn);
topo_bgp_add_to_senders(bgp, conn); topo_group_add_to_senders(group, conn);
topo_bgp_send_table_complete(bgp, conn); topo_group_send_table_complete(group, conn);
} }
static void topo_bgp_handle_nat_info(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) { static void topo_group_handle_nat_info(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
if (!bgp || !from_conn || !data || len < sizeof(struct TOPOMSG_NAT_INFO) || !bgp->local_node || !bgp->local_node->node) return; if (!group || !from_conn || !data || len < sizeof(struct TOPOMSG_NAT_INFO) || !group->local_node || !group->local_node->node) return;
const struct TOPOMSG_NAT_INFO* info = (const struct TOPOMSG_NAT_INFO*)data; const struct TOPOMSG_NAT_INFO* info = (const struct TOPOMSG_NAT_INFO*)data;
uint32_t nat_ip = (info->nat_ip[0] << 24) | (info->nat_ip[1] << 16) | (info->nat_ip[2] << 8) | info->nat_ip[3]; uint32_t nat_ip = (info->nat_ip[0] << 24) | (info->nat_ip[1] << 16) | (info->nat_ip[2] << 8) | info->nat_ip[3];
@ -640,43 +703,43 @@ static void topo_bgp_handle_nat_info(struct TOPO_BGP* bgp, struct ETCP_CONN* fro
else verified_type = NAT_VERIFIED_UNKNOWN; else verified_type = NAT_VERIFIED_UNKNOWN;
int data_changed = 0; int data_changed = 0;
{ struct TOPO_SOCKMETA4* sm = bgp->local_node->node->v4_sock_meta; while (sm) { if (sm->id == socket_id) { if (sm->nat_type != verified_type) { sm->nat_type = verified_type; data_changed = 1; } break; } sm = sm->next; } } { struct TOPO_SOCKMETA4* sm = group->local_node->node->v4_sock_meta; while (sm) { if (sm->id == socket_id) { if (sm->nat_type != verified_type) { sm->nat_type = verified_type; data_changed = 1; } break; } sm = sm->next; } }
struct ETCP_SOCKET* es = bgp->instance->etcp_sockets; struct ETCP_SOCKET* es = group->instance->etcp_sockets;
while (es) { if (es->sock_id == socket_id) { while (es) { if (es->sock_id == socket_id) {
if (verified_type == NAT_VERIFIED_STRICT) { struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; nat_sin->sin_family = AF_INET; nat_sin->sin_addr.s_addr = nat_ip; nat_sin->sin_port = htons(nat_port); es->nat_type = verified_type; } if (verified_type == NAT_VERIFIED_STRICT) { struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; nat_sin->sin_family = AF_INET; nat_sin->sin_addr.s_addr = nat_ip; nat_sin->sin_port = htons(nat_port); es->nat_type = verified_type; }
else { struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; uint32_t old_nat_ip = nat_sin->sin_addr.s_addr; uint16_t old_nat_port = ntohs(nat_sin->sin_port); nat_sin->sin_family = AF_INET; nat_sin->sin_addr.s_addr = nat_ip; nat_sin->sin_port = htons(nat_port); if (old_nat_ip != nat_ip || old_nat_port != nat_port) data_changed = 1; es->nat_type = verified_type; } break; } else { struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; uint32_t old_nat_ip = nat_sin->sin_addr.s_addr; uint16_t old_nat_port = ntohs(nat_sin->sin_port); nat_sin->sin_family = AF_INET; nat_sin->sin_addr.s_addr = nat_ip; nat_sin->sin_port = htons(nat_port); if (old_nat_ip != nat_ip || old_nat_port != nat_port) data_changed = 1; es->nat_type = verified_type; } break; }
es = es->next; } es = es->next; }
if (data_changed) { if (data_changed) {
int prev_v4a = topo_list_count((struct _topo_head*)bgp->local_node->node->v4_addrs); int prev_v4a = topo_list_count((struct _topo_head*)group->local_node->node->v4_addrs);
topo_bgp_update_my_nodeinfo(bgp->instance, bgp); topo_group_update_my_nodeinfo(group->instance, group);
if (topo_list_count((struct _topo_head*)bgp->local_node->node->v4_addrs) != prev_v4a) { if (topo_list_count((struct _topo_head*)group->local_node->node->v4_addrs) != prev_v4a) {
bgp->local_node->dirty = 1; group->local_node->dirty = 1;
bgp->local_node->node->ver = (bgp->local_node->node->ver % 255) + 1; group->local_node->node->ver = (group->local_node->node->ver % 255) + 1;
bgp->local_node->last_ver = bgp->local_node->node->ver; group->local_node->last_ver = group->local_node->node->ver;
} }
if (bgp->local_node->dirty && bgp->senders_list) { if (group->local_node->dirty && group->senders_list) {
struct ll_entry* se = bgp->senders_list->head; struct ll_entry* se = group->senders_list->head;
while (se) { struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)se->data; if (item && item->conn) topo_bgp_send_nodeinfo(bgp->local_node, item->conn); se = se->next; } while (se) { struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)se->data; if (item && item->conn) topo_group_send_nodeinfo(group, group->local_node, item->conn); se = se->next; }
} }
} }
struct ETCP_LINK* l = from_conn->links; while (l) { l->nat_type = info->nat_type; l = l->next; } struct ETCP_LINK* l = from_conn->links; while (l) { l->nat_type = info->nat_type; l = l->next; }
} }
static void topo_bgp_handle_nat_check_req(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) { static void topo_group_handle_nat_check_req(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
if (!bgp || !from_conn || !data || len < sizeof(struct TOPOMSG_NAT_CHECK_REQ)) return; if (!group || !from_conn || !data || len < sizeof(struct TOPOMSG_NAT_CHECK_REQ)) return;
const struct TOPOMSG_NAT_CHECK_REQ* req = (const struct TOPOMSG_NAT_CHECK_REQ*)data; const struct TOPOMSG_NAT_CHECK_REQ* req = (const struct TOPOMSG_NAT_CHECK_REQ*)data;
uint8_t socket_id = req->socket_id; uint8_t socket_id = req->socket_id;
struct ETCP_LINK* target_link = NULL; struct ETCP_LINK* target_link = NULL;
struct ETCP_LINK* l = from_conn->links; while (l) { if (l->remote_socket_id == socket_id) { target_link = l; break; } l = l->next; } struct ETCP_LINK* l = from_conn->links; while (l) { if (l->remote_socket_id == socket_id) { target_link = l; break; } l = l->next; }
if (!target_link) return; if (!target_link) return;
if (target_link->nat_check_status == NAT_CHECK_IN_PROGRESS) return; if (target_link->nat_check_status == NAT_CHECK_IN_PROGRESS) return;
topo_bgp_start_link_nat_check(bgp, target_link); topo_group_start_link_nat_check(group, target_link);
} }
void topo_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type) { void topo_group_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type) {
if (!conn) return; if (!conn) return;
struct TOPOMSG_NAT_INFO* pkt = u_calloc(1, sizeof(struct TOPOMSG_NAT_INFO)); if (!pkt) return; struct TOPOMSG_NAT_INFO* pkt = u_calloc(1, sizeof(struct TOPOMSG_NAT_INFO)); if (!pkt) return;
pkt->cmd = ETCP_ID_TOPO_ENTRY; pkt->subcmd = TOPO_SUBCMD_NAT_INFO; pkt->cmd = ETCP_ID_TOPO_ENTRY; pkt->subcmd = TOPO_SUBCMD_NAT_INFO;
@ -689,7 +752,7 @@ void topo_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t
if (etcp_send(conn, e) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NAT_INFO failed"); u_free(pkt); queue_entry_free(e); } if (etcp_send(conn, e) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NAT_INFO failed"); u_free(pkt); queue_entry_free(e); }
} }
void topo_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id) { void topo_group_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id) {
if (!conn) return; if (!conn) return;
struct TOPOMSG_NAT_CHECK_REQ* pkt = u_calloc(1, sizeof(struct TOPOMSG_NAT_CHECK_REQ)); if (!pkt) return; struct TOPOMSG_NAT_CHECK_REQ* pkt = u_calloc(1, sizeof(struct TOPOMSG_NAT_CHECK_REQ)); if (!pkt) return;
pkt->cmd = ETCP_ID_TOPO_ENTRY; pkt->subcmd = TOPO_SUBCMD_NAT_CHECK_REQ; pkt->socket_id = socket_id; pkt->cmd = ETCP_ID_TOPO_ENTRY; pkt->subcmd = TOPO_SUBCMD_NAT_CHECK_REQ; pkt->socket_id = socket_id;
@ -699,8 +762,14 @@ void topo_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id) {
if (etcp_send(conn, e) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NAT_CHECK_REQ failed"); u_free(pkt); queue_entry_free(e); } if (etcp_send(conn, e) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NAT_CHECK_REQ failed"); u_free(pkt); queue_entry_free(e); }
} }
void topo_bgp_request_nat_check_all(struct TOPO_BGP* bgp) { void topo_group_request_nat_check_all(struct TOPO_GROUP* group) {
if (!bgp || !bgp->instance) return; if (!group || !group->instance) return;
int count = 0; int count = 0;
struct ETCP_CONN* conn = bgp->instance->connections; while (conn) { struct ETCP_LINK* link = conn->links; while (link) { if (link->nat_check_status < NAT_CHECK_IN_PROGRESS) topo_bgp_start_link_nat_check(bgp, link); count++; link = link->next; } conn = conn->next; } struct ETCP_CONN* conn = group->instance->connections; while (conn) { struct ETCP_LINK* link = conn->links; while (link) { if (link->nat_check_status < NAT_CHECK_IN_PROGRESS) topo_group_start_link_nat_check(group, link); count++; link = link->next; } conn = conn->next; }
}
void topo_group_send_withdraw(struct TOPO_GROUP* group, uint64_t node_id) {
if (!group) return;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_group_send_withdraw: node=%016llx", (unsigned long long)node_id);
topo_group_broadcast_withdraw(group, node_id, group->instance->node_id, NULL);
} }

75
src/topo_bgp.h → src/topo_group.h

@ -1,5 +1,5 @@
#ifndef TOPO_BGP_H #ifndef TOPO_GROUP_H
#define TOPO_BGP_H #define TOPO_GROUP_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -57,7 +57,7 @@ struct TOPOMSG_TABLE_REQ {
uint8_t subcmd; uint8_t subcmd;
} __attribute__((packed)); } __attribute__((packed));
struct TOPO_BGP_CONN_ITEM { struct TOPO_GROUP_CONN_ITEM {
struct ll_entry ll; struct ll_entry ll;
struct ETCP_CONN* conn; struct ETCP_CONN* conn;
}; };
@ -88,7 +88,11 @@ struct TOPOMSG_NAT_CHECK_REQ {
struct route_ping_pending; struct route_ping_pending;
struct ETCP_LINK; struct ETCP_LINK;
struct TOPO_BGP { /**
* @brief Группа топологии (одна на каждый group_id: utun, чат-группа, …)
*/
struct TOPO_GROUP {
uint64_t group_id; // уникальный идентификатор группы
struct UTUN_INSTANCE* instance; struct UTUN_INSTANCE* instance;
struct ll_queue* senders_list; struct ll_queue* senders_list;
struct ll_queue* nodes; struct ll_queue* nodes;
@ -99,6 +103,14 @@ struct TOPO_BGP {
uint8_t ed25519_public_key[SC_PUBKEY_SIZE]; uint8_t ed25519_public_key[SC_PUBKEY_SIZE];
MDB_env* nodeinfo_env; MDB_env* nodeinfo_env;
MDB_dbi nodeinfo_dbi; MDB_dbi nodeinfo_dbi;
};
/**
* @brief Контейнер всех групп топологии экземпляра
*/
struct TOPO_GROUPS {
struct UTUN_INSTANCE* instance;
struct ll_queue* group_list; // ll_queue of TOPO_GROUP entries
struct memory_pool* v4_sock_meta_pool; struct memory_pool* v4_sock_meta_pool;
struct memory_pool* v4_addr_pool; struct memory_pool* v4_addr_pool;
struct memory_pool* v6_sock_meta_pool; struct memory_pool* v6_sock_meta_pool;
@ -108,36 +120,43 @@ struct TOPO_BGP {
}; };
/** /**
* @brief Инициализирует модуль топологии BGP. * @brief Создаёт контейнер групп и группу utun по умолчанию (group_id=1).
*
* Создает очереди, local_node из подсетей конфига, привязывает к ETCP_ID_TOPO_ENTRY,
* устанавливает коллбеки new_conn для on_up/on_down.
* *
* @param instance экземпляр utun с node_id и конфигом * @param instance экземпляр utun с node_id и конфигом
* @return TOPO_BGP или NULL при ошибке * @return TOPO_GROUPS или NULL при ошибке
*/ */
struct TOPO_BGP* topo_bgp_init(struct UTUN_INSTANCE* instance); struct TOPO_GROUPS* topo_groups_init(struct UTUN_INSTANCE* instance);
/** /**
* @brief Освобождает ресурсы BGP (очереди, local_node, снимает привязку ETCP). * @brief Освобождает все группы и контейнер.
* *
* @param instance экземпляр utun * @param instance экземпляр utun
*/ */
void topo_bgp_destroy(struct UTUN_INSTANCE* instance); void topo_groups_destroy(struct UTUN_INSTANCE* instance);
/**
* @brief Возвращает группу по умолчанию (group_id=TOPO_GROUP_UTUN=0x8000000000000000).
*/
struct TOPO_GROUP* topo_groups_get_default(struct TOPO_GROUPS* g);
/**
* @brief Находит группу по id.
*/
struct TOPO_GROUP* topo_groups_find(struct TOPO_GROUPS* g, uint64_t group_id);
/** /**
* @brief Добавляет conn в senders_list (если нет), отправляет запрос таблицы (nodeinfo). * @brief Добавляет conn в senders_list (если нет), отправляет запрос таблицы (nodeinfo).
* *
* Вызывается при ETCP on_up. * Вызывается при ETCP on_up.
*/ */
void topo_bgp_new_conn(struct ETCP_CONN* conn); void topo_group_new_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn);
/** /**
* @brief Удаляет conn из senders_list, очищает paths во всех nodes, отправляет withdraw если node unreachable. * @brief Удаляет conn из senders_list, очищает paths во всех nodes, отправляет withdraw если node unreachable.
* *
* Вызывается при ETCP on_down. * Вызывается при ETCP on_down.
*/ */
void topo_bgp_remove_conn(struct ETCP_CONN* conn); void topo_group_remove_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn);
/** /**
* @brief Обрабатывает пакет NODEINFO. * @brief Обрабатывает пакет NODEINFO.
@ -147,8 +166,8 @@ void topo_bgp_remove_conn(struct ETCP_CONN* conn);
* *
* @return 0 при успехе * @return 0 при успехе
*/ */
int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from, const uint8_t* data, size_t len);
int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, const uint8_t* data, size_t len);
/** /**
* @brief Обрабатывает WITHDRAW. * @brief Обрабатывает WITHDRAW.
* *
@ -156,42 +175,42 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
* *
* @return 0 при успехе * @return 0 при успехе
*/ */
int topo_bgp_process_withdraw(struct TOPO_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len); int topo_group_process_withdraw(struct TOPO_GROUP* group, struct ETCP_CONN* sender, const uint8_t* data, size_t len);
/** /**
* @brief Отправляет NODEINFO пакет одному conn (всегда local_node). * @brief Отправляет NODEINFO пакет одному conn (всегда local_node).
*/ */
void topo_bgp_send_nodeinfo(struct TOPO_NODEQ* node, struct ETCP_CONN* conn); void topo_group_send_nodeinfo(struct TOPO_GROUP* group, struct TOPO_NODEQ* node, struct ETCP_CONN* conn);
/** /**
* @brief Отправляет WITHDRAW для node_id (вызывает broadcast_withdraw). * @brief Отправляет WITHDRAW для node_id (вызывает broadcast_withdraw).
*/ */
void topo_bgp_send_withdraw(struct TOPO_BGP* bgp, uint64_t node_id); void topo_group_send_withdraw(struct TOPO_GROUP* group, uint64_t node_id);
/** /**
* @brief Поиск оптимального ETCP соединения для указанного node_id. * @brief Поиск оптимального ETCP соединения для указанного node_id.
* *
* Перебирает paths узла, выбирает путь с минимальным hop_count. * Перебирает paths узла, выбирает путь с минимальным hop_count.
* *
* @param bgp указатель на TOPO_BGP * @param group указатель на TOPO_GROUP
* @param node_id целевой узел * @param node_id целевой узел
* @return оптимальный ETCP_CONN* или NULL * @return оптимальный ETCP_CONN* или NULL
*/ */
struct ETCP_CONN* topo_bgp_find_conn_for_node(struct TOPO_BGP* bgp, uint64_t node_id); struct ETCP_CONN* topo_group_find_conn_for_node(struct TOPO_GROUP* group, uint64_t node_id);
/** /**
* @brief Добавляет путь (conn) в paths узла. * @brief Добавляет путь (conn) в paths узла.
* *
* @return 0 при успехе * @return 0 при успехе
*/ */
int topo_bgp_add_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count); int topo_group_add_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count);
/** /**
* @brief Удаляет conn из paths узла. * @brief Удаляет conn из paths узла.
* *
* @return 1 если путей не осталось (unreachable) * @return 1 если путей не осталось (unreachable)
*/ */
int topo_bgp_remove_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn); int topo_group_remove_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn);
/** /**
* @brief Отправляет NAT_INFO клиенту с его типом NAT. * @brief Отправляет NAT_INFO клиенту с его типом NAT.
@ -201,7 +220,7 @@ int topo_bgp_remove_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn);
* @param nat_port порт клиента (network byte order) * @param nat_port порт клиента (network byte order)
* @param nat_type NAT_TYPE_EIM или NAT_TYPE_STRICT * @param nat_type NAT_TYPE_EIM или NAT_TYPE_STRICT
*/ */
void topo_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type); void topo_group_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type);
/** /**
* @brief Отправляет запрос на проверку NAT для указанного socket_id серверу. * @brief Отправляет запрос на проверку NAT для указанного socket_id серверу.
@ -209,23 +228,23 @@ void topo_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t
* @param conn соединение к серверу * @param conn соединение к серверу
* @param socket_id ID сокета для проверки * @param socket_id ID сокета для проверки
*/ */
void topo_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id); void topo_group_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id);
/** /**
* @brief Разрешить/запретить NAT check для локальных подсетей (127.0.0.1, 10.x.x.x и т.д.) * @brief Разрешить/запретить NAT check для локальных подсетей (127.0.0.1, 10.x.x.x и т.д.)
* По умолчанию запрещено. Полезно для тестов. * По умолчанию запрещено. Полезно для тестов.
*/ */
void topo_bgp_set_nat_check_local(struct TOPO_BGP* bgp, int allow); void topo_group_set_nat_check_local(struct TOPO_GROUP* group, int allow);
/** /**
* @brief Запускает NAT check для всех линков всех соединений. * @brief Запускает NAT check для всех линков всех соединений.
*/ */
void topo_bgp_request_nat_check_all(struct TOPO_BGP* bgp); void topo_group_request_nat_check_all(struct TOPO_GROUP* group);
/** /**
* @brief Запускает NAT check для одного линка. * @brief Запускает NAT check для одного линка.
*/ */
void topo_bgp_start_link_nat_check(struct TOPO_BGP* bgp, struct ETCP_LINK* link); void topo_group_start_link_nat_check(struct TOPO_GROUP* group, struct ETCP_LINK* link);
/* Аргумент callback NAT check */ /* Аргумент callback NAT check */
struct nat_check_arg { struct nat_check_arg {
@ -238,4 +257,4 @@ struct nat_check_arg {
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif // TOPO_BGP_H #endif // TOPO_GROUP_H

124
src/topo_node.c

@ -10,7 +10,7 @@
#include "etcp.h" #include "etcp.h"
#include "config_parser.h" #include "config_parser.h"
#include "topo_node.h" #include "topo_node.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "route_lib.h" #include "route_lib.h"
#include "etcp_debug.h" #include "etcp_debug.h"
@ -46,21 +46,21 @@ static void free_v6_sub_list(struct memory_pool* pool, struct TOPO_SUBNET6* head
while (head) { struct TOPO_SUBNET6* next = head->next; memory_pool_free(pool, head); head = next; } while (head) { struct TOPO_SUBNET6* next = head->next; memory_pool_free(pool, head); head = next; }
} }
void topo_node_free_lists(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq) { void topo_node_free_lists(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq) {
if (!bgp || !nq) return; if (!group || !nq) return;
if (nq->node) { if (nq->node) {
free_v4_sock_list(bgp->v4_sock_meta_pool, nq->node->v4_sock_meta); free_v4_sock_list(group->instance->topo_groups->v4_sock_meta_pool, nq->node->v4_sock_meta);
free_v4_addr_list(bgp->v4_addr_pool, nq->node->v4_addrs); free_v4_addr_list(group->instance->topo_groups->v4_addr_pool, nq->node->v4_addrs);
free_v6_sock_list(bgp->v6_sock_meta_pool, nq->node->v6_sock_meta); free_v6_sock_list(group->instance->topo_groups->v6_sock_meta_pool, nq->node->v6_sock_meta);
free_v6_addr_list(bgp->v6_addr_pool, nq->node->v6_addrs); free_v6_addr_list(group->instance->topo_groups->v6_addr_pool, nq->node->v6_addrs);
nq->node->v4_sock_meta = NULL; nq->node->v4_addrs = NULL; nq->node->v4_sock_meta = NULL; nq->node->v4_addrs = NULL;
nq->node->v6_sock_meta = NULL; nq->node->v6_addrs = NULL; nq->node->v6_sock_meta = NULL; nq->node->v6_addrs = NULL;
topo_node_unref(nq->node); topo_node_unref(nq->node);
nq->node = NULL; nq->node = NULL;
} }
if (nq->subnets) { if (nq->subnets) {
free_v4_sub_list(bgp->v4_subnet_pool, nq->subnets->v4_subnets); free_v4_sub_list(group->instance->topo_groups->v4_subnet_pool, nq->subnets->v4_subnets);
free_v6_sub_list(bgp->v6_subnet_pool, nq->subnets->v6_subnets); free_v6_sub_list(group->instance->topo_groups->v6_subnet_pool, nq->subnets->v6_subnets);
u_free(nq->subnets); u_free(nq->subnets);
nq->subnets = NULL; nq->subnets = NULL;
} }
@ -83,8 +83,8 @@ int topo_node_dyn_size(const struct TOPOMSG_NODE* msg) {
+ msg->hop_count * 8; + msg->hop_count * 8;
} }
int topo_node_serialize(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq, uint8_t* out, size_t out_max) { int topo_node_serialize(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq, uint8_t* out, size_t out_max) {
if (!bgp || !nq || !nq->node || !out) return -1; if (!group || !nq || !nq->node || !out) return -1;
struct TOPO_NODE* ni = nq->node; struct TOPO_NODE* ni = nq->node;
struct TOPOMSG_NODE msg; struct TOPOMSG_NODE msg;
@ -154,10 +154,10 @@ int topo_node_serialize(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq, uint8_t* ou
// ===== deserialization ===== // ===== deserialization =====
int topo_node_deserialize(struct TOPO_BGP* bgp, const uint8_t* data, size_t len, struct TOPO_NODE** out_ni, struct TOPO_NODESUBNETS** out_subnets, int topo_node_deserialize(struct TOPO_GROUP* group, const uint8_t* data, size_t len, struct TOPO_NODE** out_ni, struct TOPO_NODESUBNETS** out_subnets,
struct TOPOMSG_TRANZIT** out_tranzit, uint8_t* out_tranzit_count, struct TOPOMSG_TRANZIT** out_tranzit, uint8_t* out_tranzit_count,
uint64_t** out_hop_list, uint8_t* out_hop_count) { uint64_t** out_hop_list, uint8_t* out_hop_count) {
if (!bgp || !data || len < TOPOMSG_NODE_HDR_SIZE || !out_ni) return -1; if (!group || !data || len < TOPOMSG_NODE_HDR_SIZE || !out_ni) return -1;
const struct TOPOMSG_NODE* msg = (const struct TOPOMSG_NODE*)data; const struct TOPOMSG_NODE* msg = (const struct TOPOMSG_NODE*)data;
int dyn = topo_node_dyn_size(msg); int dyn = topo_node_dyn_size(msg);
@ -183,28 +183,28 @@ int topo_node_deserialize(struct TOPO_BGP* bgp, const uint8_t* data, size_t len,
for (int i = 0; i < msg->local_v4_sockets; i++) { for (int i = 0; i < msg->local_v4_sockets; i++) {
const struct TOPOMSG_SOCKMETA4* w = (const struct TOPOMSG_SOCKMETA4*)dp; dp += sizeof(*w); const struct TOPOMSG_SOCKMETA4* w = (const struct TOPOMSG_SOCKMETA4*)dp; dp += sizeof(*w);
struct TOPO_SOCKMETA4* e = memory_pool_alloc(bgp->v4_sock_meta_pool); struct TOPO_SOCKMETA4* e = memory_pool_alloc(group->instance->topo_groups->v4_sock_meta_pool);
if (!e) { topo_node_unref(ni); return -1; } if (!e) { topo_node_unref(ni); return -1; }
e->id = w->id; e->config_type = w->config_type; e->nat_type = w->nat_type; e->id = w->id; e->config_type = w->config_type; e->nat_type = w->nat_type;
e->next = ni->v4_sock_meta; ni->v4_sock_meta = e; e->next = ni->v4_sock_meta; ni->v4_sock_meta = e;
} }
for (int i = 0; i < msg->local_v4_addrs; i++) { for (int i = 0; i < msg->local_v4_addrs; i++) {
const struct TOPOMSG_ADDR4* w = (const struct TOPOMSG_ADDR4*)dp; dp += sizeof(*w); const struct TOPOMSG_ADDR4* w = (const struct TOPOMSG_ADDR4*)dp; dp += sizeof(*w);
struct TOPO_ADDR4* e = memory_pool_alloc(bgp->v4_addr_pool); struct TOPO_ADDR4* e = memory_pool_alloc(group->instance->topo_groups->v4_addr_pool);
if (!e) { topo_node_unref(ni); return -1; } if (!e) { topo_node_unref(ni); return -1; }
memcpy(e->addr, w->addr, 4); e->port = w->port; e->type = w->type; e->socket_id = w->socket_id; e->protocol = w->protocol; memcpy(e->addr, w->addr, 4); e->port = w->port; e->type = w->type; e->socket_id = w->socket_id; e->protocol = w->protocol;
e->next = ni->v4_addrs; ni->v4_addrs = e; e->next = ni->v4_addrs; ni->v4_addrs = e;
} }
for (int i = 0; i < msg->local_v6_sockets; i++) { for (int i = 0; i < msg->local_v6_sockets; i++) {
const struct TOPOMSG_SOCKMETA6* w = (const struct TOPOMSG_SOCKMETA6*)dp; dp += sizeof(*w); const struct TOPOMSG_SOCKMETA6* w = (const struct TOPOMSG_SOCKMETA6*)dp; dp += sizeof(*w);
struct TOPO_SOCKMETA6* e = memory_pool_alloc(bgp->v6_sock_meta_pool); struct TOPO_SOCKMETA6* e = memory_pool_alloc(group->instance->topo_groups->v6_sock_meta_pool);
if (!e) { topo_node_unref(ni); return -1; } if (!e) { topo_node_unref(ni); return -1; }
e->id = w->id; e->config_type = w->config_type; e->nat_type = w->nat_type; e->id = w->id; e->config_type = w->config_type; e->nat_type = w->nat_type;
e->next = ni->v6_sock_meta; ni->v6_sock_meta = e; e->next = ni->v6_sock_meta; ni->v6_sock_meta = e;
} }
for (int i = 0; i < msg->local_v6_addrs; i++) { for (int i = 0; i < msg->local_v6_addrs; i++) {
const struct TOPOMSG_ADDR6* w = (const struct TOPOMSG_ADDR6*)dp; dp += sizeof(*w); const struct TOPOMSG_ADDR6* w = (const struct TOPOMSG_ADDR6*)dp; dp += sizeof(*w);
struct TOPO_ADDR6* e = memory_pool_alloc(bgp->v6_addr_pool); struct TOPO_ADDR6* e = memory_pool_alloc(group->instance->topo_groups->v6_addr_pool);
if (!e) { topo_node_unref(ni); return -1; } if (!e) { topo_node_unref(ni); return -1; }
memcpy(e->addr, w->addr, 16); e->port = w->port; e->type = w->type; e->socket_id = w->socket_id; e->protocol = w->protocol; memcpy(e->addr, w->addr, 16); e->port = w->port; e->type = w->type; e->socket_id = w->socket_id; e->protocol = w->protocol;
e->next = ni->v6_addrs; ni->v6_addrs = e; e->next = ni->v6_addrs; ni->v6_addrs = e;
@ -215,14 +215,14 @@ int topo_node_deserialize(struct TOPO_BGP* bgp, const uint8_t* data, size_t len,
if (!r) { topo_node_unref(ni); return -1; } if (!r) { topo_node_unref(ni); return -1; }
for (int i = 0; i < msg->local_v4_subnets; i++) { for (int i = 0; i < msg->local_v4_subnets; i++) {
const struct TOPOMSG_SUBNET4* w = (const struct TOPOMSG_SUBNET4*)dp; dp += sizeof(*w); const struct TOPOMSG_SUBNET4* w = (const struct TOPOMSG_SUBNET4*)dp; dp += sizeof(*w);
struct TOPO_SUBNET4* e = memory_pool_alloc(bgp->v4_subnet_pool); struct TOPO_SUBNET4* e = memory_pool_alloc(group->instance->topo_groups->v4_subnet_pool);
if (!e) { u_free(r); topo_node_unref(ni); return -1; } if (!e) { u_free(r); topo_node_unref(ni); return -1; }
memcpy(e->addr, w->addr, 4); e->prefix_length = w->prefix_length; memcpy(e->addr, w->addr, 4); e->prefix_length = w->prefix_length;
e->next = r->v4_subnets; r->v4_subnets = e; e->next = r->v4_subnets; r->v4_subnets = e;
} }
for (int i = 0; i < msg->local_v6_subnets; i++) { for (int i = 0; i < msg->local_v6_subnets; i++) {
const struct TOPOMSG_SUBNET6* w = (const struct TOPOMSG_SUBNET6*)dp; dp += sizeof(*w); const struct TOPOMSG_SUBNET6* w = (const struct TOPOMSG_SUBNET6*)dp; dp += sizeof(*w);
struct TOPO_SUBNET6* e = memory_pool_alloc(bgp->v6_subnet_pool); struct TOPO_SUBNET6* e = memory_pool_alloc(group->instance->topo_groups->v6_subnet_pool);
if (!e) { u_free(r); topo_node_unref(ni); return -1; } if (!e) { u_free(r); topo_node_unref(ni); return -1; }
memcpy(e->addr, w->addr, 16); e->prefix_length = w->prefix_length; memcpy(e->addr, w->addr, 16); e->prefix_length = w->prefix_length;
e->next = r->v6_subnets; r->v6_subnets = e; e->next = r->v6_subnets; r->v6_subnets = e;
@ -255,10 +255,10 @@ int topo_node_deserialize(struct TOPO_BGP* bgp, const uint8_t* data, size_t len,
return 0; return 0;
} }
struct TOPO_NODEQ* topo_node_find_by_id(struct TOPO_BGP* bgp, uint64_t node_id) { struct TOPO_NODEQ* topo_node_find_by_id(struct TOPO_GROUP* group, uint64_t node_id) {
if (!bgp || !bgp->nodes) return NULL; if (!group || !group->nodes) return NULL;
uint64_t key = node_id; uint64_t key = node_id;
struct ll_entry* e = queue_find_data_by_index(bgp->nodes, &key); struct ll_entry* e = queue_find_data_by_index(group->nodes, &key);
return e ? (struct TOPO_NODEQ*)e : NULL; return e ? (struct TOPO_NODEQ*)e : NULL;
} }
@ -283,18 +283,18 @@ static const char* conn_mgr_type_str(uint8_t t) {
switch (t) { case 1: return "DIRECT"; case 2: return "REVERSE"; case 3: return "INDIRECT"; default: return "NONE"; } switch (t) { case 1: return "DIRECT"; case 2: return "REVERSE"; case 3: return "INDIRECT"; default: return "NONE"; }
} }
void topo_node_dump_all(struct TOPO_BGP* bgp) { void topo_node_dump_all(struct TOPO_GROUP* group) {
if (!bgp || !bgp->nodes) return; if (!group || !group->nodes) return;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "=== BGP Nodes dump: %d nodes ===", queue_entry_count(bgp->nodes)); DEBUG_INFO(DEBUG_CATEGORY_BGP, "=== BGP Nodes dump: %d nodes ===", queue_entry_count(group->nodes));
int idx = 0; int idx = 0;
struct ll_entry* e = bgp->nodes->head; struct ll_entry* e = group->nodes->head;
while (e) { while (e) {
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e; struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
struct TOPO_NODE* ni = nq->node; struct TOPO_NODE* ni = nq->node;
if (!ni) { e = e->next; continue; } if (!ni) { e = e->next; continue; }
int is_local = (bgp->local_node == nq); int is_local = (group->local_node == nq);
const char* name_s = ni->node_name ? ni->node_name : ""; const char* name_s = ni->node_name ? ni->node_name : "";
DEBUG_INFO(DEBUG_CATEGORY_BGP, "--- Node #%d: id=%016llx name=\"%s\" ver=%u dirty=%u alien=%u grp=%llu%s ---", DEBUG_INFO(DEBUG_CATEGORY_BGP, "--- Node #%d: id=%016llx name=\"%s\" ver=%u dirty=%u alien=%u grp=%llu%s ---",
@ -377,20 +377,20 @@ void topo_node_dump_all(struct TOPO_BGP* bgp) {
} }
} }
int topo_node_format_all(struct TOPO_BGP* bgp, char* buf, size_t buf_size) { int topo_node_format_all(struct TOPO_GROUP* group, char* buf, size_t buf_size) {
if (!bgp || !bgp->nodes || !buf || buf_size == 0) return 0; if (!group || !group->nodes || !buf || buf_size == 0) return 0;
int pos = 0; int pos = 0;
pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0,
"=== BGP Nodes dump: %d nodes ===\n", queue_entry_count(bgp->nodes)); "=== BGP Nodes dump: %d nodes ===\n", queue_entry_count(group->nodes));
int idx = 0; int idx = 0;
struct ll_entry* e = bgp->nodes->head; struct ll_entry* e = group->nodes->head;
while (e && (size_t)pos < buf_size) { while (e && (size_t)pos < buf_size) {
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e; struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
struct TOPO_NODE* ni = nq->node; struct TOPO_NODE* ni = nq->node;
if (!ni) { e = e->next; continue; } if (!ni) { e = e->next; continue; }
int is_local = (bgp->local_node == nq); int is_local = (group->local_node == nq);
const char* name_s = ni->node_name ? ni->node_name : ""; const char* name_s = ni->node_name ? ni->node_name : "";
#define FMT_ADD(fmt, ...) pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, fmt, ##__VA_ARGS__) #define FMT_ADD(fmt, ...) pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, fmt, ##__VA_ARGS__)
@ -474,8 +474,8 @@ int topo_node_format_all(struct TOPO_BGP* bgp, char* buf, size_t buf_size) {
// ===== update my nodeinfo ===== // ===== update my nodeinfo =====
int topo_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_BGP* bgp) { int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GROUP* group) {
if (!instance || !bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_update_my_nodeinfo: invalid args"); return -1; } if (!instance || !group) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_group_update_my_nodeinfo: invalid args"); return -1; }
size_t name_len = 0; size_t name_len = 0;
if (instance->name[0]) { name_len = strlen(instance->name); if (name_len > 63) name_len = 63; } if (instance->name[0]) { name_len = strlen(instance->name); if (name_len > 63) name_len = 63; }
int vc = 0, vc6 = 0; int vc = 0, vc6 = 0;
@ -501,42 +501,42 @@ int topo_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_BGP*
} }
int changed = 1; uint8_t old_ver = 0; int changed = 1; uint8_t old_ver = 0;
if (bgp->local_node && bgp->local_node->node) { if (group->local_node && group->local_node->node) {
struct TOPO_NODE* oni = bgp->local_node->node; struct TOPO_NODE* oni = group->local_node->node;
old_ver = oni->ver; old_ver = oni->ver;
changed = (vc != (bgp->local_node->subnets ? topo_list_count((struct _topo_head*)bgp->local_node->subnets->v4_subnets) : 0)) changed = (vc != (group->local_node->subnets ? topo_list_count((struct _topo_head*)group->local_node->subnets->v4_subnets) : 0))
|| (sock_count != topo_list_count((struct _topo_head*)oni->v4_sock_meta)) || (sock_count != topo_list_count((struct _topo_head*)oni->v4_sock_meta))
|| (addr_count != topo_list_count((struct _topo_head*)oni->v4_addrs)) || (addr_count != topo_list_count((struct _topo_head*)oni->v4_addrs))
|| (name_len != (oni->node_name ? strlen(oni->node_name) : 0)) || (name_len != (oni->node_name ? strlen(oni->node_name) : 0))
|| (memcmp(oni->public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE) != 0) || (memcmp(oni->public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE) != 0)
|| (vc6 != (bgp->local_node->subnets ? topo_list_count((struct _topo_head*)bgp->local_node->subnets->v6_subnets) : 0)) || (vc6 != (group->local_node->subnets ? topo_list_count((struct _topo_head*)group->local_node->subnets->v6_subnets) : 0))
|| (sock6_count != topo_list_count((struct _topo_head*)oni->v6_sock_meta)) || (sock6_count != topo_list_count((struct _topo_head*)oni->v6_sock_meta))
|| (addr6_count != topo_list_count((struct _topo_head*)oni->v6_addrs)); || (addr6_count != topo_list_count((struct _topo_head*)oni->v6_addrs));
if (bgp->local_node && bgp->instance && bgp->instance->bgp) if (group->local_node && group->instance && group->instance->topo_groups)
if (memcmp(oni->ed25519_public_key, bgp->instance->bgp->ed25519_public_key, SC_PUBKEY_SIZE) != 0) changed = 1; if (memcmp(oni->ed25519_public_key, group->ed25519_public_key, SC_PUBKEY_SIZE) != 0) changed = 1;
} }
if (changed) { if (changed) {
if (bgp->local_node) { if (group->local_node) {
if (instance->rt) route_delete(instance->rt, bgp->local_node); if (instance->rt) route_delete(instance->rt, group->local_node);
topo_node_free_lists(bgp, bgp->local_node); topo_node_free_lists(group, group->local_node);
u_free(bgp->local_node); u_free(group->local_node);
bgp->local_node = NULL; group->local_node = NULL;
} }
bgp->local_node = u_calloc(1, sizeof(struct TOPO_NODEQ)); group->local_node = u_calloc(1, sizeof(struct TOPO_NODEQ));
if (!bgp->local_node) return -1; if (!group->local_node) return -1;
struct TOPO_NODEQ* lq = bgp->local_node; struct TOPO_NODEQ* lq = group->local_node;
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE)); struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
if (!ni) { u_free(lq); bgp->local_node = NULL; return -1; } if (!ni) { u_free(lq); group->local_node = NULL; return -1; }
ni->ref_count = 1; ni->ref_count = 1;
ni->flags = TOPO_FLAG_SEND_SUBNETS; ni->flags = TOPO_FLAG_SEND_SUBNETS;
ni->group_id = TOPO_GROUP_UTUN; ni->group_id = TOPO_GROUP_UTUN;
ni->node_id = instance->node_id; ni->node_id = instance->node_id;
ni->ver = (old_ver % 255) + 1; ni->ver = (old_ver % 255) + 1;
memcpy(ni->public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE); memcpy(ni->public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE);
memcpy(ni->ed25519_public_key, bgp->ed25519_public_key, SC_PUBKEY_SIZE); memcpy(ni->ed25519_public_key, group->ed25519_public_key, SC_PUBKEY_SIZE);
if (name_len) { ni->node_name = u_malloc(name_len + 1); if (ni->node_name) { memcpy(ni->node_name, instance->name, name_len); ni->node_name[name_len] = 0; } } if (name_len) { ni->node_name = u_malloc(name_len + 1); if (ni->node_name) { memcpy(ni->node_name, instance->name, name_len); ni->node_name[name_len] = 0; } }
lq->node = ni; lq->node = ni;
@ -549,35 +549,35 @@ int topo_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_BGP*
while (e_sock) { while (e_sock) {
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; } if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; }
if (e_sock->local_addr.ss_family == AF_INET) { if (e_sock->local_addr.ss_family == AF_INET) {
{ struct TOPO_SOCKMETA4* sm = memory_pool_alloc(bgp->v4_sock_meta_pool); { struct TOPO_SOCKMETA4* sm = memory_pool_alloc(group->instance->topo_groups->v4_sock_meta_pool);
sm->id = e_sock->sock_id; sm->config_type = e_sock->type; sm->nat_type = e_sock->nat_type; sm->id = e_sock->sock_id; sm->config_type = e_sock->type; sm->nat_type = e_sock->nat_type;
sm->next = ni->v4_sock_meta; ni->v4_sock_meta = sm; } sm->next = ni->v4_sock_meta; ni->v4_sock_meta = sm; }
struct sockaddr_in* if_sin = (struct sockaddr_in*)&e_sock->interface_addr; struct sockaddr_in* if_sin = (struct sockaddr_in*)&e_sock->interface_addr;
struct sockaddr_in* nat_sin = (struct sockaddr_in*)&e_sock->nat_addr; struct sockaddr_in* nat_sin = (struct sockaddr_in*)&e_sock->nat_addr;
{ struct TOPO_ADDR4* a = memory_pool_alloc(bgp->v4_addr_pool); { struct TOPO_ADDR4* a = memory_pool_alloc(group->instance->topo_groups->v4_addr_pool);
memcpy(a->addr, &if_sin->sin_addr.s_addr, 4); a->port = ntohs(if_sin->sin_port); memcpy(a->addr, &if_sin->sin_addr.s_addr, 4); a->port = ntohs(if_sin->sin_port);
a->type = TOPO_ADDR_INTERFACE; a->socket_id = e_sock->sock_id; a->protocol = TOPO_PROTO_UDP; a->type = TOPO_ADDR_INTERFACE; a->socket_id = e_sock->sock_id; a->protocol = TOPO_PROTO_UDP;
a->next = ni->v4_addrs; ni->v4_addrs = a; } a->next = ni->v4_addrs; ni->v4_addrs = a; }
if (e_sock->nat_addr.ss_family == AF_INET && nat_sin->sin_addr.s_addr != 0 && e_sock->nat_type != NAT_VERIFIED_STRICT) { if (e_sock->nat_addr.ss_family == AF_INET && nat_sin->sin_addr.s_addr != 0 && e_sock->nat_type != NAT_VERIFIED_STRICT) {
struct TOPO_ADDR4* a = memory_pool_alloc(bgp->v4_addr_pool); struct TOPO_ADDR4* a = memory_pool_alloc(group->instance->topo_groups->v4_addr_pool);
memcpy(a->addr, &nat_sin->sin_addr.s_addr, 4); a->port = ntohs(nat_sin->sin_port); memcpy(a->addr, &nat_sin->sin_addr.s_addr, 4); a->port = ntohs(nat_sin->sin_port);
a->type = TOPO_ADDR_NAT; a->socket_id = e_sock->sock_id; a->protocol = TOPO_PROTO_UDP; a->type = TOPO_ADDR_NAT; a->socket_id = e_sock->sock_id; a->protocol = TOPO_PROTO_UDP;
a->next = ni->v4_addrs; ni->v4_addrs = a; a->next = ni->v4_addrs; ni->v4_addrs = a;
} }
if (e_sock->nat_type == NAT_VERIFIED_DIRECT || ((e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) && e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) { if (e_sock->nat_type == NAT_VERIFIED_DIRECT || ((e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) && e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) {
struct TOPO_ADDR4* a = memory_pool_alloc(bgp->v4_addr_pool); struct TOPO_ADDR4* a = memory_pool_alloc(group->instance->topo_groups->v4_addr_pool);
memcpy(a->addr, &if_sin->sin_addr.s_addr, 4); a->port = ntohs(if_sin->sin_port); memcpy(a->addr, &if_sin->sin_addr.s_addr, 4); a->port = ntohs(if_sin->sin_port);
a->type = TOPO_ADDR_REAL; a->socket_id = e_sock->sock_id; a->protocol = TOPO_PROTO_UDP; a->type = TOPO_ADDR_REAL; a->socket_id = e_sock->sock_id; a->protocol = TOPO_PROTO_UDP;
a->next = ni->v4_addrs; ni->v4_addrs = a; a->next = ni->v4_addrs; ni->v4_addrs = a;
} }
} else if (e_sock->local_addr.ss_family == AF_INET6) { } else if (e_sock->local_addr.ss_family == AF_INET6) {
{ struct TOPO_SOCKMETA6* sm6 = memory_pool_alloc(bgp->v6_sock_meta_pool); { struct TOPO_SOCKMETA6* sm6 = memory_pool_alloc(group->instance->topo_groups->v6_sock_meta_pool);
sm6->id = e_sock->sock_id; sm6->config_type = e_sock->type; sm6->nat_type = e_sock->nat_type; sm6->id = e_sock->sock_id; sm6->config_type = e_sock->type; sm6->nat_type = e_sock->nat_type;
sm6->next = ni->v6_sock_meta; ni->v6_sock_meta = sm6; } sm6->next = ni->v6_sock_meta; ni->v6_sock_meta = sm6; }
struct sockaddr_in6* if_sin6 = (struct sockaddr_in6*)&e_sock->interface_addr; struct sockaddr_in6* if_sin6 = (struct sockaddr_in6*)&e_sock->interface_addr;
{ struct TOPO_ADDR6* a6 = memory_pool_alloc(bgp->v6_addr_pool); { struct TOPO_ADDR6* a6 = memory_pool_alloc(group->instance->topo_groups->v6_addr_pool);
memcpy(a6->addr, &if_sin6->sin6_addr, 16); a6->port = ntohs(if_sin6->sin6_port); memcpy(a6->addr, &if_sin6->sin6_addr, 16); a6->port = ntohs(if_sin6->sin6_port);
a6->type = TOPO_ADDR_INTERFACE; a6->socket_id = e_sock->sock_id; a6->protocol = TOPO_PROTO_UDP; a6->type = TOPO_ADDR_INTERFACE; a6->socket_id = e_sock->sock_id; a6->protocol = TOPO_PROTO_UDP;
a6->next = ni->v6_addrs; ni->v6_addrs = a6; } a6->next = ni->v6_addrs; ni->v6_addrs = a6; }
@ -587,13 +587,13 @@ int topo_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_BGP*
{ struct CFG_SERVER* srv = instance->config->servers; { struct CFG_SERVER* srv = instance->config->servers;
while (srv) { if (srv->transport && srv->ip.ss_family == AF_INET) { while (srv) { if (srv->transport && srv->ip.ss_family == AF_INET) {
struct sockaddr_in* tcp_sin = (struct sockaddr_in*)&srv->ip; struct sockaddr_in* tcp_sin = (struct sockaddr_in*)&srv->ip;
struct TOPO_ADDR4* a = memory_pool_alloc(bgp->v4_addr_pool); struct TOPO_ADDR4* a = memory_pool_alloc(group->instance->topo_groups->v4_addr_pool);
memcpy(a->addr, &tcp_sin->sin_addr.s_addr, 4); a->port = ntohs(tcp_sin->sin_port); memcpy(a->addr, &tcp_sin->sin_addr.s_addr, 4); a->port = ntohs(tcp_sin->sin_port);
a->type = TOPO_ADDR_INTERFACE; a->socket_id = 0; a->protocol = TOPO_PROTO_TCP; a->type = TOPO_ADDR_INTERFACE; a->socket_id = 0; a->protocol = TOPO_PROTO_TCP;
a->next = ni->v4_addrs; ni->v4_addrs = a; a->next = ni->v4_addrs; ni->v4_addrs = a;
} else if (srv->transport && srv->ip.ss_family == AF_INET6) { } else if (srv->transport && srv->ip.ss_family == AF_INET6) {
struct sockaddr_in6* tcp_sin6 = (struct sockaddr_in6*)&srv->ip; struct sockaddr_in6* tcp_sin6 = (struct sockaddr_in6*)&srv->ip;
struct TOPO_ADDR6* a6 = memory_pool_alloc(bgp->v6_addr_pool); struct TOPO_ADDR6* a6 = memory_pool_alloc(group->instance->topo_groups->v6_addr_pool);
memcpy(a6->addr, &tcp_sin6->sin6_addr, 16); a6->port = ntohs(tcp_sin6->sin6_port); memcpy(a6->addr, &tcp_sin6->sin6_addr, 16); a6->port = ntohs(tcp_sin6->sin6_port);
a6->type = TOPO_ADDR_INTERFACE; a6->socket_id = 0; a6->protocol = TOPO_PROTO_TCP; a6->type = TOPO_ADDR_INTERFACE; a6->socket_id = 0; a6->protocol = TOPO_PROTO_TCP;
a6->next = ni->v6_addrs; ni->v6_addrs = a6; a6->next = ni->v6_addrs; ni->v6_addrs = a6;
@ -605,11 +605,11 @@ int topo_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_BGP*
s = instance->config->my_subnets; s = instance->config->my_subnets;
while (s) { while (s) {
if (s->ip.family == AF_INET) { if (s->ip.family == AF_INET) {
struct TOPO_SUBNET4* sub = memory_pool_alloc(bgp->v4_subnet_pool); struct TOPO_SUBNET4* sub = memory_pool_alloc(group->instance->topo_groups->v4_subnet_pool);
memcpy(sub->addr, &s->ip.addr.v4, 4); sub->prefix_length = s->netmask; memcpy(sub->addr, &s->ip.addr.v4, 4); sub->prefix_length = s->netmask;
sub->next = r->v4_subnets; r->v4_subnets = sub; sub->next = r->v4_subnets; r->v4_subnets = sub;
} else if (s->ip.family == AF_INET6) { } else if (s->ip.family == AF_INET6) {
struct TOPO_SUBNET6* sub6 = memory_pool_alloc(bgp->v6_subnet_pool); struct TOPO_SUBNET6* sub6 = memory_pool_alloc(group->instance->topo_groups->v6_subnet_pool);
memcpy(sub6->addr, &s->ip.addr.v6, 16); sub6->prefix_length = s->netmask; memcpy(sub6->addr, &s->ip.addr.v6, 16); sub6->prefix_length = s->netmask;
sub6->next = r->v6_subnets; r->v6_subnets = sub6; sub6->next = r->v6_subnets; r->v6_subnets = sub6;
} }
@ -621,9 +621,9 @@ int topo_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_BGP*
DEBUG_INFO(DEBUG_CATEGORY_BGP, "my_nodeinfo updated: v4s=%d v4a=%d v6s=%d v6a=%d v4sub=%d v6sub=%d ver=%d", DEBUG_INFO(DEBUG_CATEGORY_BGP, "my_nodeinfo updated: v4s=%d v4a=%d v6s=%d v6a=%d v4sub=%d v6sub=%d ver=%d",
sock_count, addr_count, sock6_count, addr6_count, vc, vc6, ni->ver); sock_count, addr_count, sock6_count, addr6_count, vc, vc6, ni->ver);
if (instance->rt && !route_insert(instance->rt, lq)) if (instance->rt && !route_insert(instance->rt, lq))
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "topo_bgp_update_my_nodeinfo: failed to insert local routes"); DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "topo_group_update_my_nodeinfo: failed to insert local routes");
} else { } else {
bgp->local_node->last_ver = bgp->local_node->node->ver; group->local_node->last_ver = group->local_node->node->ver;
} }
return vc; return vc;
} }

18
src/topo_node.h

@ -10,7 +10,7 @@ extern "C" {
#include "../lib/ll_queue.h" #include "../lib/ll_queue.h"
#include "secure_channel.h" #include "secure_channel.h"
struct TOPO_BGP; struct TOPO_GROUP;
struct ETCP_SOCKET; struct ETCP_SOCKET;
struct UTUN_INSTANCE; struct UTUN_INSTANCE;
@ -51,7 +51,7 @@ struct UTUN_INSTANCE;
#define TOPO_FLAG_SEND_SUBNETS 0x01 #define TOPO_FLAG_SEND_SUBNETS 0x01
// ---- group_id по умолчанию ---- // ---- group_id по умолчанию ----
#define TOPO_GROUP_UTUN 1 #define TOPO_GROUP_UTUN 0x8000000000000000ULL
// ---- состояние связности с удалённым узлом (локальное, не передаётся по BGP) ---- // ---- состояние связности с удалённым узлом (локальное, не передаётся по BGP) ----
@ -217,11 +217,11 @@ struct TOPO_NODEQ {
// API // API
// ======================================================================= // =======================================================================
struct TOPO_NODEQ* topo_node_find_by_id(struct TOPO_BGP* bgp, uint64_t node_id); struct TOPO_NODEQ* topo_node_find_by_id(struct TOPO_GROUP* group, uint64_t node_id);
void topo_node_ref(struct TOPO_NODE* ni); void topo_node_ref(struct TOPO_NODE* ni);
void topo_node_unref(struct TOPO_NODE* ni); void topo_node_unref(struct TOPO_NODE* ni);
void topo_node_free_lists(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq); void topo_node_free_lists(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq);
int topo_node_dyn_size(const struct TOPOMSG_NODE* msg); int topo_node_dyn_size(const struct TOPOMSG_NODE* msg);
// convenience accessors // convenience accessors
@ -232,14 +232,14 @@ static inline const struct TOPO_ADDR6* topo_v6_addrs(const struct TOPO_NODE*
static inline const struct TOPO_SUBNET4* topo_v4_subnets(const struct TOPO_NODESUBNETS* r) { return r ? r->v4_subnets : NULL; } static inline const struct TOPO_SUBNET4* topo_v4_subnets(const struct TOPO_NODESUBNETS* r) { return r ? r->v4_subnets : NULL; }
static inline const struct TOPO_SUBNET6* topo_v6_subnets(const struct TOPO_NODESUBNETS* r) { return r ? r->v6_subnets : NULL; } static inline const struct TOPO_SUBNET6* topo_v6_subnets(const struct TOPO_NODESUBNETS* r) { return r ? r->v6_subnets : NULL; }
int topo_node_serialize(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq, uint8_t* out, size_t out_max); int topo_node_serialize(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq, uint8_t* out, size_t out_max);
int topo_node_deserialize(struct TOPO_BGP* bgp, const uint8_t* data, size_t len, struct TOPO_NODE** out_ni, struct TOPO_NODESUBNETS** out_subnets, int topo_node_deserialize(struct TOPO_GROUP* group, const uint8_t* data, size_t len, struct TOPO_NODE** out_ni, struct TOPO_NODESUBNETS** out_subnets,
struct TOPOMSG_TRANZIT** out_tranzit, uint8_t* out_tranzit_count, uint64_t** out_hop_list, uint8_t* out_hop_count); struct TOPOMSG_TRANZIT** out_tranzit, uint8_t* out_tranzit_count, uint64_t** out_hop_list, uint8_t* out_hop_count);
int topo_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_BGP* bgp); int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GROUP* group);
void topo_node_dump_all(struct TOPO_BGP* bgp); void topo_node_dump_all(struct TOPO_GROUP* group);
int topo_node_format_all(struct TOPO_BGP* bgp, char* buf, size_t buf_size); int topo_node_format_all(struct TOPO_GROUP* group, char* buf, size_t buf_size);
#ifdef __cplusplus #ifdef __cplusplus
} }

10
src/topo_node_lmdb.c

@ -3,13 +3,13 @@
#include <stdint.h> #include <stdint.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "topo_node_lmdb.h" #include "topo_node_lmdb.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "../lib/debug_config.h" #include "../lib/debug_config.h"
#include "../lib/mem.h" #include "../lib/mem.h"
#define NODEINFO_DB_MAPSIZE (10UL * 1024 * 1024) #define NODEINFO_DB_MAPSIZE (10UL * 1024 * 1024)
int topo_node_lmdb_init(struct TOPO_BGP* bgp, const char* db_path) { int topo_node_lmdb_init(struct TOPO_GROUP* bgp, const char* db_path) {
if (!bgp || !db_path || !db_path[0]) return -1; if (!bgp || !db_path || !db_path[0]) return -1;
int rc = mdb_env_create(&bgp->nodeinfo_env); int rc = mdb_env_create(&bgp->nodeinfo_env);
if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_create failed: %s", mdb_strerror(rc)); return -1; } if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_create failed: %s", mdb_strerror(rc)); return -1; }
@ -29,12 +29,12 @@ int topo_node_lmdb_init(struct TOPO_BGP* bgp, const char* db_path) {
return 0; return 0;
} }
void topo_node_lmdb_destroy(struct TOPO_BGP* bgp) { void topo_node_lmdb_destroy(struct TOPO_GROUP* bgp) {
if (!bgp) return; if (!bgp) return;
if (bgp->nodeinfo_env) { mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; DEBUG_INFO(DEBUG_CATEGORY_BGP, "LMDB nodeinfo database closed"); } if (bgp->nodeinfo_env) { mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; DEBUG_INFO(DEBUG_CATEGORY_BGP, "LMDB nodeinfo database closed"); }
} }
int topo_node_lmdb_put(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq) { int topo_node_lmdb_put(struct TOPO_GROUP* bgp, struct TOPO_NODEQ* nq) {
if (!bgp || !bgp->nodeinfo_env || !nq || !nq->node) return -1; if (!bgp || !bgp->nodeinfo_env || !nq || !nq->node) return -1;
uint8_t buf[8192]; uint8_t buf[8192];
int ser_len = topo_node_serialize(bgp, nq, buf, sizeof(buf)); int ser_len = topo_node_serialize(bgp, nq, buf, sizeof(buf));
@ -53,7 +53,7 @@ int topo_node_lmdb_put(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq) {
return 0; return 0;
} }
int topo_node_lmdb_del(struct TOPO_BGP* bgp, uint64_t node_id) { int topo_node_lmdb_del(struct TOPO_GROUP* bgp, uint64_t node_id) {
if (!bgp || !bgp->nodeinfo_env) return -1; if (!bgp || !bgp->nodeinfo_env) return -1;
MDB_val key; key.mv_size = 8; key.mv_data = &node_id; MDB_val key; key.mv_size = 8; key.mv_data = &node_id;
MDB_txn* txn = NULL; int rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn); MDB_txn* txn = NULL; int rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn);

10
src/topo_node_lmdb.h

@ -9,12 +9,12 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#include "topo_node.h" #include "topo_node.h"
struct TOPO_BGP; struct TOPO_GROUP;
int topo_node_lmdb_init(struct TOPO_BGP* bgp, const char* db_path); int topo_node_lmdb_init(struct TOPO_GROUP* group, const char* db_path);
void topo_node_lmdb_destroy(struct TOPO_BGP* bgp); void topo_node_lmdb_destroy(struct TOPO_GROUP* group);
int topo_node_lmdb_put(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq); int topo_node_lmdb_put(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq);
int topo_node_lmdb_del(struct TOPO_BGP* bgp, uint64_t node_id); int topo_node_lmdb_del(struct TOPO_GROUP* group, uint64_t node_id);
#ifdef __cplusplus #ifdef __cplusplus

16
src/utun_instance.c

@ -8,7 +8,7 @@
#include "topo_node.h" #include "topo_node.h"
#include "route_lib.h" #include "route_lib.h"
#include "routing.h" #include "routing.h"
#include "topo_bgp.h" #include "topo_group.h"
#include "etcp_connections.h" #include "etcp_connections.h"
#include "etcp.h" #include "etcp.h"
#include "conn_mgr.h" #include "conn_mgr.h"
@ -159,13 +159,14 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
if (socket_result == 1) { if (socket_result == 1) {
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "Partial socket initialization - some servers failed to bind"); DEBUG_WARN(DEBUG_CATEGORY_ETCP, "Partial socket initialization - some servers failed to bind");
} }
instance->bgp = topo_bgp_init(instance); instance->topo_groups = topo_groups_init(instance);
if (!instance->bgp) { if (!instance->topo_groups) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Failed to initialize BGP module"); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Failed to initialize BGP module");
} else { } else {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP module initialized"); DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP module initialized");
if (instance->rt && instance->bgp->local_node) { struct TOPO_GROUP* g = topo_groups_get_default(instance->topo_groups);
topo_bgp_update_my_nodeinfo(instance, instance->bgp); if (instance->rt && g && g->local_node) {
topo_group_update_my_nodeinfo(instance, g);
} }
} }
@ -454,10 +455,9 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
if (instance->conn_mgr) { conn_mgr_destroy(instance->conn_mgr); instance->conn_mgr = NULL; } if (instance->conn_mgr) { conn_mgr_destroy(instance->conn_mgr); instance->conn_mgr = NULL; }
// Cleanup BGP module // Cleanup BGP module
if (instance->bgp) { if (instance->topo_groups) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Destroying BGP module"); DEBUG_INFO(DEBUG_CATEGORY_BGP, "Destroying BGP module");
topo_bgp_destroy(instance); topo_groups_destroy(instance);
instance->bgp = NULL;
} }
// Cleanup firewall // Cleanup firewall

5
src/utun_instance.h

@ -34,7 +34,8 @@ struct ETCP_SOCKET;
struct tun_if; struct tun_if;
struct ETCP_BINDINGS; struct ETCP_BINDINGS;
struct ETCP_ROUTER_BINDINGS; struct ETCP_ROUTER_BINDINGS;
struct TOPO_BGP; struct TOPO_GROUP;
struct TOPO_GROUPS;
struct control_server; struct control_server;
struct msg_transport; struct msg_transport;
struct PING_CONTEXT; struct PING_CONTEXT;
@ -64,7 +65,7 @@ struct UTUN_INSTANCE {
struct CFG_ROUTE_ENTRY* route_subnets; struct CFG_ROUTE_ENTRY* route_subnets;
struct ROUTE_TABLE* rt; struct ROUTE_TABLE* rt;
struct TOPO_BGP* bgp; // BGP module for topology exchange struct TOPO_GROUPS* topo_groups; // Groups module for topology exchange
// Identification // Identification
uint64_t node_id; uint64_t node_id;

2
tests/test_bgp_route_exchange.c

@ -39,7 +39,7 @@
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
#include "../src/routing.h" #include "../src/routing.h"
#include "../src/route_lib.h" #include "../src/route_lib.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/dummynet.h" #include "../src/dummynet.h"
#include "../src/tun_if.h" #include "../src/tun_if.h"
#include "../src/secure_channel.h" #include "../src/secure_channel.h"

12
tests/test_bgp_triangle.c

@ -43,7 +43,7 @@
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
#include "../src/routing.h" #include "../src/routing.h"
#include "../src/route_lib.h" #include "../src/route_lib.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/topo_node.h" #include "../src/topo_node.h"
#include "../src/dummynet.h" #include "../src/dummynet.h"
#include "../src/tun_if.h" #include "../src/tun_if.h"
@ -121,18 +121,18 @@ static void build_node_config(char* buf, size_t size, const struct ncfg* c) {
* ================================================================ */ * ================================================================ */
static int peer_in_nodes(struct UTUN_INSTANCE* inst, uint64_t node_id) { static int peer_in_nodes(struct UTUN_INSTANCE* inst, uint64_t node_id) {
if (!inst || !inst->bgp || !inst->bgp->nodes) return 0; if (!inst || !topo_groups_get_default(inst->topo_groups) || !topo_groups_get_default(inst->topo_groups)->nodes) return 0;
return topo_node_find_by_id(inst->bgp, node_id) != NULL; return topo_node_find_by_id(topo_groups_get_default(inst->topo_groups), node_id) != NULL;
} }
static int node_path_count(struct UTUN_INSTANCE* inst, uint64_t node_id) { static int node_path_count(struct UTUN_INSTANCE* inst, uint64_t node_id) {
struct TOPO_NODEQ* nq = topo_node_find_by_id(inst->bgp, node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(inst->topo_groups), node_id);
if (!nq || !nq->paths) return 0; if (!nq || !nq->paths) return 0;
return queue_entry_count(nq->paths); return queue_entry_count(nq->paths);
} }
static int node_path_has_peer(struct UTUN_INSTANCE* inst, uint64_t node_id, uint64_t peer_id) { static int node_path_has_peer(struct UTUN_INSTANCE* inst, uint64_t node_id, uint64_t peer_id) {
struct TOPO_NODEQ* nq = topo_node_find_by_id(inst->bgp, node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(inst->topo_groups), node_id);
if (!nq || !nq->paths) return 0; if (!nq || !nq->paths) return 0;
struct ll_entry* e = nq->paths->head; struct ll_entry* e = nq->paths->head;
while (e) { while (e) {
@ -146,7 +146,7 @@ static int node_path_has_peer(struct UTUN_INSTANCE* inst, uint64_t node_id, uint
} }
static int node_version(struct UTUN_INSTANCE* inst, uint64_t node_id) { static int node_version(struct UTUN_INSTANCE* inst, uint64_t node_id) {
struct TOPO_NODEQ* nq = topo_node_find_by_id(inst->bgp, node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(inst->topo_groups), node_id);
return nq ? nq->last_ver : -1; return nq ? nq->last_ver : -1;
} }

6
tests/test_conn_mgr.c

@ -26,7 +26,7 @@
#include "../src/config_parser.h" #include "../src/config_parser.h"
#include "../src/config_updater.h" #include "../src/config_updater.h"
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/conn_mgr.h" #include "../src/conn_mgr.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
#include "../lib/debug_config.h" #include "../lib/debug_config.h"
@ -73,7 +73,7 @@ static void ccb(int r, uint64_t id, void* arg) {
static void test1(void* arg) { static void test1(void* arg) {
(void)arg; if (result) return; (void)arg; if (result) return;
if (!topo_node_find_by_id(g_a->bgp, NID_B)) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test1, "t1"); return; } if (!topo_node_find_by_id(topo_groups_get_default(g_a->topo_groups), NID_B)) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test1, "t1"); return; }
fprintf(stderr, "Test 1: direct — conn_mgr_connect_node(B)\n"); fflush(stderr); fprintf(stderr, "Test 1: direct — conn_mgr_connect_node(B)\n"); fflush(stderr);
conn_mgr_connect_node(g_a->conn_mgr, NID_B, 0, ccb, NULL); conn_mgr_connect_node(g_a->conn_mgr, NID_B, 0, ccb, NULL);
uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test2, "t2a"); uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test2, "t2a");
@ -93,7 +93,7 @@ static void test3(void* arg) {
uint64_t aid = 0xEEEE000000000001ULL; uint64_t aid = 0xEEEE000000000001ULL;
struct TOPO_NODE ni; memset(&ni, 0, sizeof(ni)); ni.node_id = aid; ni.ver = 1; struct TOPO_NODE ni; memset(&ni, 0, sizeof(ni)); ni.node_id = aid; ni.ver = 1;
conn_mgr_add_alien_node(g_a->conn_mgr, (uint8_t*)&ni, sizeof(ni)); conn_mgr_add_alien_node(g_a->conn_mgr, (uint8_t*)&ni, sizeof(ni));
struct TOPO_NODEQ* nq = topo_node_find_by_id(g_a->bgp, aid); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(g_a->topo_groups), aid);
fprintf(stderr, "Test 3: alien alien=%d\n", nq ? nq->alien : -1); fflush(stderr); fprintf(stderr, "Test 3: alien alien=%d\n", nq ? nq->alien : -1); fflush(stderr);
if (nq && nq->alien == 1) fprintf(stderr, " OK: alien flag set\n"); if (nq && nq->alien == 1) fprintf(stderr, " OK: alien flag set\n");
else { fail("alien flag not set"); return; } else { fail("alien flag not set"); return; }

12
tests/test_etcp_connect.c

@ -14,7 +14,7 @@
#include "../src/config_parser.h" #include "../src/config_parser.h"
#include "../src/config_updater.h" #include "../src/config_updater.h"
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/topo_node.h" #include "../src/topo_node.h"
#include "../src/secure_channel.h" #include "../src/secure_channel.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
@ -84,7 +84,7 @@ static struct TOPO_NODEQ* mknode(uint64_t nid, const uint8_t pubkey[32],
static void test1(void* arg) { static void test1(void* arg) {
(void)arg; if (result) return; (void)arg; if (result) return;
if (lks(g_a) < 1 || lks(g_b) < 1) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test1, "t1"); return; } if (lks(g_a) < 1 || lks(g_b) < 1) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test1, "t1"); return; }
struct TOPO_NODEQ* nb = topo_node_find_by_id(g_a->bgp, NID_B); struct TOPO_NODEQ* nb = topo_node_find_by_id(topo_groups_get_default(g_a->topo_groups), NID_B);
if (!nb) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test1, "t1b"); return; } if (!nb) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test1, "t1b"); return; }
fprintf(stderr, "Test 1: already connected → EARLY|LATE\n"); fflush(stderr); fprintf(stderr, "Test 1: already connected → EARLY|LATE\n"); fflush(stderr);
cb_type = 0; cb_conn_ok = 0; cb_count = 0; cb_type = 0; cb_conn_ok = 0; cb_count = 0;
@ -110,7 +110,7 @@ static void test3(void* arg) {
uint64_t fnid = 0xF000000000000001ULL; uint64_t fnid = 0xF000000000000001ULL;
struct TOPO_NODEQ* fn = mknode(fnid, fk.public_key, 127,0,0,1, 49999); struct TOPO_NODEQ* fn = mknode(fnid, fk.public_key, 127,0,0,1, 49999);
if (!fn) { fail("mknode failed"); return; } if (!fn) { fail("mknode failed"); return; }
queue_data_put_with_index(g_a->bgp->nodes, &fn->ll); queue_data_put_with_index(topo_groups_get_default(g_a->topo_groups)->nodes, &fn->ll);
g_a->etcp_connect_timeout_tb = 2000; g_a->etcp_connect_timeout_tb = 2000;
cb_type = -1; cb_conn_ok = -1; cb_count = 0; cb_type = -1; cb_conn_ok = -1; cb_count = 0;
int r = etcp_connect(g_a, fn, connect_ccb, NULL, ETCP_CONNECT_EARLY | ETCP_CONNECT_LATE); int r = etcp_connect(g_a, fn, connect_ccb, NULL, ETCP_CONNECT_EARLY | ETCP_CONNECT_LATE);
@ -140,7 +140,7 @@ static void test5(void* arg) {
uint64_t fnid = 0xF000000000000002ULL; uint64_t fnid = 0xF000000000000002ULL;
struct TOPO_NODEQ* fn = mknode(fnid, fk.public_key, 127,0,0,1, 49998); struct TOPO_NODEQ* fn = mknode(fnid, fk.public_key, 127,0,0,1, 49998);
if (!fn) { fail("mknode failed"); return; } if (!fn) { fail("mknode failed"); return; }
queue_data_put_with_index(g_a->bgp->nodes, &fn->ll); queue_data_put_with_index(topo_groups_get_default(g_a->topo_groups)->nodes, &fn->ll);
g_a->etcp_connect_timeout_tb = 2000; g_a->etcp_connect_timeout_tb = 2000;
t5_cb_count = 0; t5_cb_count = 0;
int r1 = etcp_connect(g_a, fn, t5_ccb, NULL, ETCP_CONNECT_EARLY | ETCP_CONNECT_LATE); int r1 = etcp_connect(g_a, fn, t5_ccb, NULL, ETCP_CONNECT_EARLY | ETCP_CONNECT_LATE);
@ -159,7 +159,7 @@ static void test6(void* arg) {
/* ======================== Test 7: EARLY-only flag ======================== */ /* ======================== Test 7: EARLY-only flag ======================== */
static void test7(void* arg) { static void test7(void* arg) {
(void)arg; if (result) return; (void)arg; if (result) return;
struct TOPO_NODEQ* nb = topo_node_find_by_id(g_a->bgp, NID_B); struct TOPO_NODEQ* nb = topo_node_find_by_id(topo_groups_get_default(g_a->topo_groups), NID_B);
if (!nb || lks(g_a) < 1) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test7, "t7"); return; } if (!nb || lks(g_a) < 1) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test7, "t7"); return; }
fprintf(stderr, "Test 7: EARLY-only flag\n"); fflush(stderr); fprintf(stderr, "Test 7: EARLY-only flag\n"); fflush(stderr);
cb_type = 0; cb_conn_ok = 0; cb_count = 0; cb_type = 0; cb_conn_ok = 0; cb_count = 0;
@ -179,7 +179,7 @@ static void test8(void* arg) {
/* ======================== Test 9: LATE-only flag ======================== */ /* ======================== Test 9: LATE-only flag ======================== */
static void test9(void* arg) { static void test9(void* arg) {
(void)arg; if (result) return; (void)arg; if (result) return;
struct TOPO_NODEQ* nb = topo_node_find_by_id(g_a->bgp, NID_B); struct TOPO_NODEQ* nb = topo_node_find_by_id(topo_groups_get_default(g_a->topo_groups), NID_B);
if (!nb || lks(g_a) < 1) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test9, "t9"); return; } if (!nb || lks(g_a) < 1) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test9, "t9"); return; }
fprintf(stderr, "Test 9: LATE-only flag\n"); fflush(stderr); fprintf(stderr, "Test 9: LATE-only flag\n"); fflush(stderr);
cb_type = 0; cb_conn_ok = 0; cb_count = 0; cb_type = 0; cb_conn_ok = 0; cb_count = 0;

2
tests/test_etcp_router.c

@ -30,7 +30,7 @@
#include "../src/tun_if.h" #include "../src/tun_if.h"
#include "../src/secure_channel.h" #include "../src/secure_channel.h"
#include "../src/pkt_normalizer.h" #include "../src/pkt_normalizer.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
#include "../lib/ll_queue.h" #include "../lib/ll_queue.h"
#include "../lib/debug_config.h" #include "../lib/debug_config.h"

6
tests/test_etcp_router_reconnect.c

@ -20,7 +20,7 @@
#include "../src/etcp_connections.h" #include "../src/etcp_connections.h"
#include "../src/etcp_router.h" #include "../src/etcp_router.h"
#include "../src/etcp_api.h" #include "../src/etcp_api.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/topo_node.h" #include "../src/topo_node.h"
#include "../src/config_parser.h" #include "../src/config_parser.h"
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
@ -172,7 +172,7 @@ static void state_step(void) {
switch (g_state) { switch (g_state) {
case ST_INIT: case ST_INIT:
if (g_bgp_ready_mask == 3) { if (g_bgp_ready_mask == 3) {
struct ETCP_CONN* rc = topo_bgp_find_conn_for_node(g_a->bgp, node_c); struct ETCP_CONN* rc = topo_group_find_conn_for_node(topo_groups_get_default(g_a->topo_groups), node_c);
if (rc) g_state=ST_PHASE1_SEND; if (rc) g_state=ST_PHASE1_SEND;
} }
break; break;
@ -204,7 +204,7 @@ static void state_step(void) {
etcp_connect(g_b,nq_c,connect_bgp_ready_cb,&cc_c,ETCP_CONNECT_BGP_READY); etcp_connect(g_b,nq_c,connect_bgp_ready_cb,&cc_c,ETCP_CONNECT_BGP_READY);
} }
if (g_bgp_ready_mask == 3) { if (g_bgp_ready_mask == 3) {
struct ETCP_CONN* rc = topo_bgp_find_conn_for_node(g_a->bgp, node_c); struct ETCP_CONN* rc = topo_group_find_conn_for_node(topo_groups_get_default(g_a->topo_groups), node_c);
if (rc) { g_phase_sent=0; g_state=ST_PHASE3_SEND; } if (rc) { g_phase_sent=0; g_state=ST_PHASE3_SEND; }
} }
break; break;

39
tests/test_etcp_router_unit.c

@ -11,7 +11,7 @@
#include "../src/etcp.h" #include "../src/etcp.h"
#include "../src/etcp_api.h" #include "../src/etcp_api.h"
#include "../src/etcp_router.h" #include "../src/etcp_router.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
#include "../lib/ll_queue.h" #include "../lib/ll_queue.h"
@ -140,13 +140,18 @@ static int setup_sign_keys(void) {
} }
static void setup_bgp_for_sign_test(struct UTUN_INSTANCE* inst, int with_ed25519_key) { static void setup_bgp_for_sign_test(struct UTUN_INSTANCE* inst, int with_ed25519_key) {
struct TOPO_BGP* bgp = u_calloc(1, sizeof(struct TOPO_BGP)); inst->topo_groups = u_calloc(1, sizeof(struct TOPO_GROUPS));
if (!bgp) { printf(" setup_bgp: u_calloc failed\n"); return; } if (!inst->topo_groups) { printf(" setup_bgp: topo_groups alloc failed\n"); return; }
bgp->instance = inst; inst->topo_groups->group_list = queue_new(inst->ua, 0, 0, 0, "group_list_test");
bgp->nodes = queue_new(inst->ua, BGP_NODES_HASH_SIZE, struct TOPO_GROUP* group = u_calloc(1, sizeof(struct TOPO_GROUP));
offsetof(struct TOPO_NODEQ, hash_node_id) - sizeof(struct ll_entry), 8, "bgp_nodes_test"); if (!group) { printf(" setup_bgp: u_calloc failed\n"); return; }
if (!bgp->nodes) { printf(" setup_bgp: queue_new failed\n"); u_free(bgp); return; } group->instance = inst;
inst->bgp = bgp; group->group_id = TOPO_GROUP_UTUN;
group->nodes = queue_new(inst->ua, BGP_NODES_HASH_SIZE,
offsetof(struct TOPO_NODEQ, hash_node_id) - sizeof(struct ll_entry), 8, "group_nodes_test");
if (!group->nodes) { printf(" setup_bgp: queue_new failed\n"); u_free(group); return; }
{ struct ll_entry* e = queue_entry_new(sizeof(struct TOPO_GROUP));
if (e) { *(struct TOPO_GROUP**)e->data = group; queue_data_put(inst->topo_groups->group_list, e); } }
struct TOPO_NODEQ* nq = u_calloc(1, sizeof(struct TOPO_NODEQ)); struct TOPO_NODEQ* nq = u_calloc(1, sizeof(struct TOPO_NODEQ));
if (!nq) { printf(" setup_bgp: nq alloc failed\n"); return; } if (!nq) { printf(" setup_bgp: nq alloc failed\n"); return; }
@ -156,18 +161,22 @@ static void setup_bgp_for_sign_test(struct UTUN_INSTANCE* inst, int with_ed25519
ni->ref_count = 1; ni->node_id = SIGNER_NODE; ni->ref_count = 1; ni->node_id = SIGNER_NODE;
if (with_ed25519_key) memcpy(ni->ed25519_public_key, g_sign_ed25519_pubkey, SC_PUBKEY_SIZE); if (with_ed25519_key) memcpy(ni->ed25519_public_key, g_sign_ed25519_pubkey, SC_PUBKEY_SIZE);
nq->node = ni; nq->hash_node_id = ni->node_id; nq->node = ni; nq->hash_node_id = ni->node_id;
queue_data_put_with_index(bgp->nodes, &nq->ll); queue_data_put_with_index(group->nodes, &nq->ll);
} }
static void teardown_bgp_for_sign_test(struct UTUN_INSTANCE* inst) { static void teardown_bgp_for_sign_test(struct UTUN_INSTANCE* inst) {
if (!inst || !inst->bgp) return; if (!inst || !inst->topo_groups) return;
if (inst->bgp->nodes) { struct TOPO_GROUP* group = topo_groups_get_default(inst->topo_groups);
if (!group) return;
if (group->nodes) {
struct ll_entry* e; struct ll_entry* e;
while ((e = queue_data_get(inst->bgp->nodes)) != NULL) queue_entry_free(e); while ((e = queue_data_get(group->nodes)) != NULL) queue_entry_free(e);
queue_free(inst->bgp->nodes); queue_free(group->nodes);
} }
u_free(inst->bgp); u_free(group);
inst->bgp = NULL; queue_free(inst->topo_groups->group_list);
u_free(inst->topo_groups);
inst->topo_groups = NULL;
} }
static void inject_signed(etcp_recv_fn recv_cb, struct UTUN_INSTANCE* inst, static void inject_signed(etcp_recv_fn recv_cb, struct UTUN_INSTANCE* inst,

16
tests/test_ipv6_sockets.c

@ -34,7 +34,7 @@
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
#include "../src/routing.h" #include "../src/routing.h"
#include "../src/route_lib.h" #include "../src/route_lib.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/topo_node.h" #include "../src/topo_node.h"
#include "../src/tun_if.h" #include "../src/tun_if.h"
#include "../src/secure_channel.h" #include "../src/secure_channel.h"
@ -136,11 +136,11 @@ static int is_connection_established(struct UTUN_INSTANCE* inst) {
static int verify_ipv6_local_nodeinfo(const char* name, struct UTUN_INSTANCE* inst, static int verify_ipv6_local_nodeinfo(const char* name, struct UTUN_INSTANCE* inst,
int expect_socks, int expect_addrs, int expect_subnets) { int expect_socks, int expect_addrs, int expect_subnets) {
if (!inst || !inst->bgp || !inst->bgp->local_node || !inst->bgp->local_node->node) { if (!inst || !topo_groups_get_default(inst->topo_groups) || !topo_groups_get_default(inst->topo_groups)->local_node || !topo_groups_get_default(inst->topo_groups)->local_node->node) {
printf("FAIL [%s]: no bgp/local_node\n", name); printf("FAIL [%s]: no bgp/local_node\n", name);
return 0; return 0;
} }
struct TOPO_NODE* ni = inst->bgp->local_node->node; struct TOPO_NODE* ni = topo_groups_get_default(inst->topo_groups)->local_node->node;
struct ETCP_SOCKET* es = inst->etcp_sockets; struct ETCP_SOCKET* es = inst->etcp_sockets;
int v6_sock_found = 0; int v6_sock_found = 0;
@ -156,7 +156,7 @@ static int verify_ipv6_local_nodeinfo(const char* name, struct UTUN_INSTANCE* in
if (v6a != expect_addrs) { printf("FAIL [%s]: v6_addrs=%d expected=%d\n", name, v6a, expect_addrs); return 0; } if (v6a != expect_addrs) { printf("FAIL [%s]: v6_addrs=%d expected=%d\n", name, v6a, expect_addrs); return 0; }
printf("PASS [%s]: v6_addrs=%d\n", name, v6a); printf("PASS [%s]: v6_addrs=%d\n", name, v6a);
int v6sub = inst->bgp->local_node->subnets ? topo_list_count((struct _topo_head*)inst->bgp->local_node->subnets->v6_subnets) : 0; int v6sub = topo_groups_get_default(inst->topo_groups)->local_node->subnets ? topo_list_count((struct _topo_head*)topo_groups_get_default(inst->topo_groups)->local_node->subnets->v6_subnets) : 0;
if (v6sub != expect_subnets) { printf("FAIL [%s]: v6_subnets=%d expected=%d\n", name, v6sub, expect_subnets); return 0; } if (v6sub != expect_subnets) { printf("FAIL [%s]: v6_subnets=%d expected=%d\n", name, v6sub, expect_subnets); return 0; }
printf("PASS [%s]: v6_subnets=%d\n", name, v6sub); printf("PASS [%s]: v6_subnets=%d\n", name, v6sub);
@ -175,8 +175,8 @@ static int verify_ipv6_local_nodeinfo(const char* name, struct UTUN_INSTANCE* in
i++; a = a->next; i++; a = a->next;
} }
} }
if (expect_subnets > 0 && inst->bgp->local_node->subnets) { if (expect_subnets > 0 && topo_groups_get_default(inst->topo_groups)->local_node->subnets) {
const struct TOPO_SUBNET6* subs = inst->bgp->local_node->subnets->v6_subnets; const struct TOPO_SUBNET6* subs = topo_groups_get_default(inst->topo_groups)->local_node->subnets->v6_subnets;
if (subs) { if (subs) {
uint8_t expected_sub[16] = {0x20,0x01,0x0d,0xb8,0x00,0x01,0,0,0,0,0,0,0,0,0,0}; uint8_t expected_sub[16] = {0x20,0x01,0x0d,0xb8,0x00,0x01,0,0,0,0,0,0,0,0,0,0};
if (memcmp(subs->addr, expected_sub, 16) != 0) { printf("FAIL [%s]: v6 subnet != 2001:db8:1::/48\n", name); return 0; } if (memcmp(subs->addr, expected_sub, 16) != 0) { printf("FAIL [%s]: v6 subnet != 2001:db8:1::/48\n", name); return 0; }
@ -188,8 +188,8 @@ static int verify_ipv6_local_nodeinfo(const char* name, struct UTUN_INSTANCE* in
} }
static int verify_remote_v6_nodeinfo(const char* name, struct UTUN_INSTANCE* inst, uint64_t peer_node_id) { static int verify_remote_v6_nodeinfo(const char* name, struct UTUN_INSTANCE* inst, uint64_t peer_node_id) {
if (!inst || !inst->bgp) { printf("FAIL [%s]: no bgp\n", name); return 0; } if (!inst || !topo_groups_get_default(inst->topo_groups)) { printf("FAIL [%s]: no bgp\n", name); return 0; }
struct TOPO_NODEQ* nq = topo_node_find_by_id(inst->bgp, peer_node_id); struct TOPO_NODEQ* nq = topo_node_find_by_id(topo_groups_get_default(inst->topo_groups), peer_node_id);
if (!nq || !nq->node) { printf("FAIL [%s]: remote node %016llx not found\n", name, (unsigned long long)peer_node_id); return 0; } if (!nq || !nq->node) { printf("FAIL [%s]: remote node %016llx not found\n", name, (unsigned long long)peer_node_id); return 0; }
printf("PASS [%s]: remote node %016llx found\n", name, (unsigned long long)peer_node_id); printf("PASS [%s]: remote node %016llx found\n", name, (unsigned long long)peer_node_id);

30
tests/test_nat_detection.c

@ -21,7 +21,7 @@
#include "../src/config_updater.h" #include "../src/config_updater.h"
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
#include "../src/routing.h" #include "../src/routing.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/route_ping.h" #include "../src/route_ping.h"
#include "../src/topo_node.h" #include "../src/topo_node.h"
#include "../src/tun_if.h" #include "../src/tun_if.h"
@ -216,7 +216,7 @@ int main(void) {
} }
// Разрешаем NAT check для localhost (для теста) // Разрешаем NAT check для localhost (для теста)
if (inst_s->bgp) topo_bgp_set_nat_check_local(inst_s->bgp, 1); if (topo_groups_get_default(inst_s->topo_groups)) topo_group_set_nat_check_local(topo_groups_get_default(inst_s->topo_groups), 1);
if (init_connections(inst_s) != 0 || init_connections(inst_c1) != 0 || init_connections(inst_c2) != 0) { if (init_connections(inst_s) != 0 || init_connections(inst_c1) != 0 || init_connections(inst_c2) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to init connections"); DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to init connections");
@ -244,16 +244,16 @@ int main(void) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for BGP exchange (S learns C1 and C2)..."); DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for BGP exchange (S learns C1 and C2)...");
int bgp_wait_cycles = 0; int bgp_wait_cycles = 0;
while (!test_timed_out && bgp_wait_cycles < 500) { while (!test_timed_out && bgp_wait_cycles < 500) {
if (inst_s->bgp && topo_node_find_by_id(inst_s->bgp, NODE_ID_C1) != NULL && if (topo_groups_get_default(inst_s->topo_groups) && topo_node_find_by_id(topo_groups_get_default(inst_s->topo_groups), NODE_ID_C1) != NULL &&
topo_node_find_by_id(inst_s->bgp, NODE_ID_C2) != NULL) { topo_node_find_by_id(topo_groups_get_default(inst_s->topo_groups), NODE_ID_C2) != NULL) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "S learned about C1 and C2"); DEBUG_INFO(DEBUG_CATEGORY_BGP, "S learned about C1 and C2");
break; break;
} }
uasync_poll(ua, 10); uasync_poll(ua, 10);
bgp_wait_cycles++; bgp_wait_cycles++;
} }
if (!inst_s->bgp || topo_node_find_by_id(inst_s->bgp, NODE_ID_C1) == NULL || if (!topo_groups_get_default(inst_s->topo_groups) || topo_node_find_by_id(topo_groups_get_default(inst_s->topo_groups), NODE_ID_C1) == NULL ||
topo_node_find_by_id(inst_s->bgp, NODE_ID_C2) == NULL) { topo_node_find_by_id(topo_groups_get_default(inst_s->topo_groups), NODE_ID_C2) == NULL) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "S did not learn about C1/C2 in time"); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "S did not learn about C1/C2 in time");
goto cleanup; goto cleanup;
} }
@ -313,7 +313,7 @@ int main(void) {
} }
// 5. Verify all NAT fields on server // 5. Verify all NAT fields on server
struct TOPO_NODEQ* node_c1 = topo_node_find_by_id(inst_s->bgp, NODE_ID_C1); struct TOPO_NODEQ* node_c1 = topo_node_find_by_id(topo_groups_get_default(inst_s->topo_groups), NODE_ID_C1);
if (!node_c1) { if (!node_c1) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "TOPO_NODEQ for C1 disappeared"); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "TOPO_NODEQ for C1 disappeared");
goto cleanup; goto cleanup;
@ -361,9 +361,9 @@ int main(void) {
} }
// Verify local_node socket update on C1 (received NAT_INFO updated nodeinfo) // Verify local_node socket update on C1 (received NAT_INFO updated nodeinfo)
if (inst_c1->bgp && inst_c1->bgp->local_node && inst_c1->bgp->local_node->node) { if (topo_groups_get_default(inst_c1->topo_groups) && topo_groups_get_default(inst_c1->topo_groups)->local_node && topo_groups_get_default(inst_c1->topo_groups)->local_node->node) {
int found = 0; int found = 0;
for (const struct TOPO_SOCKMETA4* m = inst_c1->bgp->local_node->node->v4_sock_meta; m; m = m->next) { for (const struct TOPO_SOCKMETA4* m = topo_groups_get_default(inst_c1->topo_groups)->local_node->node->v4_sock_meta; m; m = m->next) {
if (m->id == sock_c1->sock_id) { if (m->id == sock_c1->sock_id) {
if (m->nat_type != NAT_VERIFIED_EIM) { if (m->nat_type != NAT_VERIFIED_EIM) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: local_node socket meta not updated on C1: nat_type=%u expected=%u", m->nat_type, NAT_VERIFIED_EIM); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: local_node socket meta not updated on C1: nat_type=%u expected=%u", m->nat_type, NAT_VERIFIED_EIM);
@ -375,7 +375,7 @@ int main(void) {
if (!found) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: socket not found in local_node meta on C1"); goto cleanup; } if (!found) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: socket not found in local_node meta on C1"); goto cleanup; }
// Verify NAT addr in flat address list // Verify NAT addr in flat address list
int nat_found = 0; int nat_found = 0;
for (const struct TOPO_ADDR4* a = inst_c1->bgp->local_node->node->v4_addrs; a; a = a->next) { for (const struct TOPO_ADDR4* a = topo_groups_get_default(inst_c1->topo_groups)->local_node->node->v4_addrs; a; a = a->next) {
if (a->type == TOPO_ADDR_NAT && a->socket_id == sock_c1->sock_id) { if (a->type == TOPO_ADDR_NAT && a->socket_id == sock_c1->sock_id) {
uint32_t addr_ip; memcpy(&addr_ip, a->addr, 4); uint32_t addr_ip; memcpy(&addr_ip, a->addr, 4);
if (addr_ip != link_sc1->nat_ip || a->port != link_sc1->nat_port) { if (addr_ip != link_sc1->nat_ip || a->port != link_sc1->nat_port) {
@ -395,7 +395,7 @@ int main(void) {
bgp_wait_cycles = 0; bgp_wait_cycles = 0;
int c2_verified_nat = 0; int c2_verified_nat = 0;
while (!test_timed_out && bgp_wait_cycles < 500) { while (!test_timed_out && bgp_wait_cycles < 500) {
struct TOPO_NODEQ* node_c1_on_c2 = inst_c2->bgp ? topo_node_find_by_id(inst_c2->bgp, NODE_ID_C1) : NULL; struct TOPO_NODEQ* node_c1_on_c2 = topo_groups_get_default(inst_c2->topo_groups) ? topo_node_find_by_id(topo_groups_get_default(inst_c2->topo_groups), NODE_ID_C1) : NULL;
if (node_c1_on_c2 && node_c1_on_c2->node) { if (node_c1_on_c2 && node_c1_on_c2->node) {
for (const struct TOPO_SOCKMETA4* m = node_c1_on_c2->node->v4_sock_meta; m; m = m->next) { for (const struct TOPO_SOCKMETA4* m = node_c1_on_c2->node->v4_sock_meta; m; m = m->next) {
if (m->nat_type == NAT_VERIFIED_EIM) { c2_verified_nat = 1; break; } if (m->nat_type == NAT_VERIFIED_EIM) { c2_verified_nat = 1; break; }
@ -429,7 +429,7 @@ int main(void) {
uint32_t target_ip_net = link_sc1->nat_ip; uint32_t target_ip_net = link_sc1->nat_ip;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "TEST: sending ping with pubkey, nat_ip_net=0x%08x nat_port=%u", DEBUG_INFO(DEBUG_CATEGORY_BGP, "TEST: sending ping with pubkey, nat_ip_net=0x%08x nat_port=%u",
link_sc1->nat_ip, link_sc1->nat_port); link_sc1->nat_ip, link_sc1->nat_port);
int ret = route_ping_send_req_addr(inst_s->bgp, conn_sc2, int ret = route_ping_send_req_addr(topo_groups_get_default(inst_s->topo_groups), conn_sc2,
target_ip_net, link_sc1->nat_port, target_ip_net, link_sc1->nat_port,
3, 10, 200, 3000, nat_ping_resp_cb, NULL, 3, 10, 200, 3000, nat_ping_resp_cb, NULL,
node_c1->node->public_key); node_c1->node->public_key);
@ -459,14 +459,14 @@ int main(void) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for C2 to learn C1 nodeinfo..."); DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for C2 to learn C1 nodeinfo...");
bgp_wait_cycles = 0; bgp_wait_cycles = 0;
while (!test_timed_out && bgp_wait_cycles < 500) { while (!test_timed_out && bgp_wait_cycles < 500) {
if (inst_c2->bgp && topo_node_find_by_id(inst_c2->bgp, NODE_ID_C1) != NULL) { if (topo_groups_get_default(inst_c2->topo_groups) && topo_node_find_by_id(topo_groups_get_default(inst_c2->topo_groups), NODE_ID_C1) != NULL) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "C2 learned C1 nodeinfo"); DEBUG_INFO(DEBUG_CATEGORY_BGP, "C2 learned C1 nodeinfo");
break; break;
} }
uasync_poll(ua, 10); uasync_poll(ua, 10);
bgp_wait_cycles++; bgp_wait_cycles++;
} }
if (!inst_c2->bgp || topo_node_find_by_id(inst_c2->bgp, NODE_ID_C1) == NULL) { if (!topo_groups_get_default(inst_c2->topo_groups) || topo_node_find_by_id(topo_groups_get_default(inst_c2->topo_groups), NODE_ID_C1) == NULL) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: C2 did not learn C1 nodeinfo in time"); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: C2 did not learn C1 nodeinfo in time");
goto cleanup; goto cleanup;
} }
@ -477,7 +477,7 @@ int main(void) {
target_ip_net = link_sc1->nat_ip; target_ip_net = link_sc1->nat_ip;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "TEST: sending ping NO pubkey, nat_ip_net=0x%08x nat_port=%u", DEBUG_INFO(DEBUG_CATEGORY_BGP, "TEST: sending ping NO pubkey, nat_ip_net=0x%08x nat_port=%u",
link_sc1->nat_ip, link_sc1->nat_port); link_sc1->nat_ip, link_sc1->nat_port);
ret = route_ping_send_req_addr(inst_s->bgp, conn_sc2, ret = route_ping_send_req_addr(topo_groups_get_default(inst_s->topo_groups), conn_sc2,
target_ip_net, link_sc1->nat_port, target_ip_net, link_sc1->nat_port,
3, 10, 200, 3000, nat_ping_resp_cb, NULL, 3, 10, 200, 3000, nat_ping_resp_cb, NULL,
node_c1->node->public_key); node_c1->node->public_key);

6
tests/test_nat_transport.c

@ -21,7 +21,7 @@
#include "../src/config_updater.h" #include "../src/config_updater.h"
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
#include "../src/routing.h" #include "../src/routing.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/tun_if.h" #include "../src/tun_if.h"
#include "../src/nat_transport.h" #include "../src/nat_transport.h"
#include "../src/eim_nat.h" #include "../src/eim_nat.h"
@ -565,8 +565,8 @@ int main(void) {
DEBUG_INFO(DEBUG_CATEGORY_NAT, "Waiting for BGP..."); DEBUG_INFO(DEBUG_CATEGORY_NAT, "Waiting for BGP...");
int bgp_cycles = 0; int bgp_cycles = 0;
while (!test_timed_out && bgp_cycles < 500) { while (!test_timed_out && bgp_cycles < 500) {
if (inst_provider->bgp && topo_node_find_by_id(inst_provider->bgp, NODE_ID_CLIENT) && if (topo_groups_get_default(inst_provider->topo_groups) && topo_node_find_by_id(topo_groups_get_default(inst_provider->topo_groups), NODE_ID_CLIENT) &&
inst_client->bgp && topo_node_find_by_id(inst_client->bgp, NODE_ID_PROVIDER)) { topo_groups_get_default(inst_client->topo_groups) && topo_node_find_by_id(topo_groups_get_default(inst_client->topo_groups), NODE_ID_PROVIDER)) {
DEBUG_INFO(DEBUG_CATEGORY_NAT, "BGP exchanged"); DEBUG_INFO(DEBUG_CATEGORY_NAT, "BGP exchanged");
break; break;
} }

2
tests/test_route_lib.c

@ -37,7 +37,7 @@ struct ETCP_CONN {
struct UTUN_INSTANCE { struct UTUN_INSTANCE {
uint64_t node_id; uint64_t node_id;
struct ROUTE_TABLE* rt; struct ROUTE_TABLE* rt;
struct TOPO_BGP* bgp; struct TOPO_GROUP* group;
}; };
/* Helper to create test TOPO_NODEQ with subnet in linked list */ /* Helper to create test TOPO_NODEQ with subnet in linked list */

10
tests/test_route_ping.c

@ -21,7 +21,7 @@
#include "../src/config_updater.h" #include "../src/config_updater.h"
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
#include "../src/routing.h" #include "../src/routing.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/route_ping.h" #include "../src/route_ping.h"
#include "../src/tun_if.h" #include "../src/tun_if.h"
#include "../src/secure_channel.h" #include "../src/secure_channel.h"
@ -248,14 +248,14 @@ int main(void) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for BGP exchange (B learns C)..."); DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for BGP exchange (B learns C)...");
int bgp_wait_cycles = 0; int bgp_wait_cycles = 0;
while (!test_timed_out && bgp_wait_cycles < 500) { while (!test_timed_out && bgp_wait_cycles < 500) {
if (inst_b->bgp && topo_node_find_by_id(inst_b->bgp, NODE_ID_C) != NULL) { if (topo_groups_get_default(inst_b->topo_groups) && topo_node_find_by_id(topo_groups_get_default(inst_b->topo_groups), NODE_ID_C) != NULL) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "B learned about C"); DEBUG_INFO(DEBUG_CATEGORY_BGP, "B learned about C");
break; break;
} }
uasync_poll(ua, 10); uasync_poll(ua, 10);
bgp_wait_cycles++; bgp_wait_cycles++;
} }
if (!inst_b->bgp || topo_node_find_by_id(inst_b->bgp, NODE_ID_C) == NULL) { if (!topo_groups_get_default(inst_b->topo_groups) || topo_node_find_by_id(topo_groups_get_default(inst_b->topo_groups), NODE_ID_C) == NULL) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "B did not learn about C in time"); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "B did not learn about C in time");
goto cleanup; goto cleanup;
} }
@ -271,7 +271,7 @@ int main(void) {
/* addr[] в network byte order, port в host byte order */ /* addr[] в network byte order, port в host byte order */
uint32_t target_ip = 0; uint32_t target_ip = 0;
uint16_t target_port = 0; uint16_t target_port = 0;
struct TOPO_NODEQ* nq = inst_b->bgp ? topo_node_find_by_id(inst_b->bgp, NODE_ID_C) : NULL; struct TOPO_NODEQ* nq = topo_groups_get_default(inst_b->topo_groups) ? topo_node_find_by_id(topo_groups_get_default(inst_b->topo_groups), NODE_ID_C) : NULL;
if (nq && nq->node) { if (nq && nq->node) {
const struct TOPO_ADDR4* a = nq->node->v4_addrs; const struct TOPO_ADDR4* a = nq->node->v4_addrs;
if (a) { if (a) {
@ -287,7 +287,7 @@ int main(void) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending route ping request A->B for C (%s:%u)", DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending route ping request A->B for C (%s:%u)",
ip_to_str(&target_ip, AF_INET).str, (unsigned)target_port); ip_to_str(&target_ip, AF_INET).str, (unsigned)target_port);
memset(&ping_result, 0, sizeof(ping_result)); memset(&ping_result, 0, sizeof(ping_result));
int ret = route_ping_send_req_addr(inst_a->bgp, conn_ab, target_ip, target_port, int ret = route_ping_send_req_addr(topo_groups_get_default(inst_a->topo_groups), conn_ab, target_ip, target_port,
3, // count 3, // count
10, // interval_ms 10, // interval_ms
200, // timeout_ms 200, // timeout_ms

4
tests/test_stcp_traffic.c

@ -4,7 +4,7 @@
#include "../src/etcp.h" #include "../src/etcp.h"
#include "../src/secure_channel.h" #include "../src/secure_channel.h"
#include "../src/etcp_connections.h" #include "../src/etcp_connections.h"
#include "../src/topo_bgp.h" #include "../src/topo_group.h"
#include "../src/topo_node.h" #include "../src/topo_node.h"
#include "../src/utun_instance.h" #include "../src/utun_instance.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
@ -167,7 +167,7 @@ int main(void) {
TASSERT(etcp_bind(srv_inst, 1, srv_recv_cb) >= 0); TASSERT(etcp_bind(srv_inst, 1, srv_recv_cb) >= 0);
TASSERT(etcp_bind(cli_inst, 2, cli_recv_cb) >= 0); TASSERT(etcp_bind(cli_inst, 2, cli_recv_cb) >= 0);
struct TOPO_NODEQ *srv_node = srv_inst->bgp ? srv_inst->bgp->local_node : NULL; struct TOPO_NODEQ *srv_node = topo_groups_get_default(srv_inst->topo_groups) ? topo_groups_get_default(srv_inst->topo_groups)->local_node : NULL;
TASSERT(srv_node); TASSERT(srv_node);
// Increase timeout for TCP STCP handshake // Increase timeout for TCP STCP handshake
cli_inst->etcp_connect_timeout_tb = 100000; // 10 seconds cli_inst->etcp_connect_timeout_tb = 100000; // 10 seconds

2
tools/chatgui/libutun/CMakeLists.txt

@ -56,7 +56,7 @@ set(UTUN_COMMON_SOURCES
${SRC_DIR}/config_updater.c ${SRC_DIR}/config_updater.c
${SRC_DIR}/route_lib.c ${SRC_DIR}/route_lib.c
${SRC_DIR}/route6_lib.c ${SRC_DIR}/route6_lib.c
${SRC_DIR}/topo_bgp.c ${SRC_DIR}/topo_group.c
${SRC_DIR}/route_ping.c ${SRC_DIR}/route_ping.c
${SRC_DIR}/topo_node.c ${SRC_DIR}/topo_node.c
${SRC_DIR}/topo_node_lmdb.c ${SRC_DIR}/topo_node_lmdb.c

10
tools/chatgui/transport/chat_core.c

@ -12,7 +12,7 @@
#include "../../../src/utun_instance.h" #include "../../../src/utun_instance.h"
#include "../../../src/etcp_router.h" #include "../../../src/etcp_router.h"
#include "../../../src/etcp_api.h" #include "../../../src/etcp_api.h"
#include "../../../src/topo_bgp.h" #include "../../../src/topo_group.h"
#include "../../../src/topo_node.h" #include "../../../src/topo_node.h"
#include "../../../src/conn_mgr.h" #include "../../../src/conn_mgr.h"
#include "../../../src/secure_channel.h" #include "../../../src/secure_channel.h"
@ -616,7 +616,8 @@ static void connect_result_cb(int result, uint64_t node_id, void* arg) {
void chat_core_connect_from_invite(struct chat_invite* inv) { void chat_core_connect_from_invite(struct chat_invite* inv) {
if (!g_cc.initialized || !g_cc.inst || !inv) return; if (!g_cc.initialized || !g_cc.inst || !inv) return;
if (!g_cc.inst->bgp || !g_cc.inst->conn_mgr) { struct TOPO_GROUP* group = topo_groups_get_default(g_cc.inst->topo_groups);
if (!group || !g_cc.inst->conn_mgr) {
DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "%s: bgp/conn_mgr not available", CC_ID); DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "%s: bgp/conn_mgr not available", CC_ID);
uint8_t err[12]; int r = -7; uint8_t err[12]; int r = -7;
memcpy(err, &inv->node_id, 8); memcpy(err + 8, &r, 4); memcpy(err, &inv->node_id, 8); memcpy(err + 8, &r, 4);
@ -625,9 +626,8 @@ void chat_core_connect_from_invite(struct chat_invite* inv) {
} }
uint64_t node_id = inv->node_id; uint64_t node_id = inv->node_id;
struct TOPO_BGP* bgp = g_cc.inst->bgp;
if (nodeinfo_find_by_id(bgp, node_id)) { if (nodeinfo_find_by_id(group, node_id)) {
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: node 0x%016llx already in BGP, connecting", DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: node 0x%016llx already in BGP, connecting",
CC_ID, (unsigned long long)node_id); CC_ID, (unsigned long long)node_id);
conn_mgr_connect_node(g_cc.inst->conn_mgr, node_id, 30000, conn_mgr_connect_node(g_cc.inst->conn_mgr, node_id, 30000,
@ -688,7 +688,7 @@ void chat_core_connect_from_invite(struct chat_invite* inv) {
memset(&nq->connectivity, 0, sizeof(nq->connectivity)); memset(&nq->connectivity, 0, sizeof(nq->connectivity));
nq->best_socket = NULL; nq->best_socket = NULL;
queue_data_put_with_index(bgp->nodes, &nq->ll); queue_data_put_with_index(group->nodes, &nq->ll);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: created NODEINFO for 0x%016llx, %d addrs, connecting", DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: created NODEINFO for 0x%016llx, %d addrs, connecting",
CC_ID, (unsigned long long)node_id, inv->addr_count); CC_ID, (unsigned long long)node_id, inv->addr_count);

Loading…
Cancel
Save