Browse Source

refactor: переименование route_node/route_bgp в topo_node/topo_bgp

Файлы: route_node.* route_node_lmdb.* route_bgp.* -> topo_node.* topo_node_lmdb.* topo_bgp.*

Структуры:
- ROUTE_BGP -> TOPO_BGP, ROUTE_BGP_CONN_ITEM -> TOPO_BGP_CONN_ITEM
- NODEINFO -> TOPO_NODE, NODEINFO_Q -> TOPO_NODEQ, NODEINFO_PATH -> TOPO_NODEPATH
- NODEINFO_ROUTES -> TOPO_NODESUBNETS, NODE_CONNECTIVITY -> TOPO_CONNECTIVITY
- wire: NODEINFO_MSG -> TOPOMSG_NODE, NODEINFO_IPV4_* -> TOPOMSG_*4 и т.д.
- memory: NI_IPV4_* -> TOPO_*4, NI_IPV6_* -> TOPO_*6
- ROUTE_SUBCMD_* -> TOPO_SUBCMD_*, ETCP_ID_ROUTE_ENTRY -> ETCP_ID_TOPO_ENTRY

Функции:
- route_bgp_* -> topo_bgp_*
- nodeinfo_* -> topo_node_*
- route_node_* -> topo_node_*
- route_node_lmdb_* -> topo_node_lmdb_*

Смысл: отделение механизма формирования топологии узлов от IP-роутинга.
chatgui
Evgeny 3 months ago
parent
commit
3c3d9a65d9
  1. 2
      build_direct.sh
  2. 24
      compile_commands.json
  3. 4
      cross-build-win.sh
  4. 12
      src/Makefile.am
  5. 122
      src/conn_mgr.c
  6. 6
      src/conn_mgr.h
  7. 20
      src/control_server.c
  8. 4
      src/control_server.h
  9. 6
      src/db_sync.c
  10. 6
      src/etcp.c
  11. 4
      src/etcp_api.h
  12. 20
      src/etcp_connect.c
  13. 18
      src/etcp_connections.c
  14. 42
      src/etcp_router.c
  15. 6
      src/msg_transport.c
  16. 10
      src/route6_lib.c
  17. 6
      src/route6_lib.h
  18. 30
      src/route_connectivity.c
  19. 6
      src/route_connectivity.h
  20. 18
      src/route_lib.c
  21. 8
      src/route_lib.h
  22. 23
      src/route_node_lmdb.h
  23. 48
      src/route_ping.c
  24. 28
      src/route_ping.h
  25. 4
      src/routing.c
  26. 427
      src/topo_bgp.c
  27. 90
      src/topo_bgp.h
  28. 335
      src/topo_node.c
  29. 130
      src/topo_node.h
  30. 14
      src/topo_node_lmdb.c
  31. 23
      src/topo_node_lmdb.h
  32. 10
      src/utun_instance.c
  33. 4
      src/utun_instance.h
  34. 2
      tests/test_bgp_route_exchange.c
  35. 16
      tests/test_bgp_triangle.c
  36. 10
      tests/test_conn_mgr.c
  37. 30
      tests/test_etcp_connect.c
  38. 2
      tests/test_etcp_router.c
  39. 28
      tests/test_etcp_router_reconnect.c
  40. 12
      tests/test_etcp_router_unit.c
  41. 30
      tests/test_ipv6_sockets.c
  42. 32
      tests/test_nat_detection.c
  43. 6
      tests/test_nat_transport.c
  44. 54
      tests/test_route6_lib.c
  45. 36
      tests/test_route_lib.c
  46. 10
      tests/test_route_ping.c
  47. 6
      tests/test_stcp_traffic.c
  48. 6
      tools/chatgui/libutun/CMakeLists.txt
  49. 6
      tools/chatgui/transport/chat_core.c
  50. 4
      tools/etcpmon/etcpmon_protocol.h

2
build_direct.sh

@ -70,7 +70,7 @@ echo "Building utun.exe..."
cd src
EXE_NEEDS_REBUILD=0
CORE_SOURCES="utun.c utun_instance.c config_parser.c config_updater.c route_lib.c route_bgp.c routing.c tun_if.c tun_route.c etcp.c etcp_connections.c etcp_loadbalancer.c secure_channel.c crc32.c pkt_normalizer.c etcp_api.c tun_windows.c"
CORE_SOURCES="utun.c utun_instance.c config_parser.c config_updater.c route_lib.c topo_bgp.c routing.c tun_if.c tun_route.c etcp.c etcp_connections.c etcp_loadbalancer.c secure_channel.c crc32.c pkt_normalizer.c etcp_api.c tun_windows.c"
for src in $CORE_SOURCES; do
if [ -f "$src" ]; then

24
compile_commands.json

@ -500,12 +500,12 @@
"-O2",
"-c",
"-o",
"libutun_a-route_bgp.o",
"route_bgp.c"
"libutun_a-topo_bgp.o",
"topo_bgp.c"
],
"directory": "/home/vnc1/proj/utun3/src",
"file": "/home/vnc1/proj/utun3/src/route_bgp.c",
"output": "/home/vnc1/proj/utun3/src/libutun_a-route_bgp.o"
"file": "/home/vnc1/proj/utun3/src/topo_bgp.c",
"output": "/home/vnc1/proj/utun3/src/libutun_a-topo_bgp.o"
},
{
"arguments": [
@ -540,12 +540,12 @@
"-O2",
"-c",
"-o",
"libutun_a-route_node.o",
"route_node.c"
"libutun_a-topo_node.o",
"topo_node.c"
],
"directory": "/home/vnc1/proj/utun3/src",
"file": "/home/vnc1/proj/utun3/src/route_node.c",
"output": "/home/vnc1/proj/utun3/src/libutun_a-route_node.o"
"file": "/home/vnc1/proj/utun3/src/topo_node.c",
"output": "/home/vnc1/proj/utun3/src/libutun_a-topo_node.o"
},
{
"arguments": [
@ -560,12 +560,12 @@
"-O2",
"-c",
"-o",
"libutun_a-route_node_lmdb.o",
"route_node_lmdb.c"
"libutun_a-topo_node_lmdb.o",
"topo_node_lmdb.c"
],
"directory": "/home/vnc1/proj/utun3/src",
"file": "/home/vnc1/proj/utun3/src/route_node_lmdb.c",
"output": "/home/vnc1/proj/utun3/src/libutun_a-route_node_lmdb.o"
"file": "/home/vnc1/proj/utun3/src/topo_node_lmdb.c",
"output": "/home/vnc1/proj/utun3/src/libutun_a-topo_node_lmdb.o"
},
{
"arguments": [

4
cross-build-win.sh

@ -194,8 +194,8 @@ mkdir -p "$SRC_OBJDIR"
# Все .c файлы из src/Makefile.am (utun_CORE_SOURCES)
SRC_SOURCES=(
utun.c utun_instance.c config_parser.c config_updater.c
route_lib.c route6_lib.c route_bgp.c route_ping.c
route_node.c route_node_lmdb.c route_connectivity.c conn_mgr.c
route_lib.c route6_lib.c topo_bgp.c route_ping.c
topo_node.c topo_node_lmdb.c route_connectivity.c conn_mgr.c
routing.c tun_if.c tun_route.c tun_linux.c tun_freebsd.c tun_windows.c
etcp.c etcp_connections.c etcp_bbr.c etcp_loadbalancer.c
etcp_debug.c etcp_dump.c secure_channel.c crc32.c

12
src/Makefile.am

@ -9,10 +9,10 @@ utun_CORE_SOURCES = \
config_updater.c \
route_lib.c \
route6_lib.c \
route_bgp.c \
topo_bgp.c \
route_ping.c \
route_node.c \
route_node_lmdb.c \
topo_node.c \
topo_node_lmdb.c \
route_connectivity.c \
conn_mgr.c \
db_sync.c \
@ -62,10 +62,10 @@ libutun_a_SOURCES = \
config_updater.c \
route_lib.c \
route6_lib.c \
route_bgp.c \
topo_bgp.c \
route_ping.c \
route_node.c \
route_node_lmdb.c \
topo_node.c \
topo_node_lmdb.c \
route_connectivity.c \
conn_mgr.c \
db_sync.c \

122
src/conn_mgr.c

@ -17,8 +17,8 @@
#include "etcp_router.h"
#include "config_parser.h"
#include "secure_channel.h"
#include "route_node.h"
#include "route_bgp.h"
#include "topo_node.h"
#include "topo_bgp.h"
#include "route_ping.h"
#include "route_connectivity.h"
#include "conn_mgr.h"
@ -32,13 +32,13 @@ static void cm_idle_timer_cb(void* arg);
static void cm_deliver_result(struct CONN_MGR_ENTRY* entry, int result);
static void cm_bg_ping_timer_cb(void* arg);
static int cm_nat_compatible(struct ETCP_SOCKET* our, uint8_t target_config_type, uint8_t target_nat_type);
static uint16_t cm_get_node_min_rtt(struct NODEINFO_Q* nq);
static int cm_has_direct_ip(struct NODEINFO_Q* nq);
static int cm_has_local_addr(struct NODEINFO_Q* nq);
static uint16_t cm_get_node_min_rtt(struct TOPO_NODEQ* nq);
static int cm_has_direct_ip(struct TOPO_NODEQ* nq);
static int cm_has_local_addr(struct TOPO_NODEQ* nq);
static void cm_entry_destroy(struct CONN_MGR_ENTRY* entry);
static void cm_exchange_probe_retry_cb(void* arg);
static uint64_t cm_get_node_max_probe_time(struct NODEINFO_Q* nq);
static int cm_is_rtt_fresh(struct NODEINFO_Q* nq, uint64_t now_tb);
static uint64_t cm_get_node_max_probe_time(struct TOPO_NODEQ* nq);
static int cm_is_rtt_fresh(struct TOPO_NODEQ* nq, uint64_t now_tb);
static void conn_mgr_router_recv_handler(struct ETCP_CONN* conn, struct ll_entry* entry);
static void cm_handle_direct_req(struct ETCP_CONN* conn, const uint8_t* data, size_t len);
@ -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) {
struct ROUTE_BGP* bgp = entry->mgr->instance->bgp;
struct TOPO_BGP* bgp = entry->mgr->instance->bgp;
if (!bgp) return;
struct NODEINFO_Q* nq = nodeinfo_find_by_id(bgp, entry->node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, entry->node_id);
if (!nq) return;
nq->conn_mgr_type = entry->conn_type;
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) {
struct NODEINFO_Q* nq = nodeinfo_find_by_id(mgr->instance->bgp, node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->instance->bgp, node_id);
if (!nq) return;
nq->conn_mgr_type = CONN_TYPE_NONE;
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,
conn_mgr_connect_callback_t cb, void* cb_arg) {
if (!mgr) return CONN_MGR_ERR_INTERNAL;
struct ROUTE_BGP* bgp = mgr->instance->bgp;
struct TOPO_BGP* bgp = mgr->instance->bgp;
if (!bgp) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "conn_mgr_connect: BGP not initialized"); return CONN_MGR_ERR_INTERNAL; }
struct NODEINFO_Q* target = nodeinfo_find_by_id(bgp, node_id);
struct TOPO_NODEQ* target = topo_node_find_by_id(bgp, 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; }
struct CONN_MGR_ENTRY* entry = cm_find_entry(mgr, node_id);
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; }
return CONN_MGR_OK;
}
struct ETCP_CONN* existing = route_bgp_find_conn_for_node(bgp, node_id);
struct ETCP_CONN* existing = topo_bgp_find_conn_for_node(bgp, node_id);
if (existing && existing->peer_node_id == node_id && existing->links) {
struct ETCP_LINK* l = existing->links;
while (l) { if (l->link_status && l->initialized) break; l = l->next; }
@ -270,20 +270,20 @@ 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) {
if (!mgr || !nodeinfo_data || len < sizeof(struct NODEINFO)) return CONN_MGR_ERR_INTERNAL;
struct ROUTE_BGP* bgp = mgr->instance->bgp;
if (!mgr || !nodeinfo_data || len < sizeof(struct TOPO_NODE)) return CONN_MGR_ERR_INTERNAL;
struct TOPO_BGP* bgp = mgr->instance->bgp;
if (!bgp) return CONN_MGR_ERR_INTERNAL;
const struct NODEINFO* src = (const struct NODEINFO*)nodeinfo_data;
const struct TOPO_NODE* src = (const struct TOPO_NODE*)nodeinfo_data;
uint64_t node_id = src->node_id;
struct NODEINFO_Q* existing = nodeinfo_find_by_id(bgp, node_id);
struct TOPO_NODEQ* existing = topo_node_find_by_id(bgp, 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; }
struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO));
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
if (!ni) return CONN_MGR_ERR_INTERNAL;
memcpy(ni, nodeinfo_data, len < sizeof(*ni) ? len : sizeof(*ni));
ni->ref_count = 1;
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)queue_entry_new(sizeof(struct NODEINFO_Q));
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)queue_entry_new(sizeof(struct TOPO_NODEQ));
if (!nq) { u_free(ni); return CONN_MGR_ERR_INTERNAL; }
nq->node = ni; nodeinfo_ref(ni);
nq->node = ni; topo_node_ref(ni);
nq->hash_node_id = ni->node_id;
nq->alien = 1; nq->dirty = 0; nq->last_ver = ni->ver;
nq->connectivity.ping_req_time = 0;
@ -363,7 +363,7 @@ static int cm_nat_compatible(struct ETCP_SOCKET* our, uint8_t target_config_type
return 0;
}
static uint16_t cm_get_node_min_rtt(struct NODEINFO_Q* nq) {
static uint16_t cm_get_node_min_rtt(struct TOPO_NODEQ* nq) {
uint16_t rtt = 0xFFFF;
if (nq->connectivity.interface_status == PROBE_RESULT_REACHABLE && nq->connectivity.interface_min_rtt < rtt)
rtt = nq->connectivity.interface_min_rtt;
@ -374,23 +374,23 @@ static uint16_t cm_get_node_min_rtt(struct NODEINFO_Q* nq) {
return rtt;
}
static uint64_t cm_get_node_max_probe_time(struct NODEINFO_Q* nq) {
static uint64_t cm_get_node_max_probe_time(struct TOPO_NODEQ* nq) {
uint64_t t = nq->connectivity.interface_probe_time;
if (nq->connectivity.nat_probe_time > t) t = nq->connectivity.nat_probe_time;
if (nq->connectivity.real_probe_time > t) t = nq->connectivity.real_probe_time;
return t;
}
static int cm_is_rtt_fresh(struct NODEINFO_Q* nq, uint64_t now_tb) {
static int cm_is_rtt_fresh(struct TOPO_NODEQ* nq, uint64_t now_tb) {
uint64_t last = cm_get_node_max_probe_time(nq);
return (last > 0 && (now_tb - last) < (uint64_t)(CONN_MGR_CANDIDATE_CACHE_MS * 10));
}
static int cm_has_direct_ip(struct NODEINFO_Q* nq) {
static int cm_has_direct_ip(struct TOPO_NODEQ* nq) {
if (!nq || !nq->node) return 0;
for (const struct NI_IPV4_ADDR* a = nq->node->v4_addrs; a; a = a->next) {
if (a->type == ADDR_TYPE_REAL || a->type == ADDR_TYPE_NAT) {
for (const struct NI_IPV4_SOCKET_META* m = nq->node->v4_sock_meta; m; m = m->next) {
for (const struct TOPO_ADDR4* a = nq->node->v4_addrs; a; a = a->next) {
if (a->type == TOPO_ADDR_REAL || a->type == TOPO_ADDR_NAT) {
for (const struct TOPO_SOCKMETA4* m = nq->node->v4_sock_meta; m; m = m->next) {
if (m->id == a->socket_id && (m->config_type == CFG_SERVER_TYPE_PUBLIC || m->config_type == CFG_SERVER_TYPE_UNKNOWN
|| m->nat_type == NAT_VERIFIED_EIM || m->nat_type == NAT_VERIFIED_DIRECT))
return 1;
@ -400,11 +400,11 @@ static int cm_has_direct_ip(struct NODEINFO_Q* nq) {
return 0;
}
static int cm_has_local_addr(struct NODEINFO_Q* nq) {
static int cm_has_local_addr(struct TOPO_NODEQ* nq) {
if (!nq || !nq->node) return 0;
for (const struct NI_IPV4_ADDR* a = nq->node->v4_addrs; a; a = a->next) {
if (a->type == ADDR_TYPE_INTERFACE) {
for (const struct NI_IPV4_SOCKET_META* m = nq->node->v4_sock_meta; m; m = m->next) {
for (const struct TOPO_ADDR4* a = nq->node->v4_addrs; a; a = a->next) {
if (a->type == TOPO_ADDR_INTERFACE) {
for (const struct TOPO_SOCKMETA4* m = nq->node->v4_sock_meta; m; m = m->next) {
if (m->id == a->socket_id && (m->config_type == CFG_SERVER_TYPE_PRIVATE || m->config_type == CFG_SERVER_TYPE_LOCAL))
return 1;
}
@ -426,12 +426,12 @@ struct cm_ping_ctx {
};
static void cm_start_local_scan(struct CONN_MGR_ENTRY* entry) {
struct ROUTE_BGP* bgp = entry->mgr->instance->bgp;
struct NODEINFO_Q* target = nodeinfo_find_by_id(bgp, entry->node_id);
struct TOPO_BGP* bgp = entry->mgr->instance->bgp;
struct TOPO_NODEQ* target = topo_node_find_by_id(bgp, entry->node_id);
if (!target || !target->node) { entry->local_scan_state = CM_TRY_FAILED; return; }
for (const struct NI_IPV4_ADDR* a = target->node->v4_addrs; a; a = a->next) {
if (a->type != ADDR_TYPE_INTERFACE) continue;
for (const struct NI_IPV4_SOCKET_META* m = target->node->v4_sock_meta; m; m = m->next) {
for (const struct TOPO_ADDR4* a = target->node->v4_addrs; a; a = a->next) {
if (a->type != TOPO_ADDR_INTERFACE) continue;
for (const struct TOPO_SOCKMETA4* m = target->node->v4_sock_meta; m; m = m->next) {
if (m->id != a->socket_id || (m->config_type != CFG_SERVER_TYPE_PRIVATE && m->config_type != CFG_SERVER_TYPE_LOCAL)) continue;
struct ETCP_SOCKET* s = entry->mgr->instance->etcp_sockets;
while (s) {
@ -454,14 +454,14 @@ static void cm_start_local_scan(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->local_scan_state == CM_TRY_OK) return;
struct ROUTE_BGP* bgp = entry->mgr->instance->bgp;
struct NODEINFO_Q* target = nodeinfo_find_by_id(bgp, entry->node_id);
struct TOPO_BGP* bgp = entry->mgr->instance->bgp;
struct TOPO_NODEQ* target = topo_node_find_by_id(bgp, entry->node_id);
if (!target || !target->node) { cm_deliver_result(entry, CONN_MGR_ERR_NOT_FOUND); return; }
uint8_t priority_order[] = { ADDR_TYPE_REAL, ADDR_TYPE_NAT, ADDR_TYPE_INTERFACE };
uint8_t priority_order[] = { TOPO_ADDR_REAL, TOPO_ADDR_NAT, TOPO_ADDR_INTERFACE };
for (int pri = 0; pri < 3; pri++) {
for (const struct NI_IPV4_ADDR* 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 != priority_order[pri]) continue;
for (const struct NI_IPV4_SOCKET_META* m = target->node->v4_sock_meta; m; m = m->next) {
for (const struct TOPO_SOCKMETA4* m = target->node->v4_sock_meta; m; m = m->next) {
if (m->id != a->socket_id) continue;
struct ETCP_SOCKET* s = entry->mgr->instance->etcp_sockets;
while (s) {
@ -493,8 +493,8 @@ static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) {
static void cm_direct_timeout_cb(void* arg) {
struct CONN_MGR_ENTRY* entry = (struct CONN_MGR_ENTRY*)arg;
entry->main.timer = NULL;
struct ROUTE_BGP* bgp = entry->mgr->instance->bgp;
struct NODEINFO_Q* target = nodeinfo_find_by_id(bgp, entry->node_id);
struct TOPO_BGP* bgp = entry->mgr->instance->bgp;
struct TOPO_NODEQ* target = topo_node_find_by_id(bgp, entry->node_id);
int has_our = cm_has_direct_ip(bgp->local_node);
int has_target = target ? cm_has_direct_ip(target) : 0;
if (entry->local_scan_state != CM_TRY_OK) {
@ -542,7 +542,7 @@ static void cm_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce,
ctx->attempt++;
if (ctx->attempt < CONN_MGR_LOCAL_SCAN_ATTEMPTS && ctx->phase == 0) {
etcp_send_ping_to_socket(entry->mgr->instance, ctx->sock,
nodeinfo_find_by_id(entry->mgr->instance->bgp, entry->node_id)->node->public_key,
topo_node_find_by_id(entry->mgr->instance->bgp, entry->node_id)->node->public_key,
&ctx->addr, CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0);
return;
}
@ -553,16 +553,16 @@ 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) {
struct ROUTE_BGP* bgp = entry->mgr->instance->bgp;
struct NODEINFO_Q* local = bgp->local_node;
struct TOPO_BGP* bgp = entry->mgr->instance->bgp;
struct TOPO_NODEQ* local = bgp->local_node;
if (!local || !local->node) { cm_deliver_result(entry, CONN_MGR_ERR_INTERNAL); return; }
uint32_t req_id = ++entry->mgr->next_request_id;
entry->main.request_id = req_id; entry->main.phase = 2;
uint8_t direct_count = 0;
struct { uint8_t type; uint8_t ip[4]; uint16_t port; uint8_t socket_id; } out_addrs[8];
for (const struct NI_IPV4_ADDR* a = local->node->v4_addrs; a && direct_count < 8; a = a->next) {
if (a->type != ADDR_TYPE_REAL && a->type != ADDR_TYPE_NAT) continue;
for (const struct NI_IPV4_SOCKET_META* m = local->node->v4_sock_meta; m; m = m->next) {
for (const struct TOPO_ADDR4* a = local->node->v4_addrs; a && direct_count < 8; a = a->next) {
if (a->type != TOPO_ADDR_REAL && a->type != TOPO_ADDR_NAT) continue;
for (const struct TOPO_SOCKMETA4* m = local->node->v4_sock_meta; m; m = m->next) {
if (m->id == a->socket_id && (m->config_type == CFG_SERVER_TYPE_PUBLIC || m->config_type == CFG_SERVER_TYPE_UNKNOWN
|| m->nat_type == NAT_VERIFIED_EIM || m->nat_type == NAT_VERIFIED_DIRECT)) {
out_addrs[direct_count].type = a->type; memcpy(out_addrs[direct_count].ip, a->addr, 4);
@ -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++) {
uint64_t id = resp->my_candidates[i].node_id;
struct NODEINFO_Q* nq = nodeinfo_find_by_id(entry->mgr->instance->bgp, id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(entry->mgr->instance->bgp, id);
uint16_t our_rtt = nq ? cm_get_node_min_rtt(nq) : 0;
if (our_rtt == 0xFFFF) our_rtt = 0;
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++) {
pkt.selected[i].node_id = all[i].node_id;
pkt.selected[i].rtt = 0;
struct NODEINFO_Q* nq = nodeinfo_find_by_id(entry->mgr->instance->bgp, all[i].node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(entry->mgr->instance->bgp, all[i].node_id);
if (nq) pkt.selected[i].rtt = cm_get_node_min_rtt(nq);
}
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;
uint64_t now_tb = get_time_tb();
for (uint8_t i = 0; i < ep->cached_resp.my_count && i < 4; i++) {
struct NODEINFO_Q* nq = nodeinfo_find_by_id(mgr->instance->bgp, ep->cached_resp.my_candidates[i].node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->instance->bgp, ep->cached_resp.my_candidates[i].node_id);
if (!nq || !cm_is_rtt_fresh(nq, now_tb)) { need_probe++; break; }
}
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;
uint64_t now_tb = get_time_tb();
for (uint8_t i = 0; i < ep->cached_resp.my_count && i < 4; i++) {
struct NODEINFO_Q* nq = nodeinfo_find_by_id(mgr->instance->bgp, ep->cached_resp.my_candidates[i].node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->instance->bgp, 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 (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));
struct ETCP_CONN* new_conn = etcp_connection_create(conn->instance, NULL);
if (new_conn) {
struct NODEINFO_Q* nq = nodeinfo_find_by_id(conn->instance->bgp, src_node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(conn->instance->bgp, src_node_id);
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));
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();
for (uint8_t i = 0; i < req->candidate_count && i < 4; i++) {
uint64_t cand_id = req->candidates[i].node_id;
struct NODEINFO_Q* nq = nodeinfo_find_by_id(mgr->instance->bgp, cand_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->instance->bgp, cand_id);
if (nq && cm_is_rtt_fresh(nq, now_tb)) continue;
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;
for (uint8_t i = 0; i < resp.your_count; i++) {
resp.your_candidates[i].node_id = req->candidates[i].node_id;
struct NODEINFO_Q* nq2 = nodeinfo_find_by_id(mgr->instance->bgp, req->candidates[i].node_id);
struct TOPO_NODEQ* nq2 = topo_node_find_by_id(mgr->instance->bgp, req->candidates[i].node_id);
uint16_t rtt = nq2 ? cm_get_node_min_rtt(nq2) : 0;
resp.your_candidates[i].rtt = rtt;
}
@ -913,7 +913,7 @@ static void cm_handle_disconnect(struct CONN_MGR* mgr, uint64_t node_id) {
static void cm_bg_ping_timer_cb(void* arg) {
struct CONN_MGR* mgr = (struct CONN_MGR*)arg;
struct ROUTE_BGP* bgp = mgr->instance->bgp;
struct TOPO_BGP* bgp = mgr->instance->bgp;
if (!bgp || !bgp->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");
return;
@ -939,10 +939,10 @@ static void cm_bg_ping_timer_cb(void* arg) {
e = bgp->nodes->head;
while (e && cursor < mgr->bg_ping_cursor) { cursor++; e = e->next; }
if (e) {
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e;
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
uint64_t node_id = nq->node->node_id;
if (node_id != mgr->instance->node_id) {
struct ETCP_CONN* dconn = route_bgp_find_conn_for_node(bgp, node_id);
struct ETCP_CONN* dconn = topo_bgp_find_conn_for_node(bgp, node_id);
int has_active = 0;
if (dconn && 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();
for (uint8_t i = 0; i < mgr->best_candidate_count; i++) {
uint64_t cand_id = mgr->best_candidates[i].node_id;
struct NODEINFO_Q* nq = nodeinfo_find_by_id(mgr->instance->bgp, cand_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->instance->bgp, cand_id);
if (!nq) {
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;
@ -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]));
mgr->best_candidate_count--; i--; continue;
}
struct ETCP_CONN* dconn = route_bgp_find_conn_for_node(mgr->instance->bgp, cand_id);
struct ETCP_CONN* dconn = topo_bgp_find_conn_for_node(mgr->instance->bgp, cand_id);
int has_active = 0;
if (dconn && dconn->links) {
struct ETCP_LINK* l = dconn->links;

6
src/conn_mgr.h

@ -11,12 +11,12 @@ extern "C" {
#include "../lib/ll_queue.h"
#include "etcp_api.h"
#include "etcp_router.h"
#include "route_node.h"
#include "topo_node.h"
struct UTUN_INSTANCE;
struct ETCP_CONN;
struct NODEINFO_Q;
struct ROUTE_BGP;
struct TOPO_NODEQ;
struct TOPO_BGP;
/**
* @file conn_mgr.h

20
src/control_server.c

@ -10,9 +10,9 @@
#include "etcp_connections.h"
#include "tun_if.h"
#include "route_lib.h"
#include "route_bgp.h"
#include "topo_bgp.h"
#include "etcp_router.h"
#include "route_node.h"
#include "topo_node.h"
#include "pkt_normalizer.h"
#include "../tools/etcpmon/etcpmon_protocol.h"
#include "../lib/u_async.h"
@ -100,7 +100,7 @@ static void send_debug_config(struct control_server* server, struct control_clie
static void send_error(struct control_client* client, uint8_t error_code, const char* msg, uint8_t seq_id);
static void control_server_send_node_list(struct control_server* server, struct control_client* client, uint8_t seq_id);
static void send_single_node_info(struct control_server* server, struct control_client* client, struct NODEINFO_Q* nq);
static void send_single_node_info(struct control_server* server, struct control_client* client, struct TOPO_NODEQ* nq);
static int control_client_send(struct control_server* server, struct control_client* client, uint8_t* dgram, uint16_t len);
static struct ETCP_CONN* find_connection_by_peer_id(struct UTUN_INSTANCE* instance, uint64_t peer_id);
@ -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;
if (strncmp(cmd->action, "nat", 3) == 0) {
DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Action 'nat' received, requesting NAT check for all links");
route_bgp_request_nat_check_all(server->instance->bgp);
topo_bgp_request_nat_check_all(server->instance->bgp);
} else if (strncmp(cmd->action, "nodes", 5) == 0) {
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;
char* text = (char*)u_malloc(text_max);
if (text) {
int text_len = route_node_format_all(server->instance->bgp, text, text_max);
int text_len = topo_node_format_all(server->instance->bgp, text, text_max);
if (text_len < 0) text_len = 0;
text[text_len] = '\0';
uint16_t rsp_size = ETCPMON_ACTION_RESULT_SIZE(text_len);
@ -1385,10 +1385,10 @@ static struct ETCP_CONN* find_connection_by_peer_id(struct UTUN_INSTANCE* instan
* Node Info Helpers (send_single_node_info, send_node_list, notify_change)
* ============================================================================ */
static void send_single_node_info(struct control_server* server, struct control_client* client, struct NODEINFO_Q* 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;
uint8_t buf[8192];
int ser_len = nodeinfo_serialize(server->instance->bgp, nq, buf + 2, sizeof(buf) - 2);
int ser_len = topo_node_serialize(server->instance->bgp, nq, buf + 2, sizeof(buf) - 2);
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;
size_t data_size = 2 + (size_t)ser_len;
@ -1405,7 +1405,7 @@ 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) {
struct ROUTE_BGP* bgp = server->instance->bgp;
struct TOPO_BGP* bgp = server->instance->bgp;
if (!bgp) { send_error(client, ETCPMON_ERR_SERVER_BUSY, "BGP not available", seq_id); return; }
/* Send local node first */
@ -1414,7 +1414,7 @@ static void control_server_send_node_list(struct control_server* server, struct
/* Send all known remote nodes */
struct ll_entry* e = bgp->nodes ? bgp->nodes->head : NULL;
while (e) {
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e;
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
send_single_node_info(server, client, nq);
e = e->next;
}
@ -1429,7 +1429,7 @@ static void control_server_send_node_list(struct control_server* server, struct
DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Sent node list to client (seq=%d)", seq_id);
}
void control_server_notify_node_change(struct control_server* server, struct NODEINFO_Q* node) {
void control_server_notify_node_change(struct control_server* server, struct TOPO_NODEQ* node) {
if (!server || !node) return;
struct control_client* client = server->clients;
while (client) {

4
src/control_server.h

@ -19,7 +19,7 @@ extern "C" {
/* Forward declarations */
struct UTUN_INSTANCE;
struct UASYNC;
struct NODEINFO_Q;
struct TOPO_NODEQ;
struct ll_queue;
/* Forward declaration */
@ -117,7 +117,7 @@ void control_server_process_updates(struct control_server* server);
*/
uint32_t control_server_get_client_count(const struct control_server* server);
void control_server_notify_node_change(struct control_server* server, struct NODEINFO_Q* node);
void control_server_notify_node_change(struct control_server* server, struct TOPO_NODEQ* node);
void control_server_notify_node_removed(struct control_server* server, uint64_t node_id);
#ifdef __cplusplus

6
src/db_sync.c

@ -5,7 +5,7 @@
#include "etcp.h"
#include "etcp_router.h"
#include "utun_instance.h"
#include "route_bgp.h"
#include "topo_bgp.h"
#include "../lib/debug_config.h"
#include "../lib/mem.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) {
struct DB_SYNC* db = (struct DB_SYNC*)arg;
if (!db || !db->enabled) return;
struct ROUTE_BGP* bgp = db->inst->bgp;
struct TOPO_BGP* bgp = db->inst->bgp;
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; }
// Check all known peers with active connections
struct ll_entry* e = bgp->senders_list->head;
while (e) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data;
struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)e->data;
if (item->conn && item->conn->peer_node_id != 0 && item->conn->links_up) {
uint64_t pid = item->conn->peer_node_id;
if (pid != db->inst->node_id) {

6
src/etcp.c

@ -5,7 +5,7 @@
#include "etcp_loadbalancer.h"
#include "etcp_router.h"
#include "routing.h"
#include "route_bgp.h"
#include "topo_bgp.h"
#include "route_ping.h"
#include "../lib/u_async.h"
#include "../lib/ll_queue.h"
@ -96,7 +96,7 @@ static void feed_dgram_to_asm(struct ETCP_CONN* etcp, struct PKTNORM* pn,
if (pkt_len == 0 || pkt_len > 16384 || *asm_len < 2 + pkt_len) break;
const uint8_t* pkt_data = *asm_buf + 2;
if (pkt_data[0] != ETCP_ID_ROUTE_ENTRY) {
if (pkt_data[0] != ETCP_ID_TOPO_ENTRY) {
struct ll_entry* e = ll_alloc_lldgram(pkt_len);
if (e) {
memcpy(e->dgram, pkt_data, pkt_len);
@ -303,7 +303,7 @@ void etcp_connection_close(struct ETCP_CONN* etcp) {
routing_del_conn(etcp);
// NOTE: route_bgp_remove_conn is already called via down_cbk in etcp_on_down() above
// NOTE: topo_bgp_remove_conn is already called via down_cbk in etcp_on_down() above
// DO NOT call it again here to avoid double-processing and ref_count corruption
// Очистить транзитные очереди (до pn_deinit/stcp_link_close — waiter'ы на normalizer->input/tx_queue)

4
src/etcp_api.h

@ -71,7 +71,7 @@ typedef void (*etcp_recv_fn)(struct ETCP_CONN* conn, struct ll_entry* entry);
// Forward declaration
struct ETCP_CONN;
struct UTUN_INSTANCE;
struct NODEINFO_Q;
struct TOPO_NODEQ;
typedef void (*etcp_cbk_fn)(struct ETCP_CONN* conn, void* arg);
// ---- Background connection initialization ----
@ -81,7 +81,7 @@ typedef void (*etcp_cbk_fn)(struct ETCP_CONN* conn, void* arg);
typedef void (*etcp_connect_callback_t)(void* arg, struct ETCP_CONN* conn, int type);
int etcp_connect(struct UTUN_INSTANCE* instance, struct NODEINFO_Q* node,
int etcp_connect(struct UTUN_INSTANCE* instance, struct TOPO_NODEQ* node,
etcp_connect_callback_t cb, void* arg, uint8_t flags);
/**

20
src/etcp_connect.c

@ -1,7 +1,7 @@
#include "etcp_api.h"
#include "etcp.h"
#include "utun_instance.h"
#include "route_node.h"
#include "topo_node.h"
#include "stcp_link.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
@ -69,19 +69,19 @@ static void connect_cancel(struct ETCP_CONNECT* ctx) {
u_free(ctx);
}
static void connect_create_links_v4(struct ETCP_CONNECT* ctx, struct NODEINFO_Q* node) {
static void connect_create_links_v4(struct ETCP_CONNECT* ctx, struct TOPO_NODEQ* node) {
if (!node || !node->node) return;
for (const struct NI_IPV4_ADDR* a = node->node->v4_addrs; a; a = a->next) {
for (const struct TOPO_ADDR4* a = node->node->v4_addrs; a; a = a->next) {
if (a->port == 0) continue;
{ int zero = 1; for (int j = 0; j < 4; j++) if (a->addr[j] != 0) { zero = 0; break; } if (zero) continue; }
struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET;
memcpy(&sin.sin_addr.s_addr, a->addr, 4); sin.sin_port = htons(a->port);
struct sockaddr_storage sa; memcpy(&sa, &sin, sizeof(sin));
if (!(a->protocol & NODE_PROTO_TCP)) {
if (!(a->protocol & TOPO_PROTO_TCP)) {
struct ETCP_SOCKET* s = ctx->instance->etcp_sockets;
while (s) { if (s->local_addr.ss_family == AF_INET) etcp_link_new(ctx->conn, s, &sa, 0); s = s->next; }
}
if ((a->protocol & NODE_PROTO_TCP) && !ctx->tcp_link) {
if ((a->protocol & TOPO_PROTO_TCP) && !ctx->tcp_link) {
struct stcp_link_config tcp_cfg = {.ua = ctx->instance->ua, .my_keys = &ctx->instance->my_keys, .inst = ctx->instance,
.peer_pubkey = ctx->conn->crypto_ctx.peer_public_key, .peer_pubkey_mode = 0,
.remote_addr = &sa, .remote_port = a->port};
@ -91,19 +91,19 @@ static void connect_create_links_v4(struct ETCP_CONNECT* ctx, struct NODEINFO_Q*
}
}
static void connect_create_links_v6(struct ETCP_CONNECT* ctx, struct NODEINFO_Q* node) {
static void connect_create_links_v6(struct ETCP_CONNECT* ctx, struct TOPO_NODEQ* node) {
if (!node || !node->node) return;
for (const struct NI_IPV6_ADDR* a = node->node->v6_addrs; a; a = a->next) {
for (const struct TOPO_ADDR6* a = node->node->v6_addrs; a; a = a->next) {
if (a->port == 0) continue;
int zero = 1; for (int j = 0; j < 16; j++) if (a->addr[j] != 0) { zero = 0; break; } if (zero) continue;
struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6;
memcpy(&sin6.sin6_addr, a->addr, 16); sin6.sin6_port = htons(a->port);
struct sockaddr_storage sa; memcpy(&sa, &sin6, sizeof(sin6));
if (!(a->protocol & NODE_PROTO_TCP)) {
if (!(a->protocol & TOPO_PROTO_TCP)) {
struct ETCP_SOCKET* s = ctx->instance->etcp_sockets;
while (s) { if (s->local_addr.ss_family == AF_INET6) etcp_link_new(ctx->conn, s, &sa, 0); s = s->next; }
}
if ((a->protocol & NODE_PROTO_TCP) && !ctx->tcp_link) {
if ((a->protocol & TOPO_PROTO_TCP) && !ctx->tcp_link) {
struct stcp_link_config tcp_cfg = {.ua = ctx->instance->ua, .my_keys = &ctx->instance->my_keys, .inst = ctx->instance,
.peer_pubkey = ctx->conn->crypto_ctx.peer_public_key, .peer_pubkey_mode = 0,
.remote_addr = &sa, .remote_port = a->port};
@ -205,7 +205,7 @@ static void connect_ready_cb(struct ETCP_CONN* conn, void* arg) {
connect_settle_timeout_cb, "etcp_connect_settle");
}
int etcp_connect(struct UTUN_INSTANCE* inst, struct NODEINFO_Q* node,
int etcp_connect(struct UTUN_INSTANCE* inst, struct TOPO_NODEQ* node,
etcp_connect_callback_t cb, void* arg, uint8_t flags) {
if (!inst || !node || !cb) return -1;
uint64_t node_id = node->node->node_id;

18
src/etcp_connections.c

@ -17,8 +17,8 @@
#include "crc32.h"
#include "etcp.h"
#include "stcp_link.h"
#include "route_node.h"
#include "route_bgp.h"
#include "topo_node.h"
#include "topo_bgp.h"
#include "route_ping.h"
#include "../lib/memory_pool.h"
#include "../lib/u_async.h"
@ -1289,7 +1289,7 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk
link->nat_type = NAT_TYPE_DIRECT;
link->nat_check_status = NAT_CHECK_EIM;
if (link->etcp->instance->bgp) {
route_bgp_send_nat_info(link->etcp, link->remote_socket_id,
topo_bgp_send_nat_info(link->etcp, link->remote_socket_id,
link->nat_ip, link->nat_port, NAT_TYPE_DIRECT);
}
DEBUG_INFO(DEBUG_CATEGORY_BGP, "DIRECT IP: %s:%u for %s",
@ -1311,15 +1311,15 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk
nat_sin->sin_addr.s_addr = my_ip;
nat_sin->sin_port = ((struct sockaddr_in*)&e_sock->interface_addr)->sin_port;
if (link->etcp->instance->bgp) {
route_bgp_update_my_nodeinfo(link->etcp->instance->bgp->instance, link->etcp->instance->bgp);
struct ROUTE_BGP* bgp = link->etcp->instance->bgp;
topo_bgp_update_my_nodeinfo(link->etcp->instance->bgp->instance, link->etcp->instance->bgp);
struct TOPO_BGP* bgp = link->etcp->instance->bgp;
if (bgp->local_node && bgp->senders_list) {
bgp->local_node->node->ver = (bgp->local_node->node->ver % 255) + 1;
bgp->local_node->dirty = 1;
struct ll_entry* se = bgp->senders_list->head;
while (se) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data;
if (item && item->conn) route_bgp_send_nodeinfo(bgp->local_node, item->conn);
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;
}
}
@ -1369,7 +1369,7 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk
loadbalancer_link_ready(link);
// Restart NAT check after link is up (e.g. after address change or reinit)
if (link->etcp->instance->bgp) {
if (link->nat_check_status < NAT_CHECK_IN_PROGRESS) route_bgp_start_link_nat_check(link->etcp->instance->bgp, link);
if (link->nat_check_status < NAT_CHECK_IN_PROGRESS) topo_bgp_start_link_nat_check(link->etcp->instance->bgp, link);
}
}
@ -1839,7 +1839,7 @@ ec_fr:
}
// Initialize only sockets (servers for incoming connections)
// Called before route_bgp_init() to populate etcp_sockets for nodeinfo
// Called before topo_bgp_init() to populate etcp_sockets for nodeinfo
// Returns: 0 = all OK, 1 = partial success (some sockets failed), -1 = fatal error (no sockets)
int init_sockets(struct UTUN_INSTANCE* instance) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");

42
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.h"
#include "utun_instance.h"
#include "route_bgp.h"
#include "topo_bgp.h"
#include "../lib/debug_config.h"
#include "../lib/mem.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);
struct ETCP_CONN* conn = NULL;
struct ROUTE_BGP* bgp = inst->bgp;
struct TOPO_BGP* bgp = inst->bgp;
if (bgp) {
struct NODEINFO_Q* nq = nodeinfo_find_by_id(bgp, rconn->remote_node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, rconn->remote_node_id);
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++) {
conn = route_bgp_find_conn_for_node(bgp, nq->conn_mgr_intermediaries[i]);
conn = topo_bgp_find_conn_for_node(bgp, nq->conn_mgr_intermediaries[i]);
if (conn) break;
}
}
}
if (!conn) conn = route_bgp_find_conn_for_node(bgp, rconn->remote_node_id);
if (!conn) conn = topo_bgp_find_conn_for_node(bgp, rconn->remote_node_id);
if (!conn) {
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);
@ -259,7 +259,7 @@ static int router_send_one_flags(struct ETCP_ROUTER_CONN* rconn, const uint8_t*
// Отправка без conn (RST для неизвестного src)
static void router_send_to(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t svc_id, uint8_t flag_bits) {
struct ETCP_CONN* conn = route_bgp_find_conn_for_node(inst->bgp, dst);
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, dst);
if (!conn) return;
struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)u_malloc(SVC_ROUTE_HDR_SIZE);
if (!hdr) return;
@ -314,7 +314,7 @@ static void router_close_and_notify(struct ETCP_ROUTER_CONN* rconn) {
rconn->closed = 1;
router_send_close_to_service(rconn);
// Отправляем CLOSE удалённой стороне
struct ETCP_CONN* conn = route_bgp_find_conn_for_node(inst->bgp, rconn->remote_node_id);
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, rconn->remote_node_id);
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; }
@ -389,7 +389,7 @@ static void router_no_route_retry_cb(void* arg) {
struct ETCP_ROUTER_CONN* rconn = (struct ETCP_ROUTER_CONN*)arg;
if (rconn->closed) return;
rconn->no_route_timer = NULL;
struct ETCP_CONN* c = route_bgp_find_conn_for_node(rconn->inst->bgp, rconn->remote_node_id);
struct ETCP_CONN* c = topo_bgp_find_conn_for_node(rconn->inst->bgp, rconn->remote_node_id);
if (c) {
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));
@ -420,17 +420,17 @@ static void router_retransmit_one(struct ETCP_ROUTER_CONN* rconn, struct ROUTER_
hdr->timestamp = get_current_timestamp();
struct ETCP_CONN* conn = NULL;
struct ROUTE_BGP* bgp = inst->bgp;
struct TOPO_BGP* bgp = inst->bgp;
if (bgp) {
struct NODEINFO_Q* nq = nodeinfo_find_by_id(bgp, rconn->remote_node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, rconn->remote_node_id);
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++) {
conn = route_bgp_find_conn_for_node(bgp, nq->conn_mgr_intermediaries[i]);
conn = topo_bgp_find_conn_for_node(bgp, nq->conn_mgr_intermediaries[i]);
if (conn) break;
}
}
}
if (!conn) conn = route_bgp_find_conn_for_node(bgp, rconn->remote_node_id);
if (!conn) conn = topo_bgp_find_conn_for_node(bgp, rconn->remote_node_id);
if (!conn) {
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_retransmit: no route to %016llx svc_id=%u",
(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) {
struct UTUN_INSTANCE* inst = rconn->inst;
struct ETCP_CONN* conn = route_bgp_find_conn_for_node(inst->bgp, rconn->remote_node_id);
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, rconn->remote_node_id);
if (!conn) {
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_ack: no route to %016llx svc_id=%u",
(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);
struct ETCP_CONN* conn = route_bgp_find_conn_for_node(rconn->inst->bgp, rconn->remote_node_id);
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(rconn->inst->bgp, rconn->remote_node_id);
if (seq == rconn->rx_seq) router_try_assembly(rconn, conn);
router_schedule_ack(rconn);
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;
uint8_t* sig = (uint8_t*)entry->dgram + SVC_ROUTE_HDR_SIZE + actual_payload;
struct ROUTE_BGP* bgp = inst->bgp;
struct NODEINFO_Q* nq = bgp ? nodeinfo_find_by_id(bgp, hdr->src_node_id) : NULL;
struct TOPO_BGP* bgp = inst->bgp;
struct TOPO_NODEQ* nq = bgp ? topo_node_find_by_id(bgp, hdr->src_node_id) : NULL;
if (!nq) {
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router: SIGNED packet from unknown node %016llx — dropping",
(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,
struct SVC_ROUTE_HDR* hdr) {
struct ETCP_CONN* next = route_bgp_find_conn_for_node(inst->bgp, hdr->dst_node_id);
struct ETCP_CONN* next = topo_bgp_find_conn_for_node(inst->bgp, hdr->dst_node_id);
if (!next) {
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);
@ -1088,7 +1088,7 @@ int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_
return 0;
}
struct ETCP_CONN* etcp_conn = route_bgp_find_conn_for_node(inst->bgp, dst_node_id);
struct ETCP_CONN* etcp_conn = topo_bgp_find_conn_for_node(inst->bgp, dst_node_id);
if (!etcp_conn) {
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; }
@ -1120,7 +1120,7 @@ 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) {
if (!inst || !inst->bgp) return -1;
struct ETCP_CONN* conn = route_bgp_find_conn_for_node(inst->bgp, node_id);
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, node_id);
if (!conn || !conn->normalizer || !conn->normalizer->input) return -1;
return queue_entry_count(conn->normalizer->input);
}
@ -1129,7 +1129,7 @@ void etcp_router_waiter_register(struct UTUN_INSTANCE* inst, uint64_t peer_node_
struct queue_waiter_handle* h,
queue_threshold_callback_fn callback, void* arg) {
if (!inst || !inst->bgp || !h) return;
struct ETCP_CONN* conn = route_bgp_find_conn_for_node(inst->bgp, peer_node_id);
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, peer_node_id);
if (!conn || !conn->normalizer || !conn->normalizer->input) return;
queue_waiter_wait(conn->normalizer->input, h, callback, arg);
}
@ -1137,7 +1137,7 @@ void etcp_router_waiter_register(struct UTUN_INSTANCE* inst, uint64_t peer_node_
void etcp_router_waiter_cancel(struct UTUN_INSTANCE* inst, uint64_t peer_node_id,
struct queue_waiter_handle* h) {
if (!inst || !inst->bgp || !h) return;
struct ETCP_CONN* conn = route_bgp_find_conn_for_node(inst->bgp, peer_node_id);
struct ETCP_CONN* conn = topo_bgp_find_conn_for_node(inst->bgp, peer_node_id);
if (!conn || !conn->normalizer || !conn->normalizer->input) return;
queue_waiter_cancel(conn->normalizer->input, h);
}

6
src/msg_transport.c

@ -10,7 +10,7 @@
#include "etcp_router.h"
#include "etcp.h"
#include "secure_channel.h"
#include "route_bgp.h"
#include "topo_bgp.h"
#include "../lib/u_async.h"
#include "../lib/debug_config.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: {
uint64_t peer_id = hdr->id;
struct ROUTE_BGP* bgp = t->instance->bgp;
struct TOPO_BGP* bgp = t->instance->bgp;
if (!bgp) {
send_error(client, MSG_ERR_PEER_NOT_FOUND, "BGP not initialized");
break;
}
struct NODEINFO_Q* nq = nodeinfo_find_by_id(bgp, peer_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, peer_id);
if (!nq) {
send_error(client, MSG_ERR_PEER_NOT_FOUND, "peer not found");
DEBUG_WARN(DEBUG_CATEGORY_MSGTRANSPORT, "GET_PEER_INFO: peer=%016llx not found",

10
src/route6_lib.c

@ -3,7 +3,7 @@
#include "../lib/debug_config.h"
#include "../lib/mem.h"
#include "../lib/radix.h"
#include "route_node.h"
#include "topo_node.h"
#include "route6_lib.h"
#define HASH_SIZE 256
@ -63,9 +63,9 @@ void route6_table_destroy(struct ROUTE6_TABLE *table) {
u_free(table);
}
bool route6_insert(struct ROUTE6_TABLE *table, struct NODEINFO_Q *node) {
if (!table || !node || !node->routes || !node->routes->v6_subnets) return false;
for (const struct NI_IPV6_SUBNET* s = node->routes->v6_subnets; s; s = s->next) {
bool route6_insert(struct ROUTE6_TABLE *table, struct TOPO_NODEQ *node) {
if (!table || !node || !node->subnets || !node->subnets->v6_subnets) return false;
for (const struct TOPO_SUBNET6* s = node->subnets->v6_subnets; s; s = s->next) {
struct ll_entry *entry = queue_entry_new(ROUTE6_DATA_SIZE);
if (!entry) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route6_insert: queue_entry_new failed"); return false; }
struct ROUTE6_DATA *rd = (struct ROUTE6_DATA *)entry->data;
@ -81,7 +81,7 @@ bool route6_insert(struct ROUTE6_TABLE *table, struct NODEINFO_Q *node) {
return true;
}
void route6_delete(struct ROUTE6_TABLE *table, struct NODEINFO_Q *node) {
void route6_delete(struct ROUTE6_TABLE *table, struct TOPO_NODEQ *node) {
if (!table || !node) return;
uint64_t node_id = node->node->node_id;
struct ll_entry *entry = queue_find_data_by_index(table->queue, &node_id);

6
src/route6_lib.h

@ -48,7 +48,7 @@ FDxx/8 - опциональные ipv6 подсети узлов /64 (если
struct ROUTE6_DATA {
struct radix_node rn_nodes[2]; // scratch-буфер для rn_addroute
struct NODEINFO_Q *v_node_info; // узел-владелец
struct TOPO_NODEQ *v_node_info; // узел-владелец
uint64_t node_id; // ключ для hash-поиска в ll_queue
uint8_t prefix_length; // 0..128
uint8_t key[17]; // sockaddr-like: {len=17, addr[16]}
@ -66,8 +66,8 @@ struct ROUTE6_TABLE {
struct ROUTE6_TABLE *route6_table_create(struct UASYNC *ua);
void route6_table_destroy(struct ROUTE6_TABLE *table);
bool route6_insert(struct ROUTE6_TABLE *table, struct NODEINFO_Q *node);
void route6_delete(struct ROUTE6_TABLE *table, struct NODEINFO_Q *node);
bool route6_insert(struct ROUTE6_TABLE *table, struct TOPO_NODEQ *node);
void route6_delete(struct ROUTE6_TABLE *table, struct TOPO_NODEQ *node);
const struct ROUTE6_DATA *route6_lookup(struct ROUTE6_TABLE *table, const uint8_t addr[16]);

30
src/route_connectivity.c

@ -13,8 +13,8 @@
#include "utun_instance.h"
#include "etcp.h"
#include "etcp_connections.h"
#include "route_node.h"
#include "route_bgp.h"
#include "topo_node.h"
#include "topo_bgp.h"
#include "route_connectivity.h"
#define CONN_MAX_SOCKET_CANDIDATES 8
@ -22,7 +22,7 @@
struct conn_probe_ctx {
struct conn_probe_ctx* next; /* linked list in nq->connectivity.probe_list */
struct UTUN_INSTANCE* instance;
struct NODEINFO_Q* nq;
struct TOPO_NODEQ* nq;
uint8_t addr_type; // ADDR_TYPE_*
struct sockaddr_storage target_addr;
uint8_t peer_pubkey[SC_PUBKEY_SIZE];
@ -68,7 +68,7 @@ static int sock_addr_cmp(const struct sockaddr_storage* a, const struct sockaddr
}
// проверяет что два адреса (NODEINFO_IPV4_ADDR) не дубликаты по IP+port
static int addr_eq(const struct NODEINFO_IPV4_ADDR* a, uint32_t ip, uint16_t port) {
static int addr_eq(const struct TOPO_ADDR4* a, uint32_t ip, uint16_t port) {
uint32_t a_ip; memcpy(&a_ip, a->addr, 4);
return a_ip == ip && a->port == port;
}
@ -123,7 +123,7 @@ static int conn_match_candidate_sockets(struct UTUN_INSTANCE* instance,
struct sockaddr_in* if_sin = (struct sockaddr_in*)&e_sock->interface_addr;
uint32_t if_ip = if_sin->sin_addr.s_addr;
if (addr_type == ADDR_TYPE_INTERFACE) {
if (addr_type == TOPO_ADDR_INTERFACE) {
// предпочитаем PRIVATE/LOCAL сокеты в той же /24 подсети
if ((e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL)
&& (if_ip & 0x00FFFFFF) == (target_ip & 0x00FFFFFF))
@ -150,7 +150,7 @@ static int conn_match_candidate_sockets(struct UTUN_INSTANCE* instance,
int dup = 0;
for (int i = 0; i < found; i++) if (out_sockets[i] == e_sock) { dup = 1; break; }
if (!dup) {
if (addr_type == ADDR_TYPE_INTERFACE) {
if (addr_type == TOPO_ADDR_INTERFACE) {
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL)
out_sockets[found++] = e_sock;
} else {
@ -251,22 +251,22 @@ static void conn_probe_single_cb(int success, uint16_t rtt, void* arg,
static void conn_probe_finish(struct conn_probe_ctx* ctx, int ok) {
if (!ctx) return;
if (ctx->nq) {
struct NODE_CONNECTIVITY* c = &ctx->nq->connectivity;
struct TOPO_CONNECTIVITY* c = &ctx->nq->connectivity;
struct conn_probe_ctx** p = (struct conn_probe_ctx**)&c->probe_list;
while (*p) { if (*p == ctx) { *p = ctx->next; break; } p = &(*p)->next; }
switch (ctx->addr_type) {
case ADDR_TYPE_INTERFACE:
case TOPO_ADDR_INTERFACE:
c->interface_status = ok ? PROBE_RESULT_REACHABLE : (c->interface_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->interface_status);
if (ok && ctx->best_across_sockets < c->interface_min_rtt) c->interface_min_rtt = ctx->best_across_sockets;
c->interface_probe_time = get_time_tb();
break;
case ADDR_TYPE_NAT:
case TOPO_ADDR_NAT:
c->nat_status = ok ? PROBE_RESULT_REACHABLE : (c->nat_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->nat_status);
if (ok && ctx->best_across_sockets < c->nat_min_rtt) c->nat_min_rtt = ctx->best_across_sockets;
c->nat_probe_time = get_time_tb();
break;
case ADDR_TYPE_REAL:
case TOPO_ADDR_REAL:
c->real_status = ok ? PROBE_RESULT_REACHABLE : (c->real_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->real_status);
if (ok && ctx->best_across_sockets < c->real_min_rtt) c->real_min_rtt = ctx->best_across_sockets;
c->real_probe_time = get_time_tb();
@ -287,7 +287,7 @@ static void conn_probe_finish(struct conn_probe_ctx* ctx, int ok) {
// ---- public API ----
void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct NODEINFO_Q* nq) {
void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct TOPO_NODEQ* nq) {
if (!instance || !nq) return;
if (nq->node->node_id == instance->node_id) return; // не пингуем себя
if (nq->connectivity.probe_status == PROBE_STATUS_IN_PROGRESS) {
@ -310,7 +310,7 @@ void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct NODEIN
// ---- IPv4 addresses ----
if (nq->node && nq->node->v4_addrs) {
uint32_t seen_ips[16]; uint16_t seen_ports[16]; int seen_count = 0;
for (const struct NI_IPV4_ADDR* a = nq->node->v4_addrs; a; a = a->next) {
for (const struct TOPO_ADDR4* a = nq->node->v4_addrs; a; a = a->next) {
uint32_t ip; memcpy(&ip, a->addr, 4); uint16_t port = a->port;
if (ip == 0 || port == 0) continue;
int dup = 0; for (int j = 0; j < seen_count; j++) { if (seen_ips[j] == ip && seen_ports[j] == port) { dup = 1; break; } }
@ -338,7 +338,7 @@ void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct NODEIN
// ---- IPv6 addresses ----
if (nq->node && nq->node->v6_addrs) {
uint8_t seen_ip6s[16][16]; uint16_t seen_ports6[16]; int seen6_count = 0;
for (const struct NI_IPV6_ADDR* a6 = nq->node->v6_addrs; a6; a6 = a6->next) {
for (const struct TOPO_ADDR6* a6 = nq->node->v6_addrs; a6; a6 = a6->next) {
if (a6->port == 0) continue;
int zero = 1; for (int z = 0; z < 16; z++) if (a6->addr[z] != 0) { zero = 0; break; } if (zero) continue;
int dup = 0; for (int j = 0; j < seen6_count; j++) { if (memcmp(seen_ip6s[j], a6->addr, 16) == 0 && seen_ports6[j] == a6->port) { dup = 1; break; } }
@ -376,7 +376,7 @@ void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct NODEIN
}
}
void route_connectivity_cancel_node(struct UTUN_INSTANCE* instance, struct NODEINFO_Q* nq) {
void route_connectivity_cancel_node(struct UTUN_INSTANCE* instance, struct TOPO_NODEQ* nq) {
if (!instance || !nq) return;
nq->connectivity.probe_status = PROBE_STATUS_NONE;
nq->connectivity.pending_count = 0;
@ -391,7 +391,7 @@ void route_connectivity_cancel_all(struct UTUN_INSTANCE* instance) {
int count = 0;
struct ll_entry* e = instance->bgp->nodes->head;
while (e) {
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e;
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
nq->connectivity.probe_status = PROBE_STATUS_NONE;
nq->connectivity.pending_count = 0;
e = e->next;

6
src/route_connectivity.h

@ -7,17 +7,17 @@ extern "C" {
#include <stdint.h>
#include "route_node.h"
#include "topo_node.h"
struct UTUN_INSTANCE;
// Запускает зондирование связности ко всем адресам удалённого узла
void route_connectivity_probe_node(struct UTUN_INSTANCE* instance,
struct NODEINFO_Q* nq);
struct TOPO_NODEQ* nq);
// Отменяет все pending пробы для узла (при удалении / withdraw)
void route_connectivity_cancel_node(struct UTUN_INSTANCE* instance,
struct NODEINFO_Q* nq);
struct TOPO_NODEQ* nq);
// Отменяет все pending пробы для всех узлов (при destroy)
void route_connectivity_cancel_all(struct UTUN_INSTANCE* instance);

18
src/route_lib.c

@ -5,7 +5,7 @@
#include "../lib/mem.h"
#include "../lib/platform_compat.h"
#include "utun_instance.h"
#include "route_node.h"
#include "topo_node.h"
#include "route_lib.h"
#include "etcp_debug.h"
@ -136,7 +136,7 @@ void route_table_destroy(struct ROUTE_TABLE *table) {
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "route_table_destroy: count=%zu", table->count);
// v_node_info — внешний объект (NODEINFO_Q), память им не управляем
// v_node_info — внешний объект (TOPO_NODEQ), память им не управляем
u_free(table->dynamic_subnets);
u_free(table->local_subnets);
u_free(table->entries);
@ -145,19 +145,19 @@ void route_table_destroy(struct ROUTE_TABLE *table) {
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing table destroyed");
}
bool route_insert(struct ROUTE_TABLE *table, struct NODEINFO_Q *node) {
bool route_insert(struct ROUTE_TABLE *table, struct TOPO_NODEQ *node) {
if (!table || !node) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_insert: invalid arguments"); return false; }
if (!node->routes || !node->routes->v4_subnets) {
if (!node->subnets || !node->subnets->v4_subnets) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_insert: node has no v4 subnets");
return false;
}
const struct NI_IPV4_SUBNET* sub = node->routes->v4_subnets;
int cnt = 0; for (const struct NI_IPV4_SUBNET* s = sub; s; s = s->next) cnt++;
const struct TOPO_SUBNET4* sub = node->subnets->v4_subnets;
int cnt = 0; for (const struct TOPO_SUBNET4* s = sub; s; s = s->next) cnt++;
if (cnt == 0) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_insert: 0 subnets"); return false; }
size_t count = (size_t)cnt;
for (const struct NI_IPV4_SUBNET* s = sub; s; s = s->next) {
for (const struct TOPO_SUBNET4* s = sub; s; s = s->next) {
uint32_t network; memcpy(&network, s->addr, 4); network = ntohl(network);
if (check_route_overlap_in_table(network, s->prefix_length, table->entries, table->count)) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_insert: overlap detected for %s/%d", ip_to_string(network).a, s->prefix_length);
@ -173,7 +173,7 @@ bool route_insert(struct ROUTE_TABLE *table, struct NODEINFO_Q *node) {
table->entries = new_entries; table->capacity = new_cap;
}
for (const struct NI_IPV4_SUBNET* s = sub; s; s = s->next) {
for (const struct TOPO_SUBNET4* s = sub; s; s = s->next) {
uint32_t network; memcpy(&network, s->addr, 4); network = ntohl(network);
int pos = binary_search_insert_pos(table->entries, table->count, network, s->prefix_length);
if (pos < (int)table->count) memmove(&table->entries[pos + 1], &table->entries[pos], (table->count - pos) * sizeof(struct ROUTE_ENTRY));
@ -188,7 +188,7 @@ bool route_insert(struct ROUTE_TABLE *table, struct NODEINFO_Q *node) {
return true;
}
void route_delete(struct ROUTE_TABLE *table, struct NODEINFO_Q *node) {
void route_delete(struct ROUTE_TABLE *table, struct TOPO_NODEQ *node) {
if (!table || !node) return;
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "route_delete: removing all routes for node=%016llx", (unsigned long long)node->node->node_id);
size_t i = 0, removed = 0;

8
src/route_lib.h

@ -15,7 +15,7 @@ extern "C" {
struct ETCP_CONNECTIONS;
struct ROUTE_TABLE;
struct ROUTE_ENTRY;
struct NODEINFO_Q;
struct TOPO_NODEQ;
/**
* @brief Флаги узла
@ -34,7 +34,7 @@ typedef enum {
struct ROUTE_ENTRY {
uint32_t network; // Сетевой адрес (big-endian)
uint8_t prefix_length; // Длина префикса подсети
struct NODEINFO_Q* v_node_info; // узел владелец этих маршрутов. null если - локальный маршрут.
struct TOPO_NODEQ* v_node_info; // узел владелец этих маршрутов. null если - локальный маршрут.
};
/**
@ -79,7 +79,7 @@ void route_table_destroy(struct ROUTE_TABLE *table);
*
* @return true если вставка/обновление успешно
*/
bool route_insert(struct ROUTE_TABLE *table, struct NODEINFO_Q *node);
bool route_insert(struct ROUTE_TABLE *table, struct TOPO_NODEQ *node);
/**
* @brief Удаляет все записи из таблицы маршрутизации для указанного узла
@ -87,7 +87,7 @@ bool route_insert(struct ROUTE_TABLE *table, struct NODEINFO_Q *node);
* @param table Указатель на таблицу маршрутизации
* @param node узел, все маршруты которого нужно удалить
*/
void route_delete(struct ROUTE_TABLE *table, struct NODEINFO_Q *node);
void route_delete(struct ROUTE_TABLE *table, struct TOPO_NODEQ *node);
/**
* @brief Выполняет поиск маршрута для заданного IP-адреса

23
src/route_node_lmdb.h

@ -1,23 +0,0 @@
#ifndef ROUTE_NODE_LMDB_H
#define ROUTE_NODE_LMDB_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "route_node.h"
struct ROUTE_BGP;
int route_node_lmdb_init(struct ROUTE_BGP* bgp, const char* db_path);
void route_node_lmdb_destroy(struct ROUTE_BGP* bgp);
int route_node_lmdb_put(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq);
int route_node_lmdb_del(struct ROUTE_BGP* bgp, uint64_t node_id);
#ifdef __cplusplus
}
#endif
#endif

48
src/route_ping.c

@ -14,8 +14,8 @@
#include "etcp_api.h"
#include "etcp.h"
#include "etcp_connections.h"
#include "route_node.h"
#include "route_bgp.h"
#include "topo_node.h"
#include "topo_bgp.h"
#include "route_ping.h"
#include "../lib/u_async.h"
@ -36,7 +36,7 @@ struct route_ping_series_ctx {
struct route_ping_pending {
struct route_ping_pending* next;
struct ROUTE_BGP* bgp;
struct TOPO_BGP* bgp;
uint32_t request_id;
route_ping_callback_t callback;
void* arg;
@ -54,7 +54,7 @@ static void route_ping_pending_timeout(void* arg) {
u_free(p);
return;
}
struct ROUTE_BGP* bgp = p->bgp;
struct TOPO_BGP* bgp = p->bgp;
struct route_ping_pending** cur = &bgp->ping_pending;
while (*cur) {
if (*cur == p) {
@ -70,12 +70,12 @@ static void route_ping_pending_timeout(void* arg) {
}
// прошел ответ "серия пигнов на удаленном узле завершена"
void route_ping_handle_resp(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
if (!bgp || !from_conn || !data || len < sizeof(struct BGP_PING_RESPONSE)) {
void route_ping_handle_resp(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
if (!bgp || !from_conn || !data || len < sizeof(struct TOPO_PING_RESP)) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args");
return;
}
const struct BGP_PING_RESPONSE* resp = (const struct BGP_PING_RESPONSE*)data;
const struct TOPO_PING_RESP* resp = (const struct TOPO_PING_RESP*)data;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "from=%s request_id=%08x sent=%u ok=%u avg_rtt=%u",
from_conn->log_name, (unsigned)resp->request_id,
(unsigned)resp->count_sent, (unsigned)resp->count_ok, (unsigned)resp->avg_rtt);
@ -102,7 +102,7 @@ void route_ping_handle_resp(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn,
(unsigned)resp->request_id);
}
void route_ping_cancel_for_conn(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
void route_ping_cancel_for_conn(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) {
if (!bgp || !conn) return;
if (!bgp->ping_pending) {
@ -148,7 +148,7 @@ void route_ping_cancel_for_conn(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
// ========================================================================
int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn,
int route_ping_send_req_addr(struct TOPO_BGP* bgp, struct ETCP_CONN* to_conn,
uint32_t target_ip, uint16_t target_port,
uint8_t count, uint16_t interval_ms, uint16_t timeout_ms,
uint16_t wait_timeout_ms, route_ping_callback_t cb, void* arg,
@ -157,14 +157,14 @@ int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn,
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args");
return -1;
}
size_t pkt_size = pubkey ? sizeof(struct BGP_PING_REQUEST) : offsetof(struct BGP_PING_REQUEST, pubkey);
struct BGP_PING_REQUEST* req_pkt = u_calloc(1, pkt_size);
size_t pkt_size = pubkey ? sizeof(struct TOPO_PING_REQ) : offsetof(struct TOPO_PING_REQ, pubkey);
struct TOPO_PING_REQ* req_pkt = u_calloc(1, pkt_size);
if (!req_pkt) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "alloc failed");
return -2;
}
req_pkt->cmd = ETCP_ID_ROUTE_ENTRY;
req_pkt->subcmd = ROUTE_SUBCMD_PING_REQ;
req_pkt->cmd = ETCP_ID_TOPO_ENTRY;
req_pkt->subcmd = TOPO_SUBCMD_PING_REQ;
uint32_t new_req_id = bgp->next_ping_req_id++;
req_pkt->request_id = new_req_id;
req_pkt->count = count;
@ -228,10 +228,10 @@ static void route_ping_series_finish(struct route_ping_series_ctx* ctx) {
: (uint16_t)(ctx->timeout_ms * 10); /* таймаут как "плохо" */
/* Отправляем ответ по BGP */
struct BGP_PING_RESPONSE* resp = u_calloc(1, sizeof(struct BGP_PING_RESPONSE));
struct TOPO_PING_RESP* resp = u_calloc(1, sizeof(struct TOPO_PING_RESP));
if (resp) {
resp->cmd = ETCP_ID_ROUTE_ENTRY;
resp->subcmd = ROUTE_SUBCMD_PING_RESP;
resp->cmd = ETCP_ID_TOPO_ENTRY;
resp->subcmd = TOPO_SUBCMD_PING_RESP;
resp->request_id = ctx->request_id;
resp->count_sent = ctx->count_sent;
resp->count_ok = ctx->count_ok;
@ -240,7 +240,7 @@ static void route_ping_series_finish(struct route_ping_series_ctx* ctx) {
struct ll_entry* e = queue_entry_new(0);
if (e) {
e->dgram = (uint8_t*)resp;
e->len = sizeof(struct BGP_PING_RESPONSE);
e->len = sizeof(struct TOPO_PING_RESP);
etcp_send(ctx->reply_conn, e);
DEBUG_INFO(DEBUG_CATEGORY_BGP,
"PING series done %s request_id=%08x sent=%u ok=%u avg_rtt=%u",
@ -303,16 +303,16 @@ static void route_ping_single_cb(int success,
}
// Обработчик PING_REQ (нам запросили "пропингуй узел и верни результат")
void route_ping_handle_req(struct ROUTE_BGP* bgp,
void route_ping_handle_req(struct TOPO_BGP* bgp,
struct ETCP_CONN* from_conn,
const uint8_t* data,
size_t len) {
if (!bgp || !from_conn || !data || len < offsetof(struct BGP_PING_REQUEST, pubkey)) {
if (!bgp || !from_conn || !data || len < offsetof(struct TOPO_PING_REQ, pubkey)) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "ping req: bad args len=%zu", len);
return;
}
const struct BGP_PING_REQUEST* req_pkt = (const struct BGP_PING_REQUEST*)data;
const struct TOPO_PING_REQ* req_pkt = (const struct TOPO_PING_REQ*)data;
/* Создаём контекст серии */
struct route_ping_series_ctx* ctx = u_calloc(1, sizeof(struct route_ping_series_ctx));
@ -327,10 +327,10 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp,
ctx->timeout_ms = req_pkt->timeout_ms;
{
struct NODEINFO_Q* req_nq = nodeinfo_find_by_id(bgp, from_conn->peer_node_id);
struct TOPO_NODEQ* req_nq = topo_node_find_by_id(bgp, from_conn->peer_node_id);
if (req_nq) req_nq->connectivity.ping_req_time = get_time_tb();
}
if (len >= sizeof(struct BGP_PING_REQUEST)) {
if (len >= sizeof(struct TOPO_PING_REQ)) {
memcpy(ctx->pubkey, req_pkt->pubkey, SC_PUBKEY_SIZE);
}
@ -343,9 +343,9 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp,
/* Если target не указан — можно разрешить из nodeinfo */
/*
if (sin->sin_addr.s_addr == 0 && sin->sin_port == 0) {
struct NODEINFO_Q* nq = nodeinfo_find_by_id(bgp, req_pkt->node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, req_pkt->node_id);
if (nq) {
const struct NODEINFO_IPV4_ADDR* addrs;
const struct TOPOMSG_ADDR4* addrs;
int count = get_node_v4_addrs(nq, &addrs);
if (count > 0) {
memcpy(&sin->sin_addr.s_addr, addrs[0].addr, 4);

28
src/route_ping.h

@ -8,14 +8,14 @@ extern "C" {
#include <stdint.h>
#include <stddef.h>
#include "route_bgp.h"
#include "topo_bgp.h"
#define ROUTE_SUBCMD_PING_REQ 0x07
#define ROUTE_SUBCMD_PING_RESP 0x08
#define TOPO_SUBCMD_PING_REQ 0x07
#define TOPO_SUBCMD_PING_RESP 0x08
struct BGP_PING_REQUEST {
uint8_t cmd; // ETCP_ID_ROUTE_ENTRY
uint8_t subcmd; // ROUTE_SUBCMD_PING_REQ
struct TOPO_PING_REQ {
uint8_t cmd; // ETCP_ID_TOPO_ENTRY
uint8_t subcmd; // TOPO_SUBCMD_PING_REQ
uint16_t reserved; // padding для выравнивания request_id
uint32_t request_id; // для корреляции
uint8_t count; // число пингов
@ -27,9 +27,9 @@ struct BGP_PING_REQUEST {
uint8_t pubkey[SC_PUBKEY_SIZE]; // pubkey for encryption if target not in nodes
} __attribute__((packed));
struct BGP_PING_RESPONSE {
struct TOPO_PING_RESP {
uint8_t cmd;
uint8_t subcmd; // ROUTE_SUBCMD_PING_RESP
uint8_t subcmd; // TOPO_SUBCMD_PING_RESP
uint16_t reserved; // padding для выравнивания
uint32_t request_id;
uint8_t count_sent;
@ -42,21 +42,21 @@ typedef void (*route_ping_callback_t)(int success, uint16_t avg_rtt, uint8_t cou
// Отправить запрос пинга по произвольному IP:port (используется для NAT-детекции)
// Если target_ip == 0, используется node_id из списка известных узлов
// Если pubkey != NULL, он передается в пакете (для пинга без локального nodeinfo)
int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn,
int route_ping_send_req_addr(struct TOPO_BGP* bgp, struct ETCP_CONN* to_conn,
uint32_t target_ip, uint16_t target_port,
uint8_t count, uint16_t interval_ms, uint16_t timeout_ms,
uint16_t wait_timeout_ms, route_ping_callback_t cb, void* arg,
const uint8_t* pubkey);
// Очистить список ожидающих запросов (при уничтожении BGP)
void route_ping_destroy_pending(struct ROUTE_BGP* bgp);
void route_ping_destroy_pending(struct TOPO_BGP* bgp);
// Отменить pending запросы для указанного соединения (при удалении conn)
void route_ping_cancel_for_conn(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn);
void route_ping_cancel_for_conn(struct TOPO_BGP* bgp, struct ETCP_CONN* conn);
// Обработчики, вызываемые из route_bgp_receive_cbk
void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
void route_ping_handle_resp(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
// Обработчики, вызываемые из topo_bgp_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_resp(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
#ifdef __cplusplus

4
src/routing.c

@ -2,7 +2,7 @@
#include "../lib/platform_compat.h"
#include "routing.h"
#include "route_lib.h"
#include "route_node.h"
#include "topo_node.h"
#include "tun_if.h"
#include "packet_dump.h"
#include "etcp.h"
@ -138,7 +138,7 @@ void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry, uint64_t
return;
}
struct NODEINFO_Q* nq = route->v_node_info;
struct TOPO_NODEQ* nq = route->v_node_info;
if (!nq || !nq->node || nq->hop_count == 0) {
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "Local route to %s", ip_to_str(&addr, AF_INET).str);
} else {

427
src/route_bgp.c → src/topo_bgp.c

@ -1,6 +1,6 @@
/**
* @file route_bgp.c
* @brief BGP-like обмен маршрутами
* @file topo_bgp.c
* @brief BGP-like обмен топологией узлов
*/
#include <stdlib.h>
#include <string.h>
@ -15,10 +15,10 @@
#include "etcp_connections.h"
#include "etcp_debug.h"
#include "config_parser.h"
#include "route_node.h"
#include "route_node_lmdb.h"
#include "topo_node.h"
#include "topo_node_lmdb.h"
#include "route_lib.h"
#include "route_bgp.h"
#include "topo_bgp.h"
#include "route_ping.h"
#include "route_connectivity.h"
#include "control_server.h"
@ -28,64 +28,64 @@
// Вспомогательные функции
// ============================================================================
static void route_bgp_send_table_request(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
static void topo_bgp_send_table_request(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) {
if (!bgp || !conn) return;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending table request to %s", conn->log_name);
struct BGP_ROUTE_REQUEST* req = u_calloc(1, sizeof(struct BGP_ROUTE_REQUEST));
struct TOPOMSG_TABLE_REQ* req = u_calloc(1, sizeof(struct TOPOMSG_TABLE_REQ));
if (!req) return;
req->cmd = ETCP_ID_ROUTE_ENTRY;
req->subcmd = ROUTE_SUBCMD_REQUEST_TABLE;
req->cmd = ETCP_ID_TOPO_ENTRY;
req->subcmd = TOPO_SUBCMD_REQUEST_TABLE;
struct ll_entry* e = queue_entry_new(0);
if (!e) { u_free(req); return; }
e->dgram = (uint8_t*)req; e->len = sizeof(struct BGP_ROUTE_REQUEST);
e->dgram = (uint8_t*)req; e->len = sizeof(struct TOPOMSG_TABLE_REQ);
if (etcp_send(conn, e) != 0) { u_free(req); queue_entry_free(e); }
}
static void route_bgp_send_table_complete(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
static void topo_bgp_send_table_complete(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) {
if (!bgp || !conn) return;
struct BGP_ROUTE_REQUEST* req = u_calloc(1, sizeof(struct BGP_ROUTE_REQUEST));
struct TOPOMSG_TABLE_REQ* req = u_calloc(1, sizeof(struct TOPOMSG_TABLE_REQ));
if (!req) return;
req->cmd = ETCP_ID_ROUTE_ENTRY;
req->subcmd = ROUTE_SUBCMD_TABLE_COMPLETE;
req->cmd = ETCP_ID_TOPO_ENTRY;
req->subcmd = TOPO_SUBCMD_TABLE_COMPLETE;
struct ll_entry* e = queue_entry_new(0);
if (!e) { u_free(req); return; }
e->dgram = (uint8_t*)req; e->len = sizeof(struct BGP_ROUTE_REQUEST);
e->dgram = (uint8_t*)req; e->len = sizeof(struct TOPOMSG_TABLE_REQ);
if (etcp_send(conn, e) != 0) { u_free(req); queue_entry_free(e); }
}
static void route_bgp_add_to_senders(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn);
static bool route_bgp_should_send_to(const struct NODEINFO_Q* nq, uint64_t target_id);
static void route_bgp_send_full_table(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn);
static void route_bgp_handle_request_table(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn);
static void topo_bgp_add_to_senders(struct TOPO_BGP* bgp, struct ETCP_CONN* conn);
static bool topo_bgp_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_bgp_handle_request_table(struct TOPO_BGP* bgp, struct ETCP_CONN* conn);
static void nodeinfo_dump_log(const uint8_t* data, size_t len) {
if (!data || len < sizeof(struct BGP_NODEINFO_PACKET)) return;
struct BGP_NODEINFO_PACKET* pkt = (struct BGP_NODEINFO_PACKET*)data;
struct NODEINFO_MSG* ni = &pkt->node;
if (!data || len < sizeof(struct TOPOMSG_NODEINFO_PKT)) return;
struct TOPOMSG_NODEINFO_PKT* pkt = (struct TOPOMSG_NODEINFO_PKT*)data;
struct TOPOMSG_NODE* ni = &pkt->node;
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "NODEINFO nid=%016llx ver=%u v4s=%u v4a=%u hops=%u",
(unsigned long long)ni->node_id, ni->ver,
ni->local_v4_sockets, ni->local_v4_addrs, ni->hop_count);
}
static char* nodeinfo_format(const uint8_t* data, size_t len) {
if (!data || len < sizeof(struct BGP_NODEINFO_PACKET)) return NULL;
struct BGP_NODEINFO_PACKET* pkt = (struct BGP_NODEINFO_PACKET*)data;
struct NODEINFO_MSG* ni = &pkt->node;
if (!data || len < sizeof(struct TOPOMSG_NODEINFO_PKT)) return NULL;
struct TOPOMSG_NODEINFO_PKT* pkt = (struct TOPOMSG_NODEINFO_PKT*)data;
struct TOPOMSG_NODE* ni = &pkt->node;
uint64_t node_id = ni->node_id;
const uint8_t* dyn = data + sizeof(struct BGP_NODEINFO_PACKET);
const uint8_t* dyn = data + sizeof(struct TOPOMSG_NODEINFO_PKT);
size_t off = 0;
char name_buf[64] = {0};
size_t nl = ni->node_name_len;
if (nl > 0 && nl < 63 && off + nl < len - sizeof(struct BGP_NODEINFO_PACKET)) {
if (nl > 0 && nl < 63 && off + nl < len - sizeof(struct TOPOMSG_NODEINFO_PKT)) {
memcpy(name_buf, dyn + off, nl); off += nl;
}
off += ni->local_v4_sockets * sizeof(struct NODEINFO_IPV4_SOCKET_META);
off += ni->local_v4_addrs * sizeof(struct NODEINFO_IPV4_ADDR);
off += ni->local_v6_sockets * sizeof(struct NODEINFO_IPV6_SOCKET_META);
off += ni->local_v6_addrs * sizeof(struct NODEINFO_IPV6_ADDR);
off += ni->local_v4_sockets * sizeof(struct TOPOMSG_SOCKMETA4);
off += ni->local_v4_addrs * sizeof(struct TOPOMSG_ADDR4);
off += ni->local_v6_sockets * sizeof(struct TOPOMSG_SOCKMETA6);
off += ni->local_v6_addrs * sizeof(struct TOPOMSG_ADDR6);
char subs_buf[512] = {0};
if (ni->local_v4_subnets > 0) {
const struct NODEINFO_IPV4_SUBNET* subs = (const struct NODEINFO_IPV4_SUBNET*)(dyn + off);
const struct TOPOMSG_SUBNET4* subs = (const struct TOPOMSG_SUBNET4*)(dyn + off);
size_t sl = 0;
for (uint8_t i = 0; i < ni->local_v4_subnets && sl < 400; i++) {
uint32_t addr = (subs[i].addr[0]<<24)|(subs[i].addr[1]<<16)|(subs[i].addr[2]<<8)|subs[i].addr[3];
@ -101,14 +101,14 @@ static char* nodeinfo_format(const uint8_t* data, size_t len) {
static const char* bgp_subcmd_name(uint8_t subcmd) {
switch (subcmd) {
case ROUTE_SUBCMD_NODEINFO: return "NODEINFO";
case ROUTE_SUBCMD_REQUEST_TABLE: return "REQ_TABLE";
case ROUTE_SUBCMD_WITHDRAW: return "WITHDRAW";
case ROUTE_SUBCMD_PING_REQ: return "PING_REQ";
case ROUTE_SUBCMD_PING_RESP: return "PING_RESP";
case ROUTE_SUBCMD_NAT_INFO: return "NAT_INFO";
case ROUTE_SUBCMD_NAT_CHECK_REQ: return "NAT_CHECK_REQ";
case ROUTE_SUBCMD_TABLE_COMPLETE: return "TABLE_COMPLETE";
case TOPO_SUBCMD_NODEINFO: return "NODEINFO";
case TOPO_SUBCMD_REQUEST_TABLE: return "REQ_TABLE";
case TOPO_SUBCMD_WITHDRAW: return "WITHDRAW";
case TOPO_SUBCMD_PING_REQ: return "PING_REQ";
case TOPO_SUBCMD_PING_RESP: return "PING_RESP";
case TOPO_SUBCMD_NAT_INFO: return "NAT_INFO";
case TOPO_SUBCMD_NAT_CHECK_REQ: return "NAT_CHECK_REQ";
case TOPO_SUBCMD_TABLE_COMPLETE: return "TABLE_COMPLETE";
default: return "?";
}
}
@ -118,15 +118,15 @@ static const char* bgp_subcmd_name(uint8_t subcmd) {
// Broadcast / Withdraw
// ============================================================================
static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id, uint64_t wd_source, struct ETCP_CONN* exclude) {
static void topo_bgp_broadcast_withdraw(struct TOPO_BGP* bgp, uint64_t node_id, uint64_t wd_source, struct ETCP_CONN* exclude) {
if (!bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "bgp is NULL"); return; }
struct BGP_WITHDRAW_PACKET* pkt = u_calloc(1, sizeof(struct BGP_WITHDRAW_PACKET));
struct TOPOMSG_WITHDRAW_PKT* pkt = u_calloc(1, sizeof(struct TOPOMSG_WITHDRAW_PKT));
if (!pkt) return;
pkt->cmd = ETCP_ID_ROUTE_ENTRY; pkt->subcmd = ROUTE_SUBCMD_WITHDRAW;
pkt->cmd = ETCP_ID_TOPO_ENTRY; pkt->subcmd = TOPO_SUBCMD_WITHDRAW;
pkt->node_id = node_id; pkt->wd_source = wd_source;
struct ll_entry* e = bgp->senders_list ? bgp->senders_list->head : NULL;
while (e) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data;
struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)e->data;
if (item && item->conn && item->conn != exclude) {
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); }
@ -141,27 +141,27 @@ static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id
// Приём пакетов
// ============================================================================
static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
static void route_bgp_handle_nat_check_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
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_bgp_handle_nat_check_req(struct TOPO_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry) {
static void topo_bgp_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; }
struct UTUN_INSTANCE* instance = from_conn->instance;
if (!instance || !instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_receive_cbk: invalid instance/bgp"); queue_dgram_free(entry); queue_entry_free(entry); return; }
struct ROUTE_BGP* bgp = instance->bgp;
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; }
struct TOPO_BGP* bgp = instance->bgp;
uint8_t* data = entry->dgram; uint8_t cmd = data[0]; uint8_t subcmd = data[1];
if (cmd != ETCP_ID_ROUTE_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);
if (subcmd == ROUTE_SUBCMD_NODEINFO) { nodeinfo_dump_log(data, entry->len); route_bgp_process_nodeinfo(bgp, from_conn, data, entry->len); }
else if (subcmd == ROUTE_SUBCMD_WITHDRAW) route_bgp_process_withdraw(bgp, from_conn, data, entry->len);
else if (subcmd == ROUTE_SUBCMD_REQUEST_TABLE) route_bgp_handle_request_table(bgp, from_conn);
else if (subcmd == ROUTE_SUBCMD_PING_REQ) route_ping_handle_req(bgp, from_conn, data, entry->len);
else if (subcmd == ROUTE_SUBCMD_PING_RESP) route_ping_handle_resp(bgp, from_conn, data, entry->len);
else if (subcmd == ROUTE_SUBCMD_NAT_INFO) route_bgp_handle_nat_info(bgp, from_conn, data, entry->len);
else if (subcmd == ROUTE_SUBCMD_NAT_CHECK_REQ) route_bgp_handle_nat_check_req(bgp, from_conn, data, entry->len);
else if (subcmd == ROUTE_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); }
if (subcmd == TOPO_SUBCMD_NODEINFO) { nodeinfo_dump_log(data, entry->len); topo_bgp_process_nodeinfo(bgp, 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_REQUEST_TABLE) topo_bgp_handle_request_table(bgp, 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_RESP) route_ping_handle_resp(bgp, 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_CHECK_REQ) topo_bgp_handle_nat_check_req(bgp, 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); }
queue_dgram_free(entry); queue_entry_free(entry);
}
@ -171,22 +171,22 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
// Init / Destroy / New / Remove conn
// ============================================================================
static void route_bgp_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); route_bgp_new_conn(conn); }
static void topo_bgp_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); }
}
static void route_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); route_bgp_remove_conn(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 route_bgp_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, route_bgp_on_conn_up, conn->instance->bgp); etcp_conn_add_down_cbk(conn, route_bgp_on_conn_down, conn->instance->bgp); }
static void topo_bgp_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); }
}
struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) {
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: instance is NULL"); return NULL; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_init: node_id=%016llx", (unsigned long long)instance->node_id);
struct TOPO_BGP* topo_bgp_init(struct UTUN_INSTANCE* instance) {
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_init: instance is NULL"); return NULL; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_bgp_init: node_id=%016llx", (unsigned long long)instance->node_id);
struct ROUTE_BGP* bgp = u_calloc(1, sizeof(struct ROUTE_BGP));
if (!bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: alloc failed"); return NULL; }
struct TOPO_BGP* bgp = u_calloc(1, sizeof(struct TOPO_BGP));
if (!bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_init: alloc failed"); return NULL; }
bgp->instance = instance;
bgp->ping_pending = NULL; bgp->next_ping_req_id = 1;
bgp->nodeinfo_env = NULL; bgp->nodeinfo_dbi = 0;
@ -194,46 +194,46 @@ struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) {
sc_derive_ed25519_pubkey(instance->my_keys.private_key, bgp->ed25519_public_key);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Ed25519 pubkey derived from X25519 private key");
if (instance->config && instance->config->global.db_path[0]) route_node_lmdb_init(bgp, instance->config->global.db_path);
if (instance->config && instance->config->global.db_path[0]) topo_node_lmdb_init(bgp, instance->config->global.db_path);
bgp->nodes = queue_new(instance->ua, BGP_NODES_HASH_SIZE, offsetof(struct NODEINFO_Q, hash_node_id) - sizeof(struct ll_entry), 8, "bgp_nodes");
if (!bgp->nodes) { u_free(bgp); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: 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");
if (!bgp->nodes) { u_free(bgp); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_init: nodes queue creation failed"); return NULL; }
bgp->senders_list = queue_new(instance->ua, 0, 0, 0, "BGP_senders");
if (!bgp->senders_list) { queue_free(bgp->nodes); u_free(bgp); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: senders_list queue creation failed"); return 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; }
bgp->v4_sock_meta_pool = memory_pool_init(sizeof(struct NI_IPV4_SOCKET_META), "ni_v4sock");
bgp->v4_addr_pool = memory_pool_init(sizeof(struct NI_IPV4_ADDR), "ni_v4addr");
bgp->v6_sock_meta_pool = memory_pool_init(sizeof(struct NI_IPV6_SOCKET_META), "ni_v6sock");
bgp->v6_addr_pool = memory_pool_init(sizeof(struct NI_IPV6_ADDR), "ni_v6addr");
bgp->v4_subnet_pool = memory_pool_init(sizeof(struct NI_IPV4_SUBNET), "ni_v4sub");
bgp->v6_subnet_pool = memory_pool_init(sizeof(struct NI_IPV6_SUBNET), "ni_v6sub");
bgp->v4_sock_meta_pool = memory_pool_init(sizeof(struct TOPO_SOCKMETA4), "to_v4sock");
bgp->v4_addr_pool = memory_pool_init(sizeof(struct TOPO_ADDR4), "to_v4addr");
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;
route_bgp_update_my_nodeinfo(instance, bgp);
topo_bgp_update_my_nodeinfo(instance, bgp);
etcp_bind(instance, ETCP_ID_ROUTE_ENTRY, route_bgp_receive_cbk);
etcp_add_new_conn_cbk(instance, route_bgp_etcp_conn_cbk, NULL);
etcp_bind(instance, ETCP_ID_TOPO_ENTRY, topo_bgp_receive_cbk);
etcp_add_new_conn_cbk(instance, topo_bgp_etcp_conn_cbk, NULL);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP module initialized (NODEINFO based routing)");
DEBUG_INFO(DEBUG_CATEGORY_BGP, "TOPO BGP module initialized");
return bgp;
}
void route_bgp_destroy(struct UTUN_INSTANCE* instance) {
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_destroy: instance is NULL"); return; }
if (!instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_destroy: bgp is NULL"); return; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_destroy: node_id=%016llx", (unsigned long long)instance->node_id);
void topo_bgp_destroy(struct UTUN_INSTANCE* instance) {
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_destroy: instance is NULL"); return; }
if (!instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_destroy: bgp is NULL"); return; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_bgp_destroy: node_id=%016llx", (unsigned long long)instance->node_id);
etcp_unbind(instance, ETCP_ID_ROUTE_ENTRY);
etcp_unbind(instance, ETCP_ID_TOPO_ENTRY);
route_connectivity_cancel_all(instance);
struct ll_entry* e;
while ((e = queue_data_get(instance->bgp->senders_list)) != NULL) queue_entry_free(e);
queue_free(instance->bgp->senders_list);
if (instance->bgp->local_node) { nodeinfo_free_lists(instance->bgp, instance->bgp->local_node); u_free(instance->bgp->local_node); }
if (instance->bgp->local_node) { topo_node_free_lists(instance->bgp, instance->bgp->local_node); u_free(instance->bgp->local_node); }
route_node_lmdb_destroy(instance->bgp);
topo_node_lmdb_destroy(instance->bgp);
if (instance->bgp->nodes) queue_free(instance->bgp->nodes);
@ -247,36 +247,36 @@ void route_bgp_destroy(struct UTUN_INSTANCE* instance) {
u_free(instance->bgp); instance->bgp = NULL;
}
void route_bgp_set_nat_check_local(struct ROUTE_BGP* bgp, int allow) { if (!bgp) return; bgp->allow_nat_check_local = allow ? 1 : 0; }
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 route_bgp_new_conn(struct ETCP_CONN* conn) {
if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn is NULL"); return; }
if (!conn->instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn->instance is NULL"); return; }
if (!conn->instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn->instance->bgp is NULL"); return; }
if (!conn->instance->rt) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn->instance->rt is NULL"); return; }
void topo_bgp_new_conn(struct ETCP_CONN* conn) {
if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_new_conn: conn is NULL"); return; }
if (!conn->instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_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_bgp_new_conn: conn->instance->rt is NULL"); return; }
struct ROUTE_BGP* bgp = conn->instance->bgp;
struct NODEINFO_Q* peer_nq = nodeinfo_find_by_id(bgp, conn->peer_node_id);
route_bgp_add_to_senders(bgp, conn);
if (peer_nq && peer_nq->alien) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: peer 0x%016llx is alien, skipping route exchange", (unsigned long long)conn->peer_node_id); return; }
struct TOPO_BGP* bgp = conn->instance->bgp;
struct TOPO_NODEQ* peer_nq = topo_node_find_by_id(bgp, conn->peer_node_id);
topo_bgp_add_to_senders(bgp, conn);
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;
while (c) { struct ETCP_LINK* l = c->links; while (l) { if (l->initialized && l->conn && l->nat_check_status < NAT_CHECK_IN_PROGRESS) route_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_bgp_start_link_nat_check(bgp, l); l = l->next; } c = c->next; }
route_bgp_send_table_request(bgp, conn);
topo_bgp_send_table_request(bgp, conn);
}
void route_bgp_remove_conn(struct ETCP_CONN* conn) {
if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: conn is NULL"); return; }
if (!conn->instance || !conn->instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: invalid instance/bgp"); return; }
struct ROUTE_BGP* bgp = conn->instance->bgp;
void topo_bgp_remove_conn(struct ETCP_CONN* conn) {
if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_remove_conn: conn is NULL"); return; }
if (!conn->instance || !conn->instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_remove_conn: invalid instance/bgp"); return; }
struct TOPO_BGP* bgp = conn->instance->bgp;
bool found_in_list = false;
struct ll_entry* e = bgp->senders_list->head;
while (e) { struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_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, "route_bgp_remove_conn: conn already removed or not in list, skipping"); return; }
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; }
if (!found_in_list) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "topo_bgp_remove_conn: conn already removed or not in list, skipping"); return; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: peer=%016llx", (unsigned long long)conn->peer_node_id);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_bgp_remove_conn: peer=%016llx", (unsigned long long)conn->peer_node_id);
route_ping_cancel_for_conn(bgp, 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; }
@ -286,46 +286,46 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) {
struct ll_entry* node_entry = bgp->nodes ? bgp->nodes->head : NULL;
while (node_entry) {
struct ll_entry* next = node_entry->next;
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)node_entry;
if (route_bgp_remove_path(nq, conn) == 1) {
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)node_entry;
if (topo_bgp_remove_path(nq, conn) == 1) {
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);
nq->dirty = 1;
route_connectivity_cancel_node(conn->instance, nq);
if (nq->paths) { queue_free(nq->paths); nq->paths = NULL; }
uint64_t key = nq->hash_node_id;
nodeinfo_free_lists(bgp, nq);
topo_node_free_lists(bgp, nq);
struct ll_entry* entry = node_entry;
if (entry) { queue_remove_data(bgp->nodes, entry); queue_entry_free(entry); }
nodes_removed++;
etcp_router_conn_close_all_for_node(bgp->instance, key);
uint64_t wd_src = (key == conn->peer_node_id) ? conn->instance->node_id : conn->peer_node_id;
route_bgp_broadcast_withdraw(bgp, key, wd_src, NULL);
topo_bgp_broadcast_withdraw(bgp, key, wd_src, NULL);
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Removed node %016llx after link down", (unsigned long long)key);
}
node_entry = next;
}
e = bgp->senders_list->head;
while (e) { struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_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_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; }
DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer removed: %s nodes=%d", conn->log_name, nodes_removed);
}
// ============================================================================
// NEW NODEINFO BASED IMPLEMENTATION
// NODEINFO BASED IMPLEMENTATION
// ============================================================================
struct ETCP_CONN* route_bgp_find_conn_for_node(struct ROUTE_BGP* bgp, uint64_t node_id) {
struct ETCP_CONN* topo_bgp_find_conn_for_node(struct TOPO_BGP* bgp, uint64_t node_id) {
if (!bgp) return NULL;
struct NODEINFO_Q* nq = nodeinfo_find_by_id(bgp, node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, node_id);
if (!nq || !nq->paths || !nq->paths->head) return NULL;
struct ll_entry* e = nq->paths->head;
struct NODEINFO_PATH* best_live = NULL; uint8_t best_live_hops = 255;
struct NODEINFO_PATH* best_any = NULL; uint8_t best_any_hops = 255;
struct TOPO_NODEPATH* best_live = NULL; uint8_t best_live_hops = 255;
struct TOPO_NODEPATH* best_any = NULL; uint8_t best_any_hops = 255;
while (e) {
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e;
struct TOPO_NODEPATH* path = (struct TOPO_NODEPATH*)e;
if (path->conn) { if (path->conn->links_up && path->hop_count < best_live_hops) { best_live = path; best_live_hops = path->hop_count; } if (path->hop_count < best_any_hops) { best_any = path; best_any_hops = path->hop_count; } }
e = e->next;
}
@ -333,25 +333,25 @@ struct ETCP_CONN* route_bgp_find_conn_for_node(struct ROUTE_BGP* bgp, uint64_t n
return best_live ? best_live->conn : (best_any ? best_any->conn : NULL);
}
int route_bgp_add_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count) {
int topo_bgp_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->paths) { nq->paths = queue_new(conn->instance->ua, 0, 0, 0, "node_paths"); if (!nq->paths) return -1; }
size_t path_size = sizeof(struct NODEINFO_PATH) - sizeof(struct ll_entry) + hop_count * 8;
size_t path_size = sizeof(struct TOPO_NODEPATH) - sizeof(struct ll_entry) + hop_count * 8;
struct ll_entry* pe = queue_entry_new(path_size); if (!pe) return -1;
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)pe;
struct TOPO_NODEPATH* path = (struct TOPO_NODEPATH*)pe;
path->conn = conn; path->hop_count = hop_count;
memcpy((uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH)), hop_list, hop_count * 8);
memcpy((uint64_t*)((uint8_t*)path + sizeof(struct TOPO_NODEPATH)), hop_list, hop_count * 8);
queue_data_put(nq->paths, pe);
return 0;
}
int route_bgp_remove_path_by_hop(struct NODEINFO_Q* nq, uint64_t wd_source) {
int topo_bgp_remove_path_by_hop(struct TOPO_NODEQ* nq, uint64_t wd_source) {
if (!nq || !nq->paths) return 0;
int removed = 0;
struct ll_entry* e = nq->paths->head;
while (e) {
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e;
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH));
struct TOPO_NODEPATH* path = (struct TOPO_NODEPATH*)e;
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct TOPO_NODEPATH));
bool has_wd = false; for (uint8_t i = 0; i < path->hop_count; i++) if (hop[i] == wd_source) { has_wd = true; break; }
if (has_wd) { struct ll_entry* next = e->next; queue_remove_data(nq->paths, e); queue_entry_free(e); removed++; e = next; continue; }
e = e->next;
@ -360,10 +360,10 @@ int route_bgp_remove_path_by_hop(struct NODEINFO_Q* nq, uint64_t wd_source) {
return removed;
}
int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn) {
int topo_bgp_remove_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn) {
if (!nq || !conn || !nq->paths) return -1;
struct ll_entry* e = nq->paths->head;
while (e) { struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)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; }
int remaining = nq->paths ? queue_entry_count(nq->paths) : 0;
if (remaining == 0) { if (nq->paths) { queue_free(nq->paths); nq->paths = NULL; } return 1; }
return 0;
@ -378,29 +378,24 @@ 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; }
link->nat_type = success ? NAT_TYPE_EIM : NAT_TYPE_STRICT;
link->nat_check_status = success ? NAT_CHECK_EIM : NAT_CHECK_STRICT;
if (link->etcp) route_bgp_send_nat_info(link->etcp, link->remote_socket_id, na->nat_ip, na->nat_port, link->nat_type);
if (link->etcp) topo_bgp_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);
u_free(na);
}
static struct ETCP_CONN* route_bgp_find_third_node(struct ROUTE_BGP* bgp, struct ETCP_CONN* exclude) {
static struct ETCP_CONN* topo_bgp_find_third_node(struct TOPO_BGP* bgp, struct ETCP_CONN* exclude) {
if (!bgp || !bgp->senders_list) return NULL;
struct ll_entry* e = bgp->senders_list->head;
while (e) { struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_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_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; }
return NULL;
}
static void route_bgp_extract_nat_addr(struct ETCP_CONN* conn, uint32_t* nat_ip, uint16_t* nat_port) {
*nat_ip = 0; *nat_port = 0; if (!conn) return;
struct ETCP_LINK* l = conn->links; while (l) { if (l->nat_ip != 0) { *nat_ip = l->nat_ip; *nat_port = l->nat_port; return; } l = l->next; }
}
void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* link) {
void topo_bgp_start_link_nat_check(struct TOPO_BGP* bgp, struct ETCP_LINK* link) {
if (!bgp || !link || !link->conn || !link->etcp) return;
if (link->nat_type == NAT_TYPE_DIRECT) 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; }
struct ETCP_CONN* third_conn = route_bgp_find_third_node(bgp, link->etcp);
struct ETCP_CONN* third_conn = topo_bgp_find_third_node(bgp, link->etcp);
if (!third_conn) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "no third node found for link"); return; }
uint32_t target_ip; uint16_t target_port;
@ -420,30 +415,30 @@ void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* lin
// ===== NODEINFO process =====
int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, const uint8_t* data, size_t len) {
if (!bgp || !from || len < sizeof(struct BGP_NODEINFO_PACKET)) return -1;
int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, const uint8_t* data, size_t len) {
if (!bgp || !from || len < sizeof(struct TOPOMSG_NODEINFO_PKT)) return -1;
struct BGP_NODEINFO_PACKET* pkt = (struct BGP_NODEINFO_PACKET*)data;
struct NODEINFO_MSG* ni = &pkt->node;
int dyn = nodeinfo_dyn_size(ni);
if ((size_t)dyn + sizeof(struct BGP_NODEINFO_PACKET) != len) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "Incorrect packet size (%s)", from->log_name); return -1; }
struct TOPOMSG_NODEINFO_PKT* pkt = (struct TOPOMSG_NODEINFO_PKT*)data;
struct TOPOMSG_NODE* ni = &pkt->node;
int dyn = topo_node_dyn_size(ni);
if ((size_t)dyn + sizeof(struct TOPOMSG_NODEINFO_PKT) != len) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "Incorrect packet size (%s)", from->log_name); return -1; }
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 (node_id == bgp->instance->node_id) return 0;
struct NODEINFO_Q* nodeinfo1 = nodeinfo_find_by_id(bgp, node_id);
struct TOPO_NODEQ* nodeinfo1 = topo_node_find_by_id(bgp, node_id);
uint8_t new_ver = ni->ver;
if (nodeinfo1 && (int8_t)(nodeinfo1->last_ver - new_ver) >= 0) {
int new_hops = ni->hop_count + 1;
if (new_hops <= MAX_HOPS) {
uint64_t hop_list[MAX_HOPS];
const uint8_t* hop_src = (const uint8_t*)ni + sizeof(struct NODEINFO_MSG) + 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);
hop_list[ni->hop_count] = from->peer_node_id;
route_bgp_remove_path(nodeinfo1, from);
route_bgp_add_path(nodeinfo1, from, hop_list, new_hops);
topo_bgp_remove_path(nodeinfo1, from);
topo_bgp_add_path(nodeinfo1, from, hop_list, new_hops);
}
return 0;
}
@ -455,39 +450,39 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co
struct ll_queue* paths = NULL;
int is_new_node = 0;
if (nodeinfo1) {
nodeinfo_free_lists(bgp, nodeinfo1);
topo_node_free_lists(bgp, nodeinfo1);
paths = nodeinfo1->paths; nodeinfo1->paths = NULL;
} else { is_new_node = 1; }
// deserialize from protocol
const uint8_t* ser_data = data + 2;
size_t ser_len = len - 2;
struct NODEINFO* new_ni = NULL;
struct NODEINFO_ROUTES* new_routes = NULL;
struct NODEINFO_TRANZIT_NODE* new_tranzit = NULL; uint8_t new_tranzit_count = 0;
struct TOPO_NODE* new_ni = NULL;
struct TOPO_NODESUBNETS* new_subnets = NULL;
struct TOPOMSG_TRANZIT* new_tranzit = NULL; uint8_t new_tranzit_count = 0;
uint64_t* new_hop_list = NULL; uint8_t new_hop_count = 0;
if (nodeinfo_deserialize(bgp, ser_data, ser_len, &new_ni, &new_routes, &new_tranzit, &new_tranzit_count, &new_hop_list, &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) {
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); }
return -1;
}
if (nodeinfo1) {
nodeinfo1->node = new_ni; nodeinfo_ref(new_ni);
nodeinfo1->node = new_ni; topo_node_ref(new_ni);
nodeinfo1->hash_node_id = new_ni->node_id;
nodeinfo1->routes = new_routes;
nodeinfo1->subnets = new_subnets;
u_free(nodeinfo1->tranzit_data); nodeinfo1->tranzit_data = new_tranzit;
nodeinfo1->tranzit_count = new_tranzit_count;
u_free(nodeinfo1->hop_list); nodeinfo1->hop_list = new_hop_list;
nodeinfo1->hop_count = new_hop_count;
} else {
struct ll_entry* qe = queue_entry_new(sizeof(struct NODEINFO_Q));
if (!qe) { nodeinfo_unref(new_ni); u_free(new_tranzit); u_free(new_hop_list); u_free(new_routes); return -1; }
nodeinfo1 = (struct NODEINFO_Q*)qe;
struct ll_entry* qe = queue_entry_new(sizeof(struct TOPO_NODEQ));
if (!qe) { topo_node_unref(new_ni); u_free(new_tranzit); u_free(new_hop_list); u_free(new_subnets); return -1; }
nodeinfo1 = (struct TOPO_NODEQ*)qe;
memset((uint8_t*)nodeinfo1 + sizeof(struct ll_entry), 0, sizeof(*nodeinfo1) - sizeof(struct ll_entry));
nodeinfo1->node = new_ni; nodeinfo_ref(new_ni);
nodeinfo1->node = new_ni; topo_node_ref(new_ni);
nodeinfo1->hash_node_id = new_ni->node_id;
nodeinfo1->routes = new_routes;
nodeinfo1->subnets = new_subnets;
nodeinfo1->tranzit_data = new_tranzit; nodeinfo1->tranzit_count = new_tranzit_count;
nodeinfo1->hop_list = new_hop_list; nodeinfo1->hop_count = new_hop_count;
nodeinfo1->connectivity.probe_status = PROBE_STATUS_NONE;
@ -511,22 +506,22 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co
nodeinfo1->hop_list = u_malloc(nodeinfo1->hop_count * 8);
memcpy(nodeinfo1->hop_list, hop_list, nodeinfo1->hop_count * 8);
route_bgp_remove_path_by_hop(nodeinfo1, from->peer_node_id);
route_bgp_add_path(nodeinfo1, from, hop_list, nodeinfo1->hop_count);
topo_bgp_remove_path_by_hop(nodeinfo1, from->peer_node_id);
topo_bgp_add_path(nodeinfo1, from, hop_list, nodeinfo1->hop_count);
if (bgp->instance->rt) route_insert(bgp->instance->rt, nodeinfo1);
if (node_id != bgp->instance->node_id) route_node_lmdb_put(bgp, nodeinfo1);
if (node_id != bgp->instance->node_id) topo_node_lmdb_put(bgp, nodeinfo1);
if (bgp->instance->control_srv) control_server_notify_node_change(bgp->instance->control_srv, nodeinfo1);
int hop_count = nodeinfo1->hop_count;
struct ll_entry* se = bgp->senders_list ? bgp->senders_list->head : NULL;
while (se) {
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data;
struct TOPO_BGP_CONN_ITEM* item = (struct TOPO_BGP_CONN_ITEM*)se->data;
if (item->conn) {
uint64_t id = item->conn->peer_node_id;
if (id != node_id) {
int found = 0; for (int i = 0; i < hop_count; i++) if (hop_list[i] == id) found = 1;
if (found == 0) route_bgp_send_nodeinfo(nodeinfo1, item->conn);
if (found == 0) topo_bgp_send_nodeinfo(nodeinfo1, item->conn);
}
}
se = se->next;
@ -536,46 +531,46 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co
if (!is_new_node) socks_changed = 1;
if (node_id != bgp->instance->node_id && (is_new_node || socks_changed)) {
int v4a = ni_list_count((struct _ni_head*)nodeinfo1->node->v4_addrs);
int v6a = ni_list_count((struct _ni_head*)nodeinfo1->node->v6_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);
if (v4a > 0 || v6a > 0) route_connectivity_probe_node(bgp->instance, nodeinfo1);
}
return 0;
}
int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len) {
if (!bgp || len < sizeof(struct BGP_WITHDRAW_PACKET)) return -1;
struct BGP_WITHDRAW_PACKET* wp = (struct BGP_WITHDRAW_PACKET*)data;
int topo_bgp_process_withdraw(struct TOPO_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len) {
if (!bgp || len < sizeof(struct TOPOMSG_WITHDRAW_PKT)) return -1;
struct TOPOMSG_WITHDRAW_PKT* wp = (struct TOPOMSG_WITHDRAW_PKT*)data;
uint64_t node_id = wp->node_id, wd_source = wp->wd_source;
struct NODEINFO_Q* nq = nodeinfo_find_by_id(bgp, node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(bgp, node_id);
if (!nq) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "node not found"); return 0; }
int ret = route_bgp_remove_path_by_hop(nq, wd_source);
int ret = topo_bgp_remove_path_by_hop(nq, wd_source);
if (ret == 1) {
if (bgp->instance && bgp->instance->rt) route_delete(bgp->instance->rt, nq);
if (bgp->instance->control_srv) control_server_notify_node_removed(bgp->instance->control_srv, node_id);
nq->dirty = 1;
route_connectivity_cancel_node(bgp->instance, nq);
if (nq->paths) { queue_free(nq->paths); nq->paths = NULL; }
nodeinfo_free_lists(bgp, nq);
topo_node_free_lists(bgp, nq);
struct ll_entry* entry = queue_find_data_by_index(bgp->nodes, &node_id);
if (entry) { queue_remove_data(bgp->nodes, entry); queue_entry_free(entry); }
route_bgp_broadcast_withdraw(bgp, node_id, wd_source, sender);
topo_bgp_broadcast_withdraw(bgp, node_id, wd_source, sender);
}
return 0;
}
void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn) {
void topo_bgp_send_nodeinfo(struct TOPO_NODEQ* node, struct ETCP_CONN* conn) {
if (!node || !conn) return;
size_t max_sz = sizeof(struct BGP_NODEINFO_PACKET) + 4096;
size_t max_sz = sizeof(struct TOPOMSG_NODEINFO_PKT) + 4096;
uint8_t* p = u_malloc(max_sz);
if (!p) return;
p[0] = ETCP_ID_ROUTE_ENTRY; p[1] = ROUTE_SUBCMD_NODEINFO;
p[0] = ETCP_ID_TOPO_ENTRY; p[1] = TOPO_SUBCMD_NODEINFO;
int ser_len = nodeinfo_serialize(conn->instance->bgp, node, p + 2, max_sz - 2);
int ser_len = topo_node_serialize(conn->instance->bgp, node, p + 2, max_sz - 2);
if (ser_len < 0) { u_free(p); return; }
struct ll_entry* e = queue_entry_new(0);
@ -585,24 +580,24 @@ void route_bgp_send_nodeinfo(struct NODEINFO_Q* 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); }
}
static void route_bgp_add_to_senders(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
static void topo_bgp_add_to_senders(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) {
if (!bgp || !conn || !bgp->senders_list) return;
bool already = false;
struct ll_entry* e = bgp->senders_list->head;
while (e) { if (((struct ROUTE_BGP_CONN_ITEM*)e->data)->conn == conn) { already = true; break; } e = e->next; }
while (e) { if (((struct TOPO_BGP_CONN_ITEM*)e->data)->conn == conn) { already = true; break; } e = e->next; }
if (!already) {
struct ll_entry* item_entry = queue_entry_new(sizeof(struct ROUTE_BGP_CONN_ITEM));
if (item_entry) { ((struct ROUTE_BGP_CONN_ITEM*)item_entry->data)->conn = conn; queue_data_put(bgp->senders_list, item_entry); }
struct ll_entry* item_entry = queue_entry_new(sizeof(struct TOPO_BGP_CONN_ITEM));
if (item_entry) { ((struct TOPO_BGP_CONN_ITEM*)item_entry->data)->conn = conn; queue_data_put(bgp->senders_list, item_entry); }
}
}
static bool route_bgp_should_send_to(const struct NODEINFO_Q* nq, uint64_t target_id) {
static bool topo_bgp_should_send_to(const struct TOPO_NODEQ* nq, uint64_t target_id) {
if (!nq || !nq->node || !nq->paths) return false;
if (target_id == nq->node->node_id) return false;
struct ll_entry* e = nq->paths->head;
while (e) {
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e;
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH));
struct TOPO_NODEPATH* path = (struct TOPO_NODEPATH*)e;
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct TOPO_NODEPATH));
bool has_id = false; for (uint8_t i = 0; i < path->hop_count; i++) if (hop[i] == target_id) { has_id = true; break; }
if (!has_id) return true;
e = e->next;
@ -610,31 +605,31 @@ static bool route_bgp_should_send_to(const struct NODEINFO_Q* nq, uint64_t targe
return false;
}
static void route_bgp_send_full_table(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
static void topo_bgp_send_full_table(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) {
if (!bgp || !conn) return;
uint64_t target = conn->peer_node_id;
struct ll_entry* e = bgp->nodes ? bgp->nodes->head : NULL;
while (e) {
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e;
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
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 (route_bgp_should_send_to(nq, target)) route_bgp_send_nodeinfo(nq, conn);
if (topo_bgp_should_send_to(nq, target)) topo_bgp_send_nodeinfo(nq, conn);
e = e->next;
}
}
static void route_bgp_handle_request_table(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) {
static void topo_bgp_handle_request_table(struct TOPO_BGP* bgp, struct ETCP_CONN* conn) {
if (!bgp || !conn) return;
route_bgp_send_nodeinfo(bgp->local_node, conn);
route_bgp_send_full_table(bgp, conn);
route_bgp_add_to_senders(bgp, conn);
route_bgp_send_table_complete(bgp, conn);
topo_bgp_send_nodeinfo(bgp->local_node, conn);
topo_bgp_send_full_table(bgp, conn);
topo_bgp_add_to_senders(bgp, conn);
topo_bgp_send_table_complete(bgp, conn);
}
static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
if (!bgp || !from_conn || !data || len < sizeof(struct BGP_NAT_INFO) || !bgp->local_node || !bgp->local_node->node) return;
static void topo_bgp_handle_nat_info(struct TOPO_BGP* bgp, 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;
const struct BGP_NAT_INFO* info = (const struct BGP_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];
uint16_t nat_port = ntohs(info->nat_port); uint8_t socket_id = info->socket_id;
@ -645,7 +640,7 @@ static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* f
else verified_type = NAT_VERIFIED_UNKNOWN;
int data_changed = 0;
{ struct NI_IPV4_SOCKET_META* 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 = 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 ETCP_SOCKET* es = bgp->instance->etcp_sockets;
while (es) { if (es->sock_id == socket_id) {
@ -654,58 +649,58 @@ static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* f
es = es->next; }
if (data_changed) {
int prev_v4a = ni_list_count((struct _ni_head*)bgp->local_node->node->v4_addrs);
route_bgp_update_my_nodeinfo(bgp->instance, bgp);
if (ni_list_count((struct _ni_head*)bgp->local_node->node->v4_addrs) != prev_v4a) {
int prev_v4a = topo_list_count((struct _topo_head*)bgp->local_node->node->v4_addrs);
topo_bgp_update_my_nodeinfo(bgp->instance, bgp);
if (topo_list_count((struct _topo_head*)bgp->local_node->node->v4_addrs) != prev_v4a) {
bgp->local_node->dirty = 1;
bgp->local_node->node->ver = (bgp->local_node->node->ver % 255) + 1;
bgp->local_node->last_ver = bgp->local_node->node->ver;
}
if (bgp->local_node->dirty && bgp->senders_list) {
struct ll_entry* se = bgp->senders_list->head;
while (se) { struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data; if (item && item->conn) route_bgp_send_nodeinfo(bgp->local_node, item->conn); se = se->next; }
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; }
}
}
struct ETCP_LINK* l = from_conn->links; while (l) { l->nat_type = info->nat_type; l = l->next; }
}
static void route_bgp_handle_nat_check_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
if (!bgp || !from_conn || !data || len < sizeof(struct BGP_NAT_CHECK_REQ)) return;
const struct BGP_NAT_CHECK_REQ* req = (const struct BGP_NAT_CHECK_REQ*)data;
static void topo_bgp_handle_nat_check_req(struct TOPO_BGP* bgp, 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;
const struct TOPOMSG_NAT_CHECK_REQ* req = (const struct TOPOMSG_NAT_CHECK_REQ*)data;
uint8_t socket_id = req->socket_id;
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; }
if (!target_link) return;
if (target_link->nat_check_status == NAT_CHECK_IN_PROGRESS) return;
route_bgp_start_link_nat_check(bgp, target_link);
topo_bgp_start_link_nat_check(bgp, target_link);
}
void route_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_bgp_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;
struct BGP_NAT_INFO* pkt = u_calloc(1, sizeof(struct BGP_NAT_INFO)); if (!pkt) return;
pkt->cmd = ETCP_ID_ROUTE_ENTRY; pkt->subcmd = ROUTE_SUBCMD_NAT_INFO;
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->socket_id = socket_id;
pkt->nat_ip[0] = (nat_ip >> 24) & 0xFF; pkt->nat_ip[1] = (nat_ip >> 16) & 0xFF;
pkt->nat_ip[2] = (nat_ip >> 8) & 0xFF; pkt->nat_ip[3] = nat_ip & 0xFF;
pkt->nat_port = htons(nat_port); pkt->nat_type = nat_type;
struct ll_entry* e = queue_entry_new(0); if (!e) { u_free(pkt); return; }
e->dgram = (uint8_t*)pkt; e->len = sizeof(struct BGP_NAT_INFO);
e->dgram = (uint8_t*)pkt; e->len = sizeof(struct TOPOMSG_NAT_INFO);
if (etcp_send(conn, e) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NAT_INFO failed"); u_free(pkt); queue_entry_free(e); }
}
void route_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id) {
void topo_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id) {
if (!conn) return;
struct BGP_NAT_CHECK_REQ* pkt = u_calloc(1, sizeof(struct BGP_NAT_CHECK_REQ)); if (!pkt) return;
pkt->cmd = ETCP_ID_ROUTE_ENTRY; pkt->subcmd = ROUTE_SUBCMD_NAT_CHECK_REQ; pkt->socket_id = socket_id;
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;
struct ETCP_LINK* l = conn->links; while (l) { if (l->remote_socket_id == socket_id) { struct sockaddr_in* sin = (struct sockaddr_in*)&l->conn->interface_addr; if (sin->sin_family == AF_INET) { pkt->interface_ip = sin->sin_addr.s_addr; pkt->interface_port = sin->sin_port; } break; } l = l->next; }
struct ll_entry* e = queue_entry_new(0); if (!e) { u_free(pkt); return; }
e->dgram = (uint8_t*)pkt; e->len = sizeof(struct BGP_NAT_CHECK_REQ);
e->dgram = (uint8_t*)pkt; e->len = sizeof(struct TOPOMSG_NAT_CHECK_REQ);
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 route_bgp_request_nat_check_all(struct ROUTE_BGP* bgp) {
void topo_bgp_request_nat_check_all(struct TOPO_BGP* bgp) {
if (!bgp || !bgp->instance) return;
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) route_bgp_start_link_nat_check(bgp, link); count++; link = link->next; } conn = conn->next; }
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; }
}

90
src/route_bgp.h → src/topo_bgp.h

@ -1,5 +1,5 @@
#ifndef ROUTE_BGP_H
#define ROUTE_BGP_H
#ifndef TOPO_BGP_H
#define TOPO_BGP_H
#ifdef __cplusplus
extern "C" {
@ -12,20 +12,20 @@ extern "C" {
#include "../lib/memory_pool.h"
#include "../lib/liblmdb/lmdb.h"
#include "route_lib.h"
#include "route_node.h"
#include "topo_node.h"
#include "secure_channel.h"
// ETCP ID для маршрутных пакетов
#define ETCP_ID_ROUTE_ENTRY 0x01
// ETCP ID для пакетов топологии
#define ETCP_ID_TOPO_ENTRY 0x01
// Sub-команды
#define ROUTE_SUBCMD_NODEINFO 0x04 // полная информация об узле + маршруты
#define ROUTE_SUBCMD_REQUEST_TABLE 0x05 // запрос полной таблицы
#define ROUTE_SUBCMD_WITHDRAW 0x06 // узел стал недоступен
#define ROUTE_SUBCMD_NAT_INFO 0x09 // информация о типе NAT клиента
#define ROUTE_SUBCMD_NAT_CHECK_REQ 0x0A // запрос от клиента на проверку NAT для сокета
#define ROUTE_SUBCMD_TABLE_COMPLETE 0x0B // завершение начальной синхронизации таблицы
#define TOPO_SUBCMD_NODEINFO 0x04 // полная информация об узле + подсети
#define TOPO_SUBCMD_REQUEST_TABLE 0x05 // запрос полной таблицы
#define TOPO_SUBCMD_WITHDRAW 0x06 // узел стал недоступен
#define TOPO_SUBCMD_NAT_INFO 0x09 // информация о типе NAT клиента
#define TOPO_SUBCMD_NAT_CHECK_REQ 0x0A // запрос от клиента на проверку NAT для сокета
#define TOPO_SUBCMD_TABLE_COMPLETE 0x0B // завершение начальной синхронизации таблицы
#define MAX_HOPS 16
#define BGP_NODES_HASH_SIZE 256
@ -33,16 +33,16 @@ extern "C" {
/**
* @brief Пакет с информацией об узле (NODEINFO)
*/
struct BGP_NODEINFO_PACKET {
uint8_t cmd; // ETCP_ID_ROUTE_ENTRY
uint8_t subcmd; // ROUTE_SUBCMD_NODEINFO
struct NODEINFO_MSG node;
struct TOPOMSG_NODEINFO_PKT {
uint8_t cmd; // ETCP_ID_TOPO_ENTRY
uint8_t subcmd; // TOPO_SUBCMD_NODEINFO
struct TOPOMSG_NODE node;
} __attribute__((packed));
/**
* @brief Пакет WITHDRAW (фиксированный)
*/
struct BGP_WITHDRAW_PACKET {
struct TOPOMSG_WITHDRAW_PKT {
uint8_t cmd;
uint8_t subcmd;
uint64_t node_id; // удаляемый узел (который стал недоступен)
@ -52,12 +52,12 @@ struct BGP_WITHDRAW_PACKET {
/**
* @brief Пакет запроса полной таблицы
*/
struct BGP_ROUTE_REQUEST {
struct TOPOMSG_TABLE_REQ {
uint8_t cmd;
uint8_t subcmd;
} __attribute__((packed));
struct ROUTE_BGP_CONN_ITEM {
struct TOPO_BGP_CONN_ITEM {
struct ll_entry ll;
struct ETCP_CONN* conn;
};
@ -65,7 +65,7 @@ struct ROUTE_BGP_CONN_ITEM {
/**
* @brief Пакет NAT_INFO (фиксированный)
*/
struct BGP_NAT_INFO {
struct TOPOMSG_NAT_INFO {
uint8_t cmd;
uint8_t subcmd;
uint8_t socket_id; // MY socket id (link->conn->sock_id)
@ -77,9 +77,9 @@ struct BGP_NAT_INFO {
/**
* @brief Пакет запроса на проверку NAT от клиента к серверу
*/
struct BGP_NAT_CHECK_REQ {
struct TOPOMSG_NAT_CHECK_REQ {
uint8_t cmd;
uint8_t subcmd; // ROUTE_SUBCMD_NAT_CHECK_REQ
uint8_t subcmd; // TOPO_SUBCMD_NAT_CHECK_REQ
uint8_t socket_id; // ID сокета клиента, который надо проверить
uint32_t interface_ip; // interface_addr IP клиента (network byte order)
uint16_t interface_port; // interface_addr port клиента (network byte order)
@ -88,11 +88,11 @@ struct BGP_NAT_CHECK_REQ {
struct route_ping_pending;
struct ETCP_LINK;
struct ROUTE_BGP {
struct TOPO_BGP {
struct UTUN_INSTANCE* instance;
struct ll_queue* senders_list;
struct ll_queue* nodes;
struct NODEINFO_Q* local_node;
struct TOPO_NODEQ* local_node;
struct route_ping_pending* ping_pending;
uint32_t next_ping_req_id;
uint8_t allow_nat_check_local;
@ -108,47 +108,47 @@ struct ROUTE_BGP {
};
/**
* @brief Инициализирует модуль BGP маршрутизации.
* @brief Инициализирует модуль топологии BGP.
*
* Создает очереди, local_node из подсетей конфига, привязывает к ETCP_ID_ROUTE_ENTRY,
* Создает очереди, local_node из подсетей конфига, привязывает к ETCP_ID_TOPO_ENTRY,
* устанавливает коллбеки new_conn для on_up/on_down.
*
* @param instance экземпляр utun с node_id и конфигом
* @return ROUTE_BGP или NULL при ошибке
* @return TOPO_BGP или NULL при ошибке
*/
struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance);
struct TOPO_BGP* topo_bgp_init(struct UTUN_INSTANCE* instance);
/**
* @brief Освобождает ресурсы BGP (очереди, local_node, снимает привязку ETCP).
*
* @param instance экземпляр utun
*/
void route_bgp_destroy(struct UTUN_INSTANCE* instance);
void topo_bgp_destroy(struct UTUN_INSTANCE* instance);
/**
* @brief Добавляет conn в senders_list (если нет), отправляет запрос таблицы (nodeinfo).
*
* Вызывается при ETCP on_up.
*/
void route_bgp_new_conn(struct ETCP_CONN* conn);
void topo_bgp_new_conn(struct ETCP_CONN* conn);
/**
* @brief Удаляет conn из senders_list, очищает paths во всех nodes, отправляет withdraw если node unreachable.
*
* Вызывается при ETCP on_down.
*/
void route_bgp_remove_conn(struct ETCP_CONN* conn);
void topo_bgp_remove_conn(struct ETCP_CONN* conn);
/**
* @brief Обрабатывает пакет NODEINFO.
*
* Проверка версии, обновление или создание NODEINFO_Q, добавление пути,
* Проверка версии, обновление или создание TOPO_NODEQ, добавление пути,
* вставка в роутинг, broadcast если не max hops.
*
* @return 0 при успехе
*/
int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, 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.
*
@ -156,42 +156,42 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co
*
* @return 0 при успехе
*/
int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len);
int topo_bgp_process_withdraw(struct TOPO_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len);
/**
* @brief Отправляет NODEINFO пакет одному conn (всегда local_node).
*/
void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn);
void topo_bgp_send_nodeinfo(struct TOPO_NODEQ* node, struct ETCP_CONN* conn);
/**
* @brief Отправляет WITHDRAW для node_id (вызывает broadcast_withdraw).
*/
void route_bgp_send_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id);
void topo_bgp_send_withdraw(struct TOPO_BGP* bgp, uint64_t node_id);
/**
* @brief Поиск оптимального ETCP соединения для указанного node_id.
*
* Перебирает paths узла, выбирает путь с минимальным hop_count.
*
* @param bgp указатель на ROUTE_BGP
* @param bgp указатель на TOPO_BGP
* @param node_id целевой узел
* @return оптимальный ETCP_CONN* или NULL
*/
struct ETCP_CONN* route_bgp_find_conn_for_node(struct ROUTE_BGP* bgp, uint64_t node_id);
struct ETCP_CONN* topo_bgp_find_conn_for_node(struct TOPO_BGP* bgp, uint64_t node_id);
/**
* @brief Добавляет путь (conn) в paths узла.
*
* @return 0 при успехе
*/
int route_bgp_add_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count);
int topo_bgp_add_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count);
/**
* @brief Удаляет conn из paths узла.
*
* @return 1 если путей не осталось (unreachable)
*/
int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn);
int topo_bgp_remove_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn);
/**
* @brief Отправляет NAT_INFO клиенту с его типом NAT.
@ -201,7 +201,7 @@ int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn);
* @param nat_port порт клиента (network byte order)
* @param nat_type NAT_TYPE_EIM или NAT_TYPE_STRICT
*/
void route_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_bgp_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 серверу.
@ -209,23 +209,23 @@ void route_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t
* @param conn соединение к серверу
* @param socket_id ID сокета для проверки
*/
void route_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id);
void topo_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id);
/**
* @brief Разрешить/запретить NAT check для локальных подсетей (127.0.0.1, 10.x.x.x и т.д.)
* По умолчанию запрещено. Полезно для тестов.
*/
void route_bgp_set_nat_check_local(struct ROUTE_BGP* bgp, int allow);
void topo_bgp_set_nat_check_local(struct TOPO_BGP* bgp, int allow);
/**
* @brief Запускает NAT check для всех линков всех соединений.
*/
void route_bgp_request_nat_check_all(struct ROUTE_BGP* bgp);
void topo_bgp_request_nat_check_all(struct TOPO_BGP* bgp);
/**
* @brief Запускает NAT check для одного линка.
*/
void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* link);
void topo_bgp_start_link_nat_check(struct TOPO_BGP* bgp, struct ETCP_LINK* link);
/* Аргумент callback NAT check */
struct nat_check_arg {
@ -238,4 +238,4 @@ struct nat_check_arg {
#ifdef __cplusplus
}
#endif
#endif // ROUTE_BGP_H
#endif // TOPO_BGP_H

335
src/route_node.c → src/topo_node.c

@ -9,17 +9,17 @@
#include "utun_instance.h"
#include "etcp.h"
#include "config_parser.h"
#include "route_node.h"
#include "route_bgp.h"
#include "topo_node.h"
#include "topo_bgp.h"
#include "route_lib.h"
#include "etcp_debug.h"
void nodeinfo_ref(struct NODEINFO* ni) {
void topo_node_ref(struct TOPO_NODE* ni) {
if (!ni) return;
ni->ref_count++;
}
void nodeinfo_unref(struct NODEINFO* ni) {
void topo_node_unref(struct TOPO_NODE* ni) {
if (!ni) return;
if (--ni->ref_count == 0) {
u_free(ni->node_name);
@ -27,26 +27,26 @@ void nodeinfo_unref(struct NODEINFO* ni) {
}
}
static void free_v4_sock_list(struct memory_pool* pool, struct NI_IPV4_SOCKET_META* head) {
while (head) { struct NI_IPV4_SOCKET_META* next = head->next; memory_pool_free(pool, head); head = next; }
static void free_v4_sock_list(struct memory_pool* pool, struct TOPO_SOCKMETA4* head) {
while (head) { struct TOPO_SOCKMETA4* next = head->next; memory_pool_free(pool, head); head = next; }
}
static void free_v4_addr_list(struct memory_pool* pool, struct NI_IPV4_ADDR* head) {
while (head) { struct NI_IPV4_ADDR* next = head->next; memory_pool_free(pool, head); head = next; }
static void free_v4_addr_list(struct memory_pool* pool, struct TOPO_ADDR4* head) {
while (head) { struct TOPO_ADDR4* next = head->next; memory_pool_free(pool, head); head = next; }
}
static void free_v6_sock_list(struct memory_pool* pool, struct NI_IPV6_SOCKET_META* head) {
while (head) { struct NI_IPV6_SOCKET_META* next = head->next; memory_pool_free(pool, head); head = next; }
static void free_v6_sock_list(struct memory_pool* pool, struct TOPO_SOCKMETA6* head) {
while (head) { struct TOPO_SOCKMETA6* next = head->next; memory_pool_free(pool, head); head = next; }
}
static void free_v6_addr_list(struct memory_pool* pool, struct NI_IPV6_ADDR* head) {
while (head) { struct NI_IPV6_ADDR* next = head->next; memory_pool_free(pool, head); head = next; }
static void free_v6_addr_list(struct memory_pool* pool, struct TOPO_ADDR6* head) {
while (head) { struct TOPO_ADDR6* next = head->next; memory_pool_free(pool, head); head = next; }
}
static void free_v4_sub_list(struct memory_pool* pool, struct NI_IPV4_SUBNET* head) {
while (head) { struct NI_IPV4_SUBNET* next = head->next; memory_pool_free(pool, head); head = next; }
static void free_v4_sub_list(struct memory_pool* pool, struct TOPO_SUBNET4* head) {
while (head) { struct TOPO_SUBNET4* next = head->next; memory_pool_free(pool, head); head = next; }
}
static void free_v6_sub_list(struct memory_pool* pool, struct NI_IPV6_SUBNET* head) {
while (head) { struct NI_IPV6_SUBNET* next = head->next; memory_pool_free(pool, head); head = next; }
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; }
}
void nodeinfo_free_lists(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq) {
void topo_node_free_lists(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq) {
if (!bgp || !nq) return;
if (nq->node) {
free_v4_sock_list(bgp->v4_sock_meta_pool, nq->node->v4_sock_meta);
@ -55,14 +55,14 @@ void nodeinfo_free_lists(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq) {
free_v6_addr_list(bgp->v6_addr_pool, nq->node->v6_addrs);
nq->node->v4_sock_meta = NULL; nq->node->v4_addrs = NULL;
nq->node->v6_sock_meta = NULL; nq->node->v6_addrs = NULL;
nodeinfo_unref(nq->node);
topo_node_unref(nq->node);
nq->node = NULL;
}
if (nq->routes) {
free_v4_sub_list(bgp->v4_subnet_pool, nq->routes->v4_subnets);
free_v6_sub_list(bgp->v6_subnet_pool, nq->routes->v6_subnets);
u_free(nq->routes);
nq->routes = NULL;
if (nq->subnets) {
free_v4_sub_list(bgp->v4_subnet_pool, nq->subnets->v4_subnets);
free_v6_sub_list(bgp->v6_subnet_pool, nq->subnets->v6_subnets);
u_free(nq->subnets);
nq->subnets = NULL;
}
u_free(nq->tranzit_data); nq->tranzit_data = NULL; nq->tranzit_count = 0;
u_free(nq->hop_list); nq->hop_list = NULL; nq->hop_count = 0;
@ -70,24 +70,24 @@ void nodeinfo_free_lists(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq) {
// ===== serialization =====
int nodeinfo_dyn_size(const struct NODEINFO_MSG* msg) {
int topo_node_dyn_size(const struct TOPOMSG_NODE* msg) {
return msg->node_name_len
+ msg->local_v4_sockets * sizeof(struct NODEINFO_IPV4_SOCKET_META)
+ msg->local_v4_addrs * sizeof(struct NODEINFO_IPV4_ADDR)
+ msg->local_v6_sockets * sizeof(struct NODEINFO_IPV6_SOCKET_META)
+ msg->local_v6_addrs * sizeof(struct NODEINFO_IPV6_ADDR)
+ ((msg->flags & NODEINFO_FLAG_SEND_SUBNETS)
? (msg->local_v4_subnets * sizeof(struct NODEINFO_IPV4_SUBNET) + msg->local_v6_subnets * sizeof(struct NODEINFO_IPV6_SUBNET))
+ msg->local_v4_sockets * sizeof(struct TOPOMSG_SOCKMETA4)
+ msg->local_v4_addrs * sizeof(struct TOPOMSG_ADDR4)
+ msg->local_v6_sockets * sizeof(struct TOPOMSG_SOCKMETA6)
+ msg->local_v6_addrs * sizeof(struct TOPOMSG_ADDR6)
+ ((msg->flags & TOPO_FLAG_SEND_SUBNETS)
? (msg->local_v4_subnets * sizeof(struct TOPOMSG_SUBNET4) + msg->local_v6_subnets * sizeof(struct TOPOMSG_SUBNET6))
: 0)
+ msg->tranzit_nodes * sizeof(struct NODEINFO_TRANZIT_NODE)
+ msg->tranzit_nodes * sizeof(struct TOPOMSG_TRANZIT)
+ msg->hop_count * 8;
}
int nodeinfo_serialize(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq, uint8_t* out, size_t out_max) {
int topo_node_serialize(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq, uint8_t* out, size_t out_max) {
if (!bgp || !nq || !nq->node || !out) return -1;
struct NODEINFO* ni = nq->node;
struct TOPO_NODE* ni = nq->node;
struct NODEINFO_MSG msg;
struct TOPOMSG_NODE msg;
memset(&msg, 0, sizeof(msg));
msg.flags = ni->flags;
msg.group_id = ni->group_id;
@ -96,53 +96,53 @@ int nodeinfo_serialize(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq, uint8_t* ou
memcpy(msg.public_key, ni->public_key, SC_PUBKEY_SIZE);
memcpy(msg.ed25519_public_key, ni->ed25519_public_key, SC_PUBKEY_SIZE);
msg.node_name_len = ni->node_name ? (uint8_t)strlen(ni->node_name) : 0;
msg.local_v4_sockets = ni_list_count((struct _ni_head*)ni->v4_sock_meta);
msg.local_v4_addrs = ni_list_count((struct _ni_head*)ni->v4_addrs);
msg.local_v6_sockets = ni_list_count((struct _ni_head*)ni->v6_sock_meta);
msg.local_v6_addrs = ni_list_count((struct _ni_head*)ni->v6_addrs);
msg.local_v4_subnets = nq->routes ? ni_list_count((struct _ni_head*)nq->routes->v4_subnets) : 0;
msg.local_v6_subnets = nq->routes ? ni_list_count((struct _ni_head*)nq->routes->v6_subnets) : 0;
msg.local_v4_sockets = topo_list_count((struct _topo_head*)ni->v4_sock_meta);
msg.local_v4_addrs = topo_list_count((struct _topo_head*)ni->v4_addrs);
msg.local_v6_sockets = topo_list_count((struct _topo_head*)ni->v6_sock_meta);
msg.local_v6_addrs = topo_list_count((struct _topo_head*)ni->v6_addrs);
msg.local_v4_subnets = nq->subnets ? topo_list_count((struct _topo_head*)nq->subnets->v4_subnets) : 0;
msg.local_v6_subnets = nq->subnets ? topo_list_count((struct _topo_head*)nq->subnets->v6_subnets) : 0;
msg.tranzit_nodes = nq->tranzit_count;
msg.hop_count = nq->hop_count;
size_t total = NODEINFO_MSG_HDR_SIZE + (size_t)nodeinfo_dyn_size(&msg);
size_t total = TOPOMSG_NODE_HDR_SIZE + (size_t)topo_node_dyn_size(&msg);
if (total > out_max) return -1;
memcpy(out, &msg, NODEINFO_MSG_HDR_SIZE);
uint8_t* dp = out + NODEINFO_MSG_HDR_SIZE;
memcpy(out, &msg, TOPOMSG_NODE_HDR_SIZE);
uint8_t* dp = out + TOPOMSG_NODE_HDR_SIZE;
if (msg.node_name_len) { memcpy(dp, ni->node_name, msg.node_name_len); dp += msg.node_name_len; }
{ struct NI_IPV4_SOCKET_META* e = ni->v4_sock_meta; while (e) {
struct NODEINFO_IPV4_SOCKET_META w = { .id=e->id, .config_type=e->config_type, .nat_type=e->nat_type };
{ struct TOPO_SOCKMETA4* e = ni->v4_sock_meta; while (e) {
struct TOPOMSG_SOCKMETA4 w = { .id=e->id, .config_type=e->config_type, .nat_type=e->nat_type };
memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next;
}}
{ struct NI_IPV4_ADDR* e = ni->v4_addrs; while (e) {
struct NODEINFO_IPV4_ADDR w = { .port=e->port, .type=e->type, .socket_id=e->socket_id, .protocol=e->protocol };
{ struct TOPO_ADDR4* e = ni->v4_addrs; while (e) {
struct TOPOMSG_ADDR4 w = { .port=e->port, .type=e->type, .socket_id=e->socket_id, .protocol=e->protocol };
memcpy(w.addr, e->addr, 4); memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next;
}}
{ struct NI_IPV6_SOCKET_META* e = ni->v6_sock_meta; while (e) {
struct NODEINFO_IPV6_SOCKET_META w = { .id=e->id, .config_type=e->config_type, .nat_type=e->nat_type };
{ struct TOPO_SOCKMETA6* e = ni->v6_sock_meta; while (e) {
struct TOPOMSG_SOCKMETA6 w = { .id=e->id, .config_type=e->config_type, .nat_type=e->nat_type };
memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next;
}}
{ struct NI_IPV6_ADDR* e = ni->v6_addrs; while (e) {
struct NODEINFO_IPV6_ADDR w = { .port=e->port, .type=e->type, .socket_id=e->socket_id, .protocol=e->protocol };
{ struct TOPO_ADDR6* e = ni->v6_addrs; while (e) {
struct TOPOMSG_ADDR6 w = { .port=e->port, .type=e->type, .socket_id=e->socket_id, .protocol=e->protocol };
memcpy(w.addr, e->addr, 16); memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next;
}}
if (msg.flags & NODEINFO_FLAG_SEND_SUBNETS) {
if (nq->routes) {
{ struct NI_IPV4_SUBNET* e = nq->routes->v4_subnets; while (e) {
struct NODEINFO_IPV4_SUBNET w = { .prefix_length=e->prefix_length };
if (msg.flags & TOPO_FLAG_SEND_SUBNETS) {
if (nq->subnets) {
{ struct TOPO_SUBNET4* e = nq->subnets->v4_subnets; while (e) {
struct TOPOMSG_SUBNET4 w = { .prefix_length=e->prefix_length };
memcpy(w.addr, e->addr, 4); memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next;
}}
{ struct NI_IPV6_SUBNET* e = nq->routes->v6_subnets; while (e) {
struct NODEINFO_IPV6_SUBNET w = { .prefix_length=e->prefix_length };
{ struct TOPO_SUBNET6* e = nq->subnets->v6_subnets; while (e) {
struct TOPOMSG_SUBNET6 w = { .prefix_length=e->prefix_length };
memcpy(w.addr, e->addr, 16); memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next;
}}
}
}
if (msg.tranzit_nodes && nq->tranzit_data) {
size_t sz = msg.tranzit_nodes * sizeof(struct NODEINFO_TRANZIT_NODE);
size_t sz = msg.tranzit_nodes * sizeof(struct TOPOMSG_TRANZIT);
memcpy(dp, nq->tranzit_data, sz); dp += sz;
}
if (msg.hop_count && nq->hop_list) {
@ -154,17 +154,17 @@ int nodeinfo_serialize(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq, uint8_t* ou
// ===== deserialization =====
int nodeinfo_deserialize(struct ROUTE_BGP* bgp, const uint8_t* data, size_t len, struct NODEINFO** out_ni, struct NODEINFO_ROUTES** out_routes,
struct NODEINFO_TRANZIT_NODE** out_tranzit, uint8_t* out_tranzit_count,
uint64_t** out_hop_list, uint8_t* out_hop_count) {
if (!bgp || !data || len < NODEINFO_MSG_HDR_SIZE || !out_ni) return -1;
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,
struct TOPOMSG_TRANZIT** out_tranzit, uint8_t* out_tranzit_count,
uint64_t** out_hop_list, uint8_t* out_hop_count) {
if (!bgp || !data || len < TOPOMSG_NODE_HDR_SIZE || !out_ni) return -1;
const struct NODEINFO_MSG* msg = (const struct NODEINFO_MSG*)data;
int dyn = nodeinfo_dyn_size(msg);
if ((size_t)dyn + NODEINFO_MSG_HDR_SIZE != len) return -1;
const struct TOPOMSG_NODE* msg = (const struct TOPOMSG_NODE*)data;
int dyn = topo_node_dyn_size(msg);
if ((size_t)dyn + TOPOMSG_NODE_HDR_SIZE != len) return -1;
struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO));
if (!ni) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "nodeinfo_deserialize: alloc NODEINFO failed"); return -1; }
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
if (!ni) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_node_deserialize: alloc TOPO_NODE failed"); return -1; }
ni->ref_count = 1;
ni->flags = msg->flags;
ni->group_id = msg->group_id;
@ -173,7 +173,7 @@ int nodeinfo_deserialize(struct ROUTE_BGP* bgp, const uint8_t* data, size_t len,
memcpy(ni->public_key, msg->public_key, SC_PUBKEY_SIZE);
memcpy(ni->ed25519_public_key, msg->ed25519_public_key, SC_PUBKEY_SIZE);
const uint8_t* dp = data + NODEINFO_MSG_HDR_SIZE;
const uint8_t* dp = data + TOPOMSG_NODE_HDR_SIZE;
if (msg->node_name_len) {
ni->node_name = u_malloc(msg->node_name_len + 1);
@ -182,71 +182,71 @@ int nodeinfo_deserialize(struct ROUTE_BGP* bgp, const uint8_t* data, size_t len,
}
for (int i = 0; i < msg->local_v4_sockets; i++) {
const struct NODEINFO_IPV4_SOCKET_META* w = (const struct NODEINFO_IPV4_SOCKET_META*)dp; dp += sizeof(*w);
struct NI_IPV4_SOCKET_META* e = memory_pool_alloc(bgp->v4_sock_meta_pool);
if (!e) { nodeinfo_unref(ni); return -1; }
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);
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->next = ni->v4_sock_meta; ni->v4_sock_meta = e;
}
for (int i = 0; i < msg->local_v4_addrs; i++) {
const struct NODEINFO_IPV4_ADDR* w = (const struct NODEINFO_IPV4_ADDR*)dp; dp += sizeof(*w);
struct NI_IPV4_ADDR* e = memory_pool_alloc(bgp->v4_addr_pool);
if (!e) { nodeinfo_unref(ni); return -1; }
const struct TOPOMSG_ADDR4* w = (const struct TOPOMSG_ADDR4*)dp; dp += sizeof(*w);
struct TOPO_ADDR4* e = memory_pool_alloc(bgp->v4_addr_pool);
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;
e->next = ni->v4_addrs; ni->v4_addrs = e;
}
for (int i = 0; i < msg->local_v6_sockets; i++) {
const struct NODEINFO_IPV6_SOCKET_META* w = (const struct NODEINFO_IPV6_SOCKET_META*)dp; dp += sizeof(*w);
struct NI_IPV6_SOCKET_META* e = memory_pool_alloc(bgp->v6_sock_meta_pool);
if (!e) { nodeinfo_unref(ni); return -1; }
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);
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->next = ni->v6_sock_meta; ni->v6_sock_meta = e;
}
for (int i = 0; i < msg->local_v6_addrs; i++) {
const struct NODEINFO_IPV6_ADDR* w = (const struct NODEINFO_IPV6_ADDR*)dp; dp += sizeof(*w);
struct NI_IPV6_ADDR* e = memory_pool_alloc(bgp->v6_addr_pool);
if (!e) { nodeinfo_unref(ni); return -1; }
const struct TOPOMSG_ADDR6* w = (const struct TOPOMSG_ADDR6*)dp; dp += sizeof(*w);
struct TOPO_ADDR6* e = memory_pool_alloc(bgp->v6_addr_pool);
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;
e->next = ni->v6_addrs; ni->v6_addrs = e;
}
if (out_routes && (msg->flags & NODEINFO_FLAG_SEND_SUBNETS) && (msg->local_v4_subnets || msg->local_v6_subnets)) {
struct NODEINFO_ROUTES* r = u_calloc(1, sizeof(struct NODEINFO_ROUTES));
if (!r) { nodeinfo_unref(ni); return -1; }
if (out_subnets && (msg->flags & TOPO_FLAG_SEND_SUBNETS) && (msg->local_v4_subnets || msg->local_v6_subnets)) {
struct TOPO_NODESUBNETS* r = u_calloc(1, sizeof(struct TOPO_NODESUBNETS));
if (!r) { topo_node_unref(ni); return -1; }
for (int i = 0; i < msg->local_v4_subnets; i++) {
const struct NODEINFO_IPV4_SUBNET* w = (const struct NODEINFO_IPV4_SUBNET*)dp; dp += sizeof(*w);
struct NI_IPV4_SUBNET* e = memory_pool_alloc(bgp->v4_subnet_pool);
if (!e) { u_free(r); nodeinfo_unref(ni); return -1; }
const struct TOPOMSG_SUBNET4* w = (const struct TOPOMSG_SUBNET4*)dp; dp += sizeof(*w);
struct TOPO_SUBNET4* e = memory_pool_alloc(bgp->v4_subnet_pool);
if (!e) { u_free(r); topo_node_unref(ni); return -1; }
memcpy(e->addr, w->addr, 4); e->prefix_length = w->prefix_length;
e->next = r->v4_subnets; r->v4_subnets = e;
}
for (int i = 0; i < msg->local_v6_subnets; i++) {
const struct NODEINFO_IPV6_SUBNET* w = (const struct NODEINFO_IPV6_SUBNET*)dp; dp += sizeof(*w);
struct NI_IPV6_SUBNET* e = memory_pool_alloc(bgp->v6_subnet_pool);
if (!e) { u_free(r); nodeinfo_unref(ni); return -1; }
const struct TOPOMSG_SUBNET6* w = (const struct TOPOMSG_SUBNET6*)dp; dp += sizeof(*w);
struct TOPO_SUBNET6* e = memory_pool_alloc(bgp->v6_subnet_pool);
if (!e) { u_free(r); topo_node_unref(ni); return -1; }
memcpy(e->addr, w->addr, 16); e->prefix_length = w->prefix_length;
e->next = r->v6_subnets; r->v6_subnets = e;
}
*out_routes = r;
} else if (!(msg->flags & NODEINFO_FLAG_SEND_SUBNETS)) {
dp += msg->local_v4_subnets * sizeof(struct NODEINFO_IPV4_SUBNET)
+ msg->local_v6_subnets * sizeof(struct NODEINFO_IPV6_SUBNET);
if (out_routes) *out_routes = NULL;
*out_subnets = r;
} else if (!(msg->flags & TOPO_FLAG_SEND_SUBNETS)) {
dp += msg->local_v4_subnets * sizeof(struct TOPOMSG_SUBNET4)
+ msg->local_v6_subnets * sizeof(struct TOPOMSG_SUBNET6);
if (out_subnets) *out_subnets = NULL;
} else {
if (out_routes) *out_routes = NULL;
if (out_subnets) *out_subnets = NULL;
}
if (out_tranzit && msg->tranzit_nodes > 0) {
size_t tsz = msg->tranzit_nodes * sizeof(struct NODEINFO_TRANZIT_NODE);
size_t tsz = msg->tranzit_nodes * sizeof(struct TOPOMSG_TRANZIT);
*out_tranzit = u_malloc(tsz);
if (!*out_tranzit) { nodeinfo_unref(ni); return -1; }
if (!*out_tranzit) { topo_node_unref(ni); return -1; }
memcpy(*out_tranzit, dp, tsz); dp += tsz;
*out_tranzit_count = msg->tranzit_nodes;
}
if (out_hop_list && msg->hop_count > 0) {
size_t hsz = msg->hop_count * 8;
*out_hop_list = u_malloc(hsz);
if (!*out_hop_list) { nodeinfo_unref(ni); return -1; }
if (!*out_hop_list) { topo_node_unref(ni); return -1; }
memcpy(*out_hop_list, dp, hsz); dp += hsz;
*out_hop_count = msg->hop_count;
}
@ -255,16 +255,16 @@ int nodeinfo_deserialize(struct ROUTE_BGP* bgp, const uint8_t* data, size_t len,
return 0;
}
struct NODEINFO_Q* nodeinfo_find_by_id(struct ROUTE_BGP* bgp, uint64_t node_id) {
struct TOPO_NODEQ* topo_node_find_by_id(struct TOPO_BGP* bgp, uint64_t node_id) {
if (!bgp || !bgp->nodes) return NULL;
uint64_t key = node_id;
struct ll_entry* e = queue_find_data_by_index(bgp->nodes, &key);
return e ? (struct NODEINFO_Q*)e : NULL;
return e ? (struct TOPO_NODEQ*)e : NULL;
}
// ===== dump / format (updated for new structures) =====
// ===== dump / format =====
static int is_node_connectivity_active(struct NODE_CONNECTIVITY* c) {
static int is_node_connectivity_active(struct TOPO_CONNECTIVITY* c) {
return c->probe_status != PROBE_STATUS_NONE
|| c->interface_status != PROBE_RESULT_UNKNOWN
|| c->nat_status != PROBE_RESULT_UNKNOWN
@ -283,7 +283,7 @@ 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"; }
}
void route_node_dump_all(struct ROUTE_BGP* bgp) {
void topo_node_dump_all(struct TOPO_BGP* bgp) {
if (!bgp || !bgp->nodes) return;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "=== BGP Nodes dump: %d nodes ===", queue_entry_count(bgp->nodes));
@ -291,8 +291,8 @@ void route_node_dump_all(struct ROUTE_BGP* bgp) {
int idx = 0;
struct ll_entry* e = bgp->nodes->head;
while (e) {
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e;
struct NODEINFO* ni = nq->node;
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
struct TOPO_NODE* ni = nq->node;
if (!ni) { e = e->next; continue; }
int is_local = (bgp->local_node == nq);
const char* name_s = ni->node_name ? ni->node_name : "";
@ -307,33 +307,33 @@ void route_node_dump_all(struct ROUTE_BGP* bgp) {
log_dump(DEBUG_LEVEL_INFO, DEBUG_CATEGORY_BGP, " ed25519", ni->ed25519_public_key, SC_PUBKEY_SIZE);
int si = 0;
{ struct NI_IPV4_SOCKET_META* sm = ni->v4_sock_meta; while (sm) {
{ struct TOPO_SOCKMETA4* sm = ni->v4_sock_meta; while (sm) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4sock[%d]: id=%u config=%u nat=%u", si++, sm->id, sm->config_type, sm->nat_type);
sm = sm->next;
}}
{ const char* atn[] = {"INTERFACE","NAT","REAL"};
int ai = 0; struct NI_IPV4_ADDR* a = ni->v4_addrs; while (a) {
const char* proto = (a->protocol & NODE_PROTO_TCP) ? "tcp" : (a->protocol & NODE_PROTO_UDP) ? "udp" : "?";
int ai = 0; struct TOPO_ADDR4* a = ni->v4_addrs; while (a) {
const char* proto = (a->protocol & TOPO_PROTO_TCP) ? "tcp" : (a->protocol & TOPO_PROTO_UDP) ? "udp" : "?";
DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4addr[%d]: %s:%u %s sock=%u proto=%s", ai++,
ip_to_str(a->addr, AF_INET).str, a->port, (a->type<=2)?atn[a->type]:"?", a->socket_id, proto);
a = a->next;
}}
{ int si6 = 0; struct NI_IPV6_SOCKET_META* sm6 = ni->v6_sock_meta; while (sm6) {
{ int si6 = 0; struct TOPO_SOCKMETA6* sm6 = ni->v6_sock_meta; while (sm6) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6sock[%d]: id=%u config=%u nat=%u", si6++, sm6->id, sm6->config_type, sm6->nat_type);
sm6 = sm6->next;
}}
{ int ai6 = 0; struct NI_IPV6_ADDR* a6 = ni->v6_addrs; while (a6) {
const char* proto = (a6->protocol & NODE_PROTO_TCP) ? "tcp" : (a6->protocol & NODE_PROTO_UDP) ? "udp" : "?";
{ int ai6 = 0; struct TOPO_ADDR6* a6 = ni->v6_addrs; while (a6) {
const char* proto = (a6->protocol & TOPO_PROTO_TCP) ? "tcp" : (a6->protocol & TOPO_PROTO_UDP) ? "udp" : "?";
DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6addr[%d]: %s:%u type=%u sock=%u proto=%s", ai6++,
ip_to_str(a6->addr, AF_INET6).str, a6->port, a6->type, a6->socket_id, proto);
a6 = a6->next;
}}
if (nq->routes) {
{ int ri = 0; struct NI_IPV4_SUBNET* sub = nq->routes->v4_subnets; while (sub) {
if (nq->subnets) {
{ int ri = 0; struct TOPO_SUBNET4* sub = nq->subnets->v4_subnets; while (sub) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4sub[%d]: %s/%d", ri++, ip_to_str(sub->addr, AF_INET).str, sub->prefix_length);
sub = sub->next;
}}
{ int ri6 = 0; struct NI_IPV6_SUBNET* sub6 = nq->routes->v6_subnets; while (sub6) {
{ int ri6 = 0; struct TOPO_SUBNET6* sub6 = nq->subnets->v6_subnets; while (sub6) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6sub[%d]: %s/%d", ri6++, ip_to_str(sub6->addr, AF_INET6).str, sub6->prefix_length);
sub6 = sub6->next;
}}
@ -347,8 +347,8 @@ void route_node_dump_all(struct ROUTE_BGP* bgp) {
if (nq->paths) {
struct ll_entry* pe = nq->paths->head;
while (pe) {
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)pe;
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH));
struct TOPO_NODEPATH* path = (struct TOPO_NODEPATH*)pe;
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct TOPO_NODEPATH));
char hop_buf[256] = ""; int hop_pos = 0;
for (uint8_t hi = 0; hi < path->hop_count && hop_pos < (int)sizeof(hop_buf)-20; hi++)
hop_pos += snprintf(hop_buf + hop_pos, sizeof(hop_buf) - hop_pos, "%s%016llx", hi ? "->" : "", (unsigned long long)hop[hi]);
@ -358,7 +358,7 @@ void route_node_dump_all(struct ROUTE_BGP* bgp) {
}
}
struct NODE_CONNECTIVITY* c = &nq->connectivity;
struct TOPO_CONNECTIVITY* c = &nq->connectivity;
if (is_node_connectivity_active(c)) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, " connectivity: probe=%s iface=%s(%u) nat=%s(%u) real=%s(%u) pend=%u iface_rtt=%u nat_rtt=%u real_rtt=%u start_tb=%llu ping_req_tb=%llu",
probe_status_str(c->probe_status), probe_result_str(c->interface_status), c->interface_min_rtt,
@ -377,7 +377,7 @@ void route_node_dump_all(struct ROUTE_BGP* bgp) {
}
}
int route_node_format_all(struct ROUTE_BGP* bgp, char* buf, size_t buf_size) {
int topo_node_format_all(struct TOPO_BGP* bgp, char* buf, size_t buf_size) {
if (!bgp || !bgp->nodes || !buf || buf_size == 0) return 0;
int pos = 0;
@ -387,8 +387,8 @@ int route_node_format_all(struct ROUTE_BGP* bgp, char* buf, size_t buf_size) {
int idx = 0;
struct ll_entry* e = bgp->nodes->head;
while (e && (size_t)pos < buf_size) {
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e;
struct NODEINFO* ni = nq->node;
struct TOPO_NODEQ* nq = (struct TOPO_NODEQ*)e;
struct TOPO_NODE* ni = nq->node;
if (!ni) { e = e->next; continue; }
int is_local = (bgp->local_node == nq);
const char* name_s = ni->node_name ? ni->node_name : "";
@ -404,29 +404,29 @@ int route_node_format_all(struct ROUTE_BGP* bgp, char* buf, size_t buf_size) {
FMT_ADD(" pubkey: "); for (int k = 0; k < SC_PUBKEY_SIZE; k++) FMT_ADD("%02x", ni->public_key[k]); FMT_ADD("\n");
FMT_ADD(" ed25519: "); for (int k = 0; k < SC_PUBKEY_SIZE; k++) FMT_ADD("%02x", ni->ed25519_public_key[k]); FMT_ADD("\n");
{ struct NI_IPV4_SOCKET_META* sm = ni->v4_sock_meta; int si = 0; while (sm) {
{ struct TOPO_SOCKMETA4* sm = ni->v4_sock_meta; int si = 0; while (sm) {
FMT_ADD(" v4sock[%d]: id=%u config=%u nat=%u\n", si++, sm->id, sm->config_type, sm->nat_type); sm = sm->next;
}}
{ const char* atn[] = {"INTERFACE","NAT","REAL"}; struct NI_IPV4_ADDR* a = ni->v4_addrs; int ai = 0; while (a) {
const char* proto = (a->protocol & NODE_PROTO_TCP) ? "tcp" : (a->protocol & NODE_PROTO_UDP) ? "udp" : "?";
{ const char* atn[] = {"INTERFACE","NAT","REAL"}; struct TOPO_ADDR4* a = ni->v4_addrs; int ai = 0; while (a) {
const char* proto = (a->protocol & TOPO_PROTO_TCP) ? "tcp" : (a->protocol & TOPO_PROTO_UDP) ? "udp" : "?";
FMT_ADD(" v4addr[%d]: %s:%u %s sock=%u proto=%s\n",
ai++, ip_to_str(a->addr, AF_INET).str, a->port, (a->type<=2)?atn[a->type]:"?", a->socket_id, proto);
a = a->next;
}}
{ struct NI_IPV6_SOCKET_META* sm6 = ni->v6_sock_meta; int s6i = 0; while (sm6) {
{ struct TOPO_SOCKMETA6* sm6 = ni->v6_sock_meta; int s6i = 0; while (sm6) {
FMT_ADD(" v6sock[%d]: id=%u config=%u nat=%u\n", s6i++, sm6->id, sm6->config_type, sm6->nat_type); sm6 = sm6->next;
}}
{ struct NI_IPV6_ADDR* a6 = ni->v6_addrs; int a6i = 0; while (a6) {
const char* proto = (a6->protocol & NODE_PROTO_TCP) ? "tcp" : (a6->protocol & NODE_PROTO_UDP) ? "udp" : "?";
{ struct TOPO_ADDR6* a6 = ni->v6_addrs; int a6i = 0; while (a6) {
const char* proto = (a6->protocol & TOPO_PROTO_TCP) ? "tcp" : (a6->protocol & TOPO_PROTO_UDP) ? "udp" : "?";
FMT_ADD(" v6addr[%d]: %s:%u type=%u sock=%u proto=%s\n",
a6i++, ip_to_str(a6->addr, AF_INET6).str, a6->port, a6->type, a6->socket_id, proto);
a6 = a6->next;
}}
if (nq->routes) {
{ struct NI_IPV4_SUBNET* sub = nq->routes->v4_subnets; int ri = 0; while (sub) {
if (nq->subnets) {
{ struct TOPO_SUBNET4* sub = nq->subnets->v4_subnets; int ri = 0; while (sub) {
FMT_ADD(" v4sub[%d]: %s/%d\n", ri++, ip_to_str(sub->addr, AF_INET).str, sub->prefix_length); sub = sub->next;
}}
{ struct NI_IPV6_SUBNET* sub6 = nq->routes->v6_subnets; int r6i = 0; while (sub6) {
{ struct TOPO_SUBNET6* sub6 = nq->subnets->v6_subnets; int r6i = 0; while (sub6) {
FMT_ADD(" v6sub[%d]: %s/%d\n", r6i++, ip_to_str(sub6->addr, AF_INET6).str, sub6->prefix_length); sub6 = sub6->next;
}}
}
@ -437,8 +437,8 @@ int route_node_format_all(struct ROUTE_BGP* bgp, char* buf, size_t buf_size) {
if (nq->paths) {
struct ll_entry* pe = nq->paths->head; int pi = 0;
while (pe) {
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)pe;
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH));
struct TOPO_NODEPATH* path = (struct TOPO_NODEPATH*)pe;
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct TOPO_NODEPATH));
FMT_ADD(" path[%d]: conn=%s hop_count=%u hops=[", pi++, path->conn ? path->conn->log_name : "NULL", path->hop_count);
for (uint8_t hi = 0; hi < path->hop_count; hi++)
FMT_ADD("%s%016llx", hi ? "->" : "", (unsigned long long)hop[hi]);
@ -446,7 +446,7 @@ int route_node_format_all(struct ROUTE_BGP* bgp, char* buf, size_t buf_size) {
}
}
struct NODE_CONNECTIVITY* c = &nq->connectivity;
struct TOPO_CONNECTIVITY* c = &nq->connectivity;
if (is_node_connectivity_active(c)) {
FMT_ADD(" connectivity: probe=%s iface=%s(%u) nat=%s(%u) real=%s(%u) pend=%u iface_rtt=%u nat_rtt=%u real_rtt=%u start_tb=%llu ping_req_tb=%llu\n",
probe_status_str(c->probe_status), probe_result_str(c->interface_status), c->interface_min_rtt,
@ -472,10 +472,10 @@ int route_node_format_all(struct ROUTE_BGP* bgp, char* buf, size_t buf_size) {
return pos;
}
// ===== update my nodeinfo (rewritten for new structures) =====
// ===== update my nodeinfo =====
int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp) {
if (!instance || !bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_update_my_nodeinfo: invalid args"); return -1; }
int topo_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_BGP* bgp) {
if (!instance || !bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "topo_bgp_update_my_nodeinfo: invalid args"); return -1; }
size_t name_len = 0;
if (instance->name[0]) { name_len = strlen(instance->name); if (name_len > 63) name_len = 63; }
int vc = 0, vc6 = 0;
@ -502,17 +502,16 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
int changed = 1; uint8_t old_ver = 0;
if (bgp->local_node && bgp->local_node->node) {
struct NODEINFO* oni = bgp->local_node->node;
struct TOPO_NODE* oni = bgp->local_node->node;
old_ver = oni->ver;
int v4a_cnt = ni_list_count((struct _ni_head*)oni->v4_addrs);
changed = (vc != (bgp->local_node->routes ? ni_list_count((struct _ni_head*)bgp->local_node->routes->v4_subnets) : 0))
|| (sock_count != ni_list_count((struct _ni_head*)oni->v4_sock_meta))
|| (addr_count != v4a_cnt)
changed = (vc != (bgp->local_node->subnets ? topo_list_count((struct _topo_head*)bgp->local_node->subnets->v4_subnets) : 0))
|| (sock_count != topo_list_count((struct _topo_head*)oni->v4_sock_meta))
|| (addr_count != topo_list_count((struct _topo_head*)oni->v4_addrs))
|| (name_len != (oni->node_name ? strlen(oni->node_name) : 0))
|| (memcmp(oni->public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE) != 0)
|| (vc6 != (bgp->local_node->routes ? ni_list_count((struct _ni_head*)bgp->local_node->routes->v6_subnets) : 0))
|| (sock6_count != ni_list_count((struct _ni_head*)oni->v6_sock_meta))
|| (addr6_count != ni_list_count((struct _ni_head*)oni->v6_addrs));
|| (vc6 != (bgp->local_node->subnets ? topo_list_count((struct _topo_head*)bgp->local_node->subnets->v6_subnets) : 0))
|| (sock6_count != topo_list_count((struct _topo_head*)oni->v6_sock_meta))
|| (addr6_count != topo_list_count((struct _topo_head*)oni->v6_addrs));
if (bgp->local_node && bgp->instance && bgp->instance->bgp)
if (memcmp(oni->ed25519_public_key, bgp->instance->bgp->ed25519_public_key, SC_PUBKEY_SIZE) != 0) changed = 1;
}
@ -520,20 +519,20 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
if (changed) {
if (bgp->local_node) {
if (instance->rt) route_delete(instance->rt, bgp->local_node);
nodeinfo_free_lists(bgp, bgp->local_node);
topo_node_free_lists(bgp, bgp->local_node);
u_free(bgp->local_node);
bgp->local_node = NULL;
}
bgp->local_node = u_calloc(1, sizeof(struct NODEINFO_Q));
bgp->local_node = u_calloc(1, sizeof(struct TOPO_NODEQ));
if (!bgp->local_node) return -1;
struct NODEINFO_Q* lq = bgp->local_node;
struct TOPO_NODEQ* lq = bgp->local_node;
struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO));
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
if (!ni) { u_free(lq); bgp->local_node = NULL; return -1; }
ni->ref_count = 1;
ni->flags = NODEINFO_FLAG_SEND_SUBNETS;
ni->group_id = NODEINFO_GROUP_UTUN;
ni->flags = TOPO_FLAG_SEND_SUBNETS;
ni->group_id = TOPO_GROUP_UTUN;
ni->node_id = instance->node_id;
ni->ver = (old_ver % 255) + 1;
memcpy(ni->public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE);
@ -550,37 +549,37 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
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->local_addr.ss_family == AF_INET) {
{ struct NI_IPV4_SOCKET_META* sm = memory_pool_alloc(bgp->v4_sock_meta_pool);
{ struct TOPO_SOCKMETA4* sm = memory_pool_alloc(bgp->v4_sock_meta_pool);
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; }
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 NI_IPV4_ADDR* a = memory_pool_alloc(bgp->v4_addr_pool);
{ struct TOPO_ADDR4* a = memory_pool_alloc(bgp->v4_addr_pool);
memcpy(a->addr, &if_sin->sin_addr.s_addr, 4); a->port = ntohs(if_sin->sin_port);
a->type = ADDR_TYPE_INTERFACE; a->socket_id = e_sock->sock_id; a->protocol = NODE_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; }
if (e_sock->nat_addr.ss_family == AF_INET && nat_sin->sin_addr.s_addr != 0 && e_sock->nat_type != NAT_VERIFIED_STRICT) {
struct NI_IPV4_ADDR* a = memory_pool_alloc(bgp->v4_addr_pool);
struct TOPO_ADDR4* a = memory_pool_alloc(bgp->v4_addr_pool);
memcpy(a->addr, &nat_sin->sin_addr.s_addr, 4); a->port = ntohs(nat_sin->sin_port);
a->type = ADDR_TYPE_NAT; a->socket_id = e_sock->sock_id; a->protocol = NODE_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;
}
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 NI_IPV4_ADDR* a = memory_pool_alloc(bgp->v4_addr_pool);
struct TOPO_ADDR4* a = memory_pool_alloc(bgp->v4_addr_pool);
memcpy(a->addr, &if_sin->sin_addr.s_addr, 4); a->port = ntohs(if_sin->sin_port);
a->type = ADDR_TYPE_REAL; a->socket_id = e_sock->sock_id; a->protocol = NODE_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;
}
} else if (e_sock->local_addr.ss_family == AF_INET6) {
{ struct NI_IPV6_SOCKET_META* sm6 = memory_pool_alloc(bgp->v6_sock_meta_pool);
{ struct TOPO_SOCKMETA6* sm6 = memory_pool_alloc(bgp->v6_sock_meta_pool);
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; }
struct sockaddr_in6* if_sin6 = (struct sockaddr_in6*)&e_sock->interface_addr;
{ struct NI_IPV6_ADDR* a6 = memory_pool_alloc(bgp->v6_addr_pool);
{ struct TOPO_ADDR6* a6 = memory_pool_alloc(bgp->v6_addr_pool);
memcpy(a6->addr, &if_sin6->sin6_addr, 16); a6->port = ntohs(if_sin6->sin6_port);
a6->type = ADDR_TYPE_INTERFACE; a6->socket_id = e_sock->sock_id; a6->protocol = NODE_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; }
}
e_sock = e_sock->next;
@ -588,41 +587,41 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
{ struct CFG_SERVER* srv = instance->config->servers;
while (srv) { if (srv->transport && srv->ip.ss_family == AF_INET) {
struct sockaddr_in* tcp_sin = (struct sockaddr_in*)&srv->ip;
struct NI_IPV4_ADDR* a = memory_pool_alloc(bgp->v4_addr_pool);
struct TOPO_ADDR4* a = memory_pool_alloc(bgp->v4_addr_pool);
memcpy(a->addr, &tcp_sin->sin_addr.s_addr, 4); a->port = ntohs(tcp_sin->sin_port);
a->type = ADDR_TYPE_INTERFACE; a->socket_id = 0; a->protocol = NODE_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;
} else if (srv->transport && srv->ip.ss_family == AF_INET6) {
struct sockaddr_in6* tcp_sin6 = (struct sockaddr_in6*)&srv->ip;
struct NI_IPV6_ADDR* a6 = memory_pool_alloc(bgp->v6_addr_pool);
struct TOPO_ADDR6* a6 = memory_pool_alloc(bgp->v6_addr_pool);
memcpy(a6->addr, &tcp_sin6->sin6_addr, 16); a6->port = ntohs(tcp_sin6->sin6_port);
a6->type = ADDR_TYPE_INTERFACE; a6->socket_id = 0; a6->protocol = NODE_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;
} srv = srv->next; }
}
if (vc || vc6) {
struct NODEINFO_ROUTES* r = u_calloc(1, sizeof(struct NODEINFO_ROUTES));
struct TOPO_NODESUBNETS* r = u_calloc(1, sizeof(struct TOPO_NODESUBNETS));
s = instance->config->my_subnets;
while (s) {
if (s->ip.family == AF_INET) {
struct NI_IPV4_SUBNET* sub = memory_pool_alloc(bgp->v4_subnet_pool);
struct TOPO_SUBNET4* sub = memory_pool_alloc(bgp->v4_subnet_pool);
memcpy(sub->addr, &s->ip.addr.v4, 4); sub->prefix_length = s->netmask;
sub->next = r->v4_subnets; r->v4_subnets = sub;
} else if (s->ip.family == AF_INET6) {
struct NI_IPV6_SUBNET* sub6 = memory_pool_alloc(bgp->v6_subnet_pool);
struct TOPO_SUBNET6* sub6 = memory_pool_alloc(bgp->v6_subnet_pool);
memcpy(sub6->addr, &s->ip.addr.v6, 16); sub6->prefix_length = s->netmask;
sub6->next = r->v6_subnets; r->v6_subnets = sub6;
}
s = s->next;
}
lq->routes = r;
lq->subnets = r;
}
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);
if (instance->rt && !route_insert(instance->rt, lq))
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_bgp_update_my_nodeinfo: failed to insert local routes");
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "topo_bgp_update_my_nodeinfo: failed to insert local routes");
} else {
bgp->local_node->last_ver = bgp->local_node->node->ver;
}

130
src/route_node.h → src/topo_node.h

@ -1,5 +1,5 @@
#ifndef ROUTE_NODE_H
#define ROUTE_NODE_H
#ifndef TOPO_NODE_H
#define TOPO_NODE_H
#ifdef __cplusplus
extern "C" {
@ -10,19 +10,19 @@ extern "C" {
#include "../lib/ll_queue.h"
#include "secure_channel.h"
struct ROUTE_BGP;
struct TOPO_BGP;
struct ETCP_SOCKET;
struct UTUN_INSTANCE;
// ---- типы адресов в плоском списке NODEINFO_IPV4_ADDR ----
// ---- типы адресов в плоском списке TOPOMSG_ADDR4 ----
#define ADDR_TYPE_INTERFACE 0 // interface_addr сокета (LAN)
#define ADDR_TYPE_NAT 1 // nat_addr после детекции NAT
#define ADDR_TYPE_REAL 2 // подтверждённый прямой интернет-адрес (nat проверка показала совпадение с interface_addr)
#define TOPO_ADDR_INTERFACE 0 // interface_addr сокета (LAN)
#define TOPO_ADDR_NAT 1 // nat_addr после детекции NAT
#define TOPO_ADDR_REAL 2 // подтверждённый прямой интернет-адрес (nat проверка показала совпадение с interface_addr)
// ---- протоколы транспорта (поле protocol в NODEINFO_IPV4_ADDR/NODEINFO_IPV6_ADDR) ----
#define NODE_PROTO_UDP 0x01
#define NODE_PROTO_TCP 0x02
// ---- протоколы транспорта (поле protocol в TOPOMSG_ADDR4/TOPOMSG_ADDR6) ----
#define TOPO_PROTO_UDP 0x01
#define TOPO_PROTO_TCP 0x02
// ---- типы NAT (etcp_connections.h) ----
// NAT_TYPE_UNKNOWN(0), NAT_TYPE_EIM(1), NAT_TYPE_STRICT(2)
@ -47,15 +47,15 @@ struct UTUN_INSTANCE;
#define CONN_TYPE_INDIRECT 3
#define CONN_MGR_MAX_INTERMEDIARIES 3
// ---- флаги nodeinfo (protocol) ----
#define NODEINFO_FLAG_SEND_SUBNETS 0x01
// ---- флаги nodeinfo ----
#define TOPO_FLAG_SEND_SUBNETS 0x01
// ---- group_id по умолчанию ----
#define NODEINFO_GROUP_UTUN 1
#define TOPO_GROUP_UTUN 1
// ---- состояние связности с удалённым узлом (локальное, не передаётся по BGP) ----
struct NODE_CONNECTIVITY {
struct TOPO_CONNECTIVITY {
uint8_t probe_status;
uint8_t pending_count;
uint64_t probe_start_time;
@ -77,13 +77,13 @@ struct NODE_CONNECTIVITY {
// Протокольные структуры (wire-format, packed, без next)
// =======================================================================
struct NODEINFO_IPV4_SOCKET_META {
struct TOPOMSG_SOCKMETA4 {
uint8_t id;
uint8_t config_type;
uint8_t nat_type;
} __attribute__((packed));
struct NODEINFO_IPV4_ADDR {
struct TOPOMSG_ADDR4 {
uint8_t addr[4];
uint16_t port;
uint8_t type;
@ -91,13 +91,13 @@ struct NODEINFO_IPV4_ADDR {
uint8_t protocol;
} __attribute__((packed));
struct NODEINFO_IPV6_SOCKET_META {
struct TOPOMSG_SOCKMETA6 {
uint8_t id;
uint8_t config_type;
uint8_t nat_type;
} __attribute__((packed));
struct NODEINFO_IPV6_ADDR {
struct TOPOMSG_ADDR6 {
uint8_t addr[16];
uint16_t port;
uint8_t type;
@ -105,17 +105,17 @@ struct NODEINFO_IPV6_ADDR {
uint8_t protocol;
} __attribute__((packed));
struct NODEINFO_IPV4_SUBNET {
struct TOPOMSG_SUBNET4 {
uint8_t addr[4];
uint8_t prefix_length;
} __attribute__((packed));
struct NODEINFO_IPV6_SUBNET {
struct TOPOMSG_SUBNET6 {
uint8_t addr[16];
uint8_t prefix_length;
} __attribute__((packed));
struct NODEINFO_TRANZIT_NODE {
struct TOPOMSG_TRANZIT {
uint64_t node_id;
uint16_t rtt;
uint16_t link_q;
@ -124,7 +124,7 @@ struct NODEINFO_TRANZIT_NODE {
/**
* @brief Протокольный формат NODEINFO сообщения (wire-format)
*/
struct NODEINFO_MSG {
struct TOPOMSG_NODE {
uint8_t flags;
uint64_t group_id;
uint64_t node_id;
@ -142,28 +142,28 @@ struct NODEINFO_MSG {
uint8_t hop_count;
} __attribute__((packed));
#define NODEINFO_MSG_HDR_SIZE sizeof(struct NODEINFO_MSG)
#define TOPOMSG_NODE_HDR_SIZE sizeof(struct TOPOMSG_NODE)
// =======================================================================
// Структуры для хранения в памяти (linked list с next* первым полем)
// =======================================================================
struct NI_IPV4_SOCKET_META { struct NI_IPV4_SOCKET_META* next; uint8_t id, config_type, nat_type; };
struct NI_IPV4_ADDR { struct NI_IPV4_ADDR* next; uint8_t addr[4]; uint16_t port; uint8_t type, socket_id, protocol; };
struct NI_IPV6_SOCKET_META { struct NI_IPV6_SOCKET_META* next; uint8_t id, config_type, nat_type; };
struct NI_IPV6_ADDR { struct NI_IPV6_ADDR* next; uint8_t addr[16]; uint16_t port; uint8_t type, socket_id, protocol; };
struct NI_IPV4_SUBNET { struct NI_IPV4_SUBNET* next; uint8_t addr[4]; uint8_t prefix_length; };
struct NI_IPV6_SUBNET { struct NI_IPV6_SUBNET* next; uint8_t addr[16]; uint8_t prefix_length; };
struct TOPO_SOCKMETA4 { struct TOPO_SOCKMETA4* next; uint8_t id, config_type, nat_type; };
struct TOPO_ADDR4 { struct TOPO_ADDR4* next; uint8_t addr[4]; uint16_t port; uint8_t type, socket_id, protocol; };
struct TOPO_SOCKMETA6 { struct TOPO_SOCKMETA6* next; uint8_t id, config_type, nat_type; };
struct TOPO_ADDR6 { struct TOPO_ADDR6* next; uint8_t addr[16]; uint16_t port; uint8_t type, socket_id, protocol; };
struct TOPO_SUBNET4 { struct TOPO_SUBNET4* next; uint8_t addr[4]; uint8_t prefix_length; };
struct TOPO_SUBNET6 { struct TOPO_SUBNET6* next; uint8_t addr[16]; uint8_t prefix_length; };
// Универсальная голова списка (next — первое поле во всех NI_*)
struct _ni_head { struct _ni_head* next; };
// Универсальная голова списка (next — первое поле во всех TOPO_*)
struct _topo_head { struct _topo_head* next; };
static inline int ni_list_count(struct _ni_head* head) { int n = 0; while (head) { n++; head = head->next; } return n; }
static inline int topo_list_count(struct _topo_head* head) { int n = 0; while (head) { n++; head = head->next; } return n; }
/**
* @brief Идентификационная информация об узле (память, разделяется между группами)
*/
struct NODEINFO {
struct TOPO_NODE {
uint32_t ref_count;
uint8_t flags;
uint64_t group_id;
@ -172,32 +172,32 @@ struct NODEINFO {
uint8_t public_key[SC_PUBKEY_SIZE];
uint8_t ed25519_public_key[SC_PUBKEY_SIZE];
char* node_name; // отдельный u_strdup/u_free
struct NI_IPV4_SOCKET_META* v4_sock_meta; // linked list head
struct NI_IPV4_ADDR* v4_addrs; // linked list head
struct NI_IPV6_SOCKET_META* v6_sock_meta;
struct NI_IPV6_ADDR* v6_addrs;
struct TOPO_SOCKMETA4* v4_sock_meta; // linked list head
struct TOPO_ADDR4* v4_addrs; // linked list head
struct TOPO_SOCKMETA6* v6_sock_meta;
struct TOPO_ADDR6* v6_addrs;
};
/**
* @brief Маршруты узла (отдельный malloc, NULL если нет подсетей)
* @brief Подсети узла (отдельный malloc, NULL если нет подсетей)
*/
struct NODEINFO_ROUTES {
struct NI_IPV4_SUBNET* v4_subnets; // linked list head
struct NI_IPV6_SUBNET* v6_subnets;
struct TOPO_NODESUBNETS {
struct TOPO_SUBNET4* v4_subnets; // linked list head
struct TOPO_SUBNET6* v6_subnets;
};
struct NODEINFO_PATH {
struct TOPO_NODEPATH {
struct ll_entry ll;
struct ETCP_CONN* conn;
uint8_t hop_count;
};
struct NODEINFO_Q {
struct TOPO_NODEQ {
struct ll_entry ll;
uint64_t hash_node_id; // копия node_id для хеш-индекса
struct NODEINFO* node; // отдельный malloc, ref_count
struct NODEINFO_ROUTES* routes; // отдельный malloc (NULL если без подсетей)
struct NODEINFO_TRANZIT_NODE* tranzit_data; // отдельный malloc
struct TOPO_NODE* node; // отдельный malloc, ref_count
struct TOPO_NODESUBNETS* subnets; // отдельный malloc (NULL если без подсетей)
struct TOPOMSG_TRANZIT* tranzit_data; // отдельный malloc
uint64_t* hop_list; // отдельный malloc
uint8_t tranzit_count;
uint8_t hop_count;
@ -208,7 +208,7 @@ struct NODEINFO_Q {
uint8_t conn_mgr_type;
uint64_t conn_mgr_intermediaries[CONN_MGR_MAX_INTERMEDIARIES];
uint8_t conn_mgr_intermediariy_count;
struct NODE_CONNECTIVITY connectivity;
struct TOPO_CONNECTIVITY connectivity;
struct ETCP_SOCKET* best_socket;
};
@ -217,32 +217,32 @@ struct NODEINFO_Q {
// API
// =======================================================================
struct NODEINFO_Q* nodeinfo_find_by_id(struct ROUTE_BGP* bgp, uint64_t node_id);
struct TOPO_NODEQ* topo_node_find_by_id(struct TOPO_BGP* bgp, uint64_t node_id);
void nodeinfo_ref(struct NODEINFO* ni);
void nodeinfo_unref(struct NODEINFO* ni);
void nodeinfo_free_lists(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq);
int nodeinfo_dyn_size(const struct NODEINFO_MSG* msg);
void topo_node_ref(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);
int topo_node_dyn_size(const struct TOPOMSG_NODE* msg);
// convenience accessors
static inline const struct NI_IPV4_SOCKET_META* ni_v4_sock_meta(const struct NODEINFO* ni) { return ni->v4_sock_meta; }
static inline const struct NI_IPV4_ADDR* ni_v4_addrs(const struct NODEINFO* ni) { return ni->v4_addrs; }
static inline const struct NI_IPV6_SOCKET_META* ni_v6_sock_meta(const struct NODEINFO* ni) { return ni->v6_sock_meta; }
static inline const struct NI_IPV6_ADDR* ni_v6_addrs(const struct NODEINFO* ni) { return ni->v6_addrs; }
static inline const struct NI_IPV4_SUBNET* ni_v4_subnets(const struct NODEINFO_ROUTES* r) { return r ? r->v4_subnets : NULL; }
static inline const struct NI_IPV6_SUBNET* ni_v6_subnets(const struct NODEINFO_ROUTES* r) { return r ? r->v6_subnets : NULL; }
static inline const struct TOPO_SOCKMETA4* topo_v4_sock_meta(const struct TOPO_NODE* ni) { return ni->v4_sock_meta; }
static inline const struct TOPO_ADDR4* topo_v4_addrs(const struct TOPO_NODE* ni) { return ni->v4_addrs; }
static inline const struct TOPO_SOCKMETA6* topo_v6_sock_meta(const struct TOPO_NODE* ni) { return ni->v6_sock_meta; }
static inline const struct TOPO_ADDR6* topo_v6_addrs(const struct TOPO_NODE* ni) { return ni->v6_addrs; }
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; }
int nodeinfo_serialize(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq, uint8_t* out, size_t out_max);
int nodeinfo_deserialize(struct ROUTE_BGP* bgp, const uint8_t* data, size_t len, struct NODEINFO** out_ni, struct NODEINFO_ROUTES** out_routes,
struct NODEINFO_TRANZIT_NODE** out_tranzit, uint8_t* out_tranzit_count, uint64_t** out_hop_list, uint8_t* out_hop_count);
int topo_node_serialize(struct TOPO_BGP* bgp, 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,
struct TOPOMSG_TRANZIT** out_tranzit, uint8_t* out_tranzit_count, uint64_t** out_hop_list, uint8_t* out_hop_count);
int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp);
int topo_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_BGP* bgp);
void route_node_dump_all(struct ROUTE_BGP* bgp);
int route_node_format_all(struct ROUTE_BGP* bgp, char* buf, size_t buf_size);
void topo_node_dump_all(struct TOPO_BGP* bgp);
int topo_node_format_all(struct TOPO_BGP* bgp, char* buf, size_t buf_size);
#ifdef __cplusplus
}
#endif
#endif // ROUTE_NODE_H
#endif // TOPO_NODE_H

14
src/route_node_lmdb.c → src/topo_node_lmdb.c

@ -2,14 +2,14 @@
#include <string.h>
#include <stdint.h>
#include <sys/stat.h>
#include "route_node_lmdb.h"
#include "route_bgp.h"
#include "topo_node_lmdb.h"
#include "topo_bgp.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
#define NODEINFO_DB_MAPSIZE (10UL * 1024 * 1024)
int route_node_lmdb_init(struct ROUTE_BGP* bgp, const char* db_path) {
int topo_node_lmdb_init(struct TOPO_BGP* bgp, const char* db_path) {
if (!bgp || !db_path || !db_path[0]) return -1;
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; }
@ -29,15 +29,15 @@ int route_node_lmdb_init(struct ROUTE_BGP* bgp, const char* db_path) {
return 0;
}
void route_node_lmdb_destroy(struct ROUTE_BGP* bgp) {
void topo_node_lmdb_destroy(struct TOPO_BGP* bgp) {
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"); }
}
int route_node_lmdb_put(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq) {
int topo_node_lmdb_put(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq) {
if (!bgp || !bgp->nodeinfo_env || !nq || !nq->node) return -1;
uint8_t buf[8192];
int ser_len = nodeinfo_serialize(bgp, nq, buf, sizeof(buf));
int ser_len = topo_node_serialize(bgp, nq, buf, sizeof(buf));
if (ser_len < 0) return -1;
MDB_val key, data;
@ -53,7 +53,7 @@ int route_node_lmdb_put(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq) {
return 0;
}
int route_node_lmdb_del(struct ROUTE_BGP* bgp, uint64_t node_id) {
int topo_node_lmdb_del(struct TOPO_BGP* bgp, uint64_t node_id) {
if (!bgp || !bgp->nodeinfo_env) return -1;
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);

23
src/topo_node_lmdb.h

@ -0,0 +1,23 @@
#ifndef TOPO_NODE_LMDB_H
#define TOPO_NODE_LMDB_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "topo_node.h"
struct TOPO_BGP;
int topo_node_lmdb_init(struct TOPO_BGP* bgp, const char* db_path);
void topo_node_lmdb_destroy(struct TOPO_BGP* bgp);
int topo_node_lmdb_put(struct TOPO_BGP* bgp, struct TOPO_NODEQ* nq);
int topo_node_lmdb_del(struct TOPO_BGP* bgp, uint64_t node_id);
#ifdef __cplusplus
}
#endif
#endif

10
src/utun_instance.c

@ -5,10 +5,10 @@
#include "config_updater.h"
#include "tun_if.h"
#include "tun_route.h"
#include "route_node.h"
#include "topo_node.h"
#include "route_lib.h"
#include "routing.h"
#include "route_bgp.h"
#include "topo_bgp.h"
#include "etcp_connections.h"
#include "etcp.h"
#include "conn_mgr.h"
@ -159,13 +159,13 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
if (socket_result == 1) {
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "Partial socket initialization - some servers failed to bind");
}
instance->bgp = route_bgp_init(instance);
instance->bgp = topo_bgp_init(instance);
if (!instance->bgp) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Failed to initialize BGP module");
} else {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP module initialized");
if (instance->rt && instance->bgp->local_node) {
route_bgp_update_my_nodeinfo(instance, instance->bgp);
topo_bgp_update_my_nodeinfo(instance, instance->bgp);
}
}
@ -456,7 +456,7 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
// Cleanup BGP module
if (instance->bgp) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Destroying BGP module");
route_bgp_destroy(instance);
topo_bgp_destroy(instance);
instance->bgp = NULL;
}

4
src/utun_instance.h

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

2
tests/test_bgp_route_exchange.c

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

16
tests/test_bgp_triangle.c

@ -43,8 +43,8 @@
#include "../src/utun_instance.h"
#include "../src/routing.h"
#include "../src/route_lib.h"
#include "../src/route_bgp.h"
#include "../src/route_node.h"
#include "../src/topo_bgp.h"
#include "../src/topo_node.h"
#include "../src/dummynet.h"
#include "../src/tun_if.h"
#include "../src/secure_channel.h"
@ -122,22 +122,22 @@ 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) {
if (!inst || !inst->bgp || !inst->bgp->nodes) return 0;
return nodeinfo_find_by_id(inst->bgp, node_id) != NULL;
return topo_node_find_by_id(inst->bgp, node_id) != NULL;
}
static int node_path_count(struct UTUN_INSTANCE* inst, uint64_t node_id) {
struct NODEINFO_Q* nq = nodeinfo_find_by_id(inst->bgp, node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(inst->bgp, node_id);
if (!nq || !nq->paths) return 0;
return queue_entry_count(nq->paths);
}
static int node_path_has_peer(struct UTUN_INSTANCE* inst, uint64_t node_id, uint64_t peer_id) {
struct NODEINFO_Q* nq = nodeinfo_find_by_id(inst->bgp, node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(inst->bgp, node_id);
if (!nq || !nq->paths) return 0;
struct ll_entry* e = nq->paths->head;
while (e) {
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e;
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH));
struct TOPO_NODEPATH* path = (struct TOPO_NODEPATH*)e;
uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct TOPO_NODEPATH));
for (uint8_t i = 0; i < path->hop_count; i++)
if (hop[i] == peer_id) return 1;
e = e->next;
@ -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) {
struct NODEINFO_Q* nq = nodeinfo_find_by_id(inst->bgp, node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(inst->bgp, node_id);
return nq ? nq->last_ver : -1;
}

10
tests/test_conn_mgr.c

@ -4,7 +4,7 @@
*
* Test 1: Direct via existing ETCP conn → CONN_TYPE_DIRECT
* Test 2: Status check → state/type
* Test 3: Alien node → NODEINFO_Q.alien=1
* Test 3: Alien node → TOPO_NODEQ.alien=1
*
* Pending:
* Test 4: New link UP callback (INIT to new peer via conn_mgr)
@ -26,7 +26,7 @@
#include "../src/config_parser.h"
#include "../src/config_updater.h"
#include "../src/utun_instance.h"
#include "../src/route_bgp.h"
#include "../src/topo_bgp.h"
#include "../src/conn_mgr.h"
#include "../lib/u_async.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) {
(void)arg; if (result) return;
if (!nodeinfo_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(g_a->bgp, 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);
conn_mgr_connect_node(g_a->conn_mgr, NID_B, 0, ccb, NULL);
uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test2, "t2a");
@ -91,9 +91,9 @@ static void test2(void* arg) {
static void test3(void* arg) {
(void)arg;
uint64_t aid = 0xEEEE000000000001ULL;
struct NODEINFO 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));
struct NODEINFO_Q* nq = nodeinfo_find_by_id(g_a->bgp, aid);
struct TOPO_NODEQ* nq = topo_node_find_by_id(g_a->bgp, aid);
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");
else { fail("alien flag not set"); return; }

30
tests/test_etcp_connect.c

@ -14,8 +14,8 @@
#include "../src/config_parser.h"
#include "../src/config_updater.h"
#include "../src/utun_instance.h"
#include "../src/route_bgp.h"
#include "../src/route_node.h"
#include "../src/topo_bgp.h"
#include "../src/topo_node.h"
#include "../src/secure_channel.h"
#include "../lib/u_async.h"
#include "../lib/ll_queue.h"
@ -63,20 +63,20 @@ static volatile int cb_type = 0, cb_conn_ok = 0, cb_count = 0;
static void connect_ccb(void* a, struct ETCP_CONN* conn, int type) { cb_type = type; cb_conn_ok = (conn != NULL); cb_count++; }
/* ----- helper: create minimal NODEINFO_Q with 1 v4 addr ----- */
static struct NODEINFO_Q* mknode(uint64_t nid, const uint8_t pubkey[32],
/* ----- helper: create minimal TOPO_NODEQ with 1 v4 addr ----- */
static struct TOPO_NODEQ* mknode(uint64_t nid, const uint8_t pubkey[32],
uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port) {
struct NODEINFO_Q* nq = u_calloc(1, sizeof(struct NODEINFO_Q));
struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO));
struct TOPO_NODEQ* nq = u_calloc(1, sizeof(struct TOPO_NODEQ));
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
if (!nq || !ni) { u_free(nq); u_free(ni); return NULL; }
ni->ref_count = 1; ni->node_id = nid; ni->ver = 0;
memcpy(ni->public_key, pubkey, SC_PUBKEY_SIZE);
nq->ll.size = sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry);
nq->ll.size = sizeof(struct TOPO_NODEQ) - sizeof(struct ll_entry);
nq->node = ni; nq->hash_node_id = nid;
struct NI_IPV4_SOCKET_META* sm = u_calloc(1, sizeof(struct NI_IPV4_SOCKET_META));
struct TOPO_SOCKMETA4* sm = u_calloc(1, sizeof(struct TOPO_SOCKMETA4));
if (sm) { sm->id = 0; sm->config_type = CFG_SERVER_TYPE_PUBLIC; sm->nat_type = NAT_TYPE_UNKNOWN; sm->next = ni->v4_sock_meta; ni->v4_sock_meta = sm; }
struct NI_IPV4_ADDR* addr = u_calloc(1, sizeof(struct NI_IPV4_ADDR));
if (addr) { addr->addr[0] = a; addr->addr[1] = b; addr->addr[2] = c; addr->addr[3] = d; addr->port = port; addr->type = ADDR_TYPE_INTERFACE; addr->socket_id = 0; addr->next = ni->v4_addrs; ni->v4_addrs = addr; }
struct TOPO_ADDR4* addr = u_calloc(1, sizeof(struct TOPO_ADDR4));
if (addr) { addr->addr[0] = a; addr->addr[1] = b; addr->addr[2] = c; addr->addr[3] = d; addr->port = port; addr->type = TOPO_ADDR_INTERFACE; addr->socket_id = 0; addr->next = ni->v4_addrs; ni->v4_addrs = addr; }
return nq;
}
@ -84,7 +84,7 @@ static struct NODEINFO_Q* mknode(uint64_t nid, const uint8_t pubkey[32],
static void test1(void* arg) {
(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; }
struct NODEINFO_Q* nb = nodeinfo_find_by_id(g_a->bgp, NID_B);
struct TOPO_NODEQ* nb = topo_node_find_by_id(g_a->bgp, NID_B);
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);
cb_type = 0; cb_conn_ok = 0; cb_count = 0;
@ -108,7 +108,7 @@ static void test3(void* arg) {
fprintf(stderr, "Test 3: unreachable node → error\n"); fflush(stderr);
struct SC_MYKEYS fk; sc_generate_keypair(&fk);
uint64_t fnid = 0xF000000000000001ULL;
struct NODEINFO_Q* 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; }
queue_data_put_with_index(g_a->bgp->nodes, &fn->ll);
g_a->etcp_connect_timeout_tb = 2000;
@ -138,7 +138,7 @@ static void test5(void* arg) {
fprintf(stderr, "Test 5: double connect to unreachable → both callbacks\n"); fflush(stderr);
struct SC_MYKEYS fk; sc_generate_keypair(&fk);
uint64_t fnid = 0xF000000000000002ULL;
struct NODEINFO_Q* 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; }
queue_data_put_with_index(g_a->bgp->nodes, &fn->ll);
g_a->etcp_connect_timeout_tb = 2000;
@ -159,7 +159,7 @@ static void test6(void* arg) {
/* ======================== Test 7: EARLY-only flag ======================== */
static void test7(void* arg) {
(void)arg; if (result) return;
struct NODEINFO_Q* nb = nodeinfo_find_by_id(g_a->bgp, NID_B);
struct TOPO_NODEQ* nb = topo_node_find_by_id(g_a->bgp, NID_B);
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);
cb_type = 0; cb_conn_ok = 0; cb_count = 0;
@ -179,7 +179,7 @@ static void test8(void* arg) {
/* ======================== Test 9: LATE-only flag ======================== */
static void test9(void* arg) {
(void)arg; if (result) return;
struct NODEINFO_Q* nb = nodeinfo_find_by_id(g_a->bgp, NID_B);
struct TOPO_NODEQ* nb = topo_node_find_by_id(g_a->bgp, NID_B);
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);
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/secure_channel.h"
#include "../src/pkt_normalizer.h"
#include "../src/route_bgp.h"
#include "../src/topo_bgp.h"
#include "../lib/u_async.h"
#include "../lib/ll_queue.h"
#include "../lib/debug_config.h"

28
tests/test_etcp_router_reconnect.c

@ -20,8 +20,8 @@
#include "../src/etcp_connections.h"
#include "../src/etcp_router.h"
#include "../src/etcp_api.h"
#include "../src/route_bgp.h"
#include "../src/route_node.h"
#include "../src/topo_bgp.h"
#include "../src/topo_node.h"
#include "../src/config_parser.h"
#include "../src/utun_instance.h"
#include "../src/routing.h"
@ -78,18 +78,18 @@ static void gen_payload(uint32_t seq, uint8_t* buf, int len) {
for (int i=0;i<len;i++) buf[i]=(uint8_t)((i^seq^0xA5)&0xFF);
}
static struct NODEINFO_Q* mknode(uint64_t nid, const uint8_t pubkey[32],
static struct TOPO_NODEQ* mknode(uint64_t nid, const uint8_t pubkey[32],
uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port) {
struct NODEINFO_Q* nq = u_calloc(1, sizeof(struct NODEINFO_Q));
struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO));
struct TOPO_NODEQ* nq = u_calloc(1, sizeof(struct TOPO_NODEQ));
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
if (!nq || !ni) { u_free(nq); u_free(ni); return NULL; }
ni->ref_count = 1; ni->node_id = nid; ni->ver = 0;
memcpy(ni->public_key, pubkey, SC_PUBKEY_SIZE);
nq->node = ni; nq->hash_node_id = nid;
struct NI_IPV4_SOCKET_META* sm = u_calloc(1, sizeof(struct NI_IPV4_SOCKET_META));
struct TOPO_SOCKMETA4* sm = u_calloc(1, sizeof(struct TOPO_SOCKMETA4));
if (sm) { sm->id = 0; sm->config_type = CFG_SERVER_TYPE_PUBLIC; sm->nat_type = NAT_TYPE_UNKNOWN; sm->next = ni->v4_sock_meta; ni->v4_sock_meta = sm; }
struct NI_IPV4_ADDR* addr = u_calloc(1, sizeof(struct NI_IPV4_ADDR));
if (addr) { addr->addr[0] = a; addr->addr[1] = b; addr->addr[2] = c; addr->addr[3] = d; addr->port = port; addr->type = ADDR_TYPE_INTERFACE; addr->socket_id = 0; addr->next = ni->v4_addrs; ni->v4_addrs = addr; }
struct TOPO_ADDR4* addr = u_calloc(1, sizeof(struct TOPO_ADDR4));
if (addr) { addr->addr[0] = a; addr->addr[1] = b; addr->addr[2] = c; addr->addr[3] = d; addr->port = port; addr->type = TOPO_ADDR_INTERFACE; addr->socket_id = 0; addr->next = ni->v4_addrs; ni->v4_addrs = addr; }
return nq;
}
@ -172,7 +172,7 @@ static void state_step(void) {
switch (g_state) {
case ST_INIT:
if (g_bgp_ready_mask == 3) {
struct ETCP_CONN* rc = route_bgp_find_conn_for_node(g_a->bgp, node_c);
struct ETCP_CONN* rc = topo_bgp_find_conn_for_node(g_a->bgp, node_c);
if (rc) g_state=ST_PHASE1_SEND;
}
break;
@ -196,15 +196,15 @@ static void state_step(void) {
g_b=utun_instance_create(ua,b_conf);
if (!g_b||utun_instance_init(g_b)<0) { fprintf(stderr,"FAIL: b restart\n"); g_test_ok=-1; g_fail_code=20; return; }
g_b->etcp_connect_timeout_tb = 300000;
struct NODEINFO_Q* nq_a = mknode(node_a, keys_a.public_key, 127,0,0,1, (uint16_t)a_port);
struct NODEINFO_Q* nq_c = mknode(node_c, keys_c.public_key, 127,0,0,1, (uint16_t)c_port);
struct TOPO_NODEQ* nq_a = mknode(node_a, keys_a.public_key, 127,0,0,1, (uint16_t)a_port);
struct TOPO_NODEQ* nq_c = mknode(node_c, keys_c.public_key, 127,0,0,1, (uint16_t)c_port);
if (!nq_a || !nq_c) { fprintf(stderr,"FAIL: mknode\n"); g_test_ok=-1; return; }
static int cc_a=0,cc_c=1;
etcp_connect(g_b,nq_a,connect_bgp_ready_cb,&cc_a,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) {
struct ETCP_CONN* rc = route_bgp_find_conn_for_node(g_a->bgp, node_c);
struct ETCP_CONN* rc = topo_bgp_find_conn_for_node(g_a->bgp, node_c);
if (rc) { g_phase_sent=0; g_state=ST_PHASE3_SEND; }
}
break;
@ -244,8 +244,8 @@ int main(void) {
g_b=utun_instance_create(ua,b_conf); if(!g_b||utun_instance_init(g_b)<0){fprintf(stderr,"FAIL: b\n");goto fail;}
etcp_router_bind(g_c, TEST_SVC_ID, recv_handler);
struct NODEINFO_Q* nq_a = mknode(node_a, keys_a.public_key, 127,0,0,1, (uint16_t)a_port);
struct NODEINFO_Q* nq_c = mknode(node_c, keys_c.public_key, 127,0,0,1, (uint16_t)c_port);
struct TOPO_NODEQ* nq_a = mknode(node_a, keys_a.public_key, 127,0,0,1, (uint16_t)a_port);
struct TOPO_NODEQ* nq_c = mknode(node_c, keys_c.public_key, 127,0,0,1, (uint16_t)c_port);
if (!nq_a || !nq_c) { fprintf(stderr,"FAIL: mknode\n"); goto fail; }
g_b->etcp_connect_timeout_tb = 300000;
{ static int cc_a=0,cc_c=1;

12
tests/test_etcp_router_unit.c

@ -11,7 +11,7 @@
#include "../src/etcp.h"
#include "../src/etcp_api.h"
#include "../src/etcp_router.h"
#include "../src/route_bgp.h"
#include "../src/topo_bgp.h"
#include "../src/utun_instance.h"
#include "../lib/u_async.h"
#include "../lib/ll_queue.h"
@ -140,18 +140,18 @@ static int setup_sign_keys(void) {
}
static void setup_bgp_for_sign_test(struct UTUN_INSTANCE* inst, int with_ed25519_key) {
struct ROUTE_BGP* bgp = u_calloc(1, sizeof(struct ROUTE_BGP));
struct TOPO_BGP* bgp = u_calloc(1, sizeof(struct TOPO_BGP));
if (!bgp) { printf(" setup_bgp: u_calloc failed\n"); return; }
bgp->instance = inst;
bgp->nodes = queue_new(inst->ua, BGP_NODES_HASH_SIZE,
offsetof(struct NODEINFO_Q, hash_node_id) - sizeof(struct ll_entry), 8, "bgp_nodes_test");
offsetof(struct TOPO_NODEQ, hash_node_id) - sizeof(struct ll_entry), 8, "bgp_nodes_test");
if (!bgp->nodes) { printf(" setup_bgp: queue_new failed\n"); u_free(bgp); return; }
inst->bgp = bgp;
struct NODEINFO_Q* nq = u_calloc(1, sizeof(struct NODEINFO_Q));
struct TOPO_NODEQ* nq = u_calloc(1, sizeof(struct TOPO_NODEQ));
if (!nq) { printf(" setup_bgp: nq alloc failed\n"); return; }
nq->ll.size = sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry);
struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO));
nq->ll.size = sizeof(struct TOPO_NODEQ) - sizeof(struct ll_entry);
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
if (!ni) { printf(" setup_bgp: ni alloc failed\n"); u_free(nq); return; }
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);

30
tests/test_ipv6_sockets.c

@ -34,8 +34,8 @@
#include "../src/utun_instance.h"
#include "../src/routing.h"
#include "../src/route_lib.h"
#include "../src/route_bgp.h"
#include "../src/route_node.h"
#include "../src/topo_bgp.h"
#include "../src/topo_node.h"
#include "../src/tun_if.h"
#include "../src/secure_channel.h"
#include "../lib/u_async.h"
@ -140,7 +140,7 @@ static int verify_ipv6_local_nodeinfo(const char* name, struct UTUN_INSTANCE* in
printf("FAIL [%s]: no bgp/local_node\n", name);
return 0;
}
struct NODEINFO* ni = inst->bgp->local_node->node;
struct TOPO_NODE* ni = inst->bgp->local_node->node;
struct ETCP_SOCKET* es = inst->etcp_sockets;
int v6_sock_found = 0;
@ -148,35 +148,35 @@ static int verify_ipv6_local_nodeinfo(const char* name, struct UTUN_INSTANCE* in
if (!v6_sock_found) { printf("FAIL [%s]: no AF_INET6 socket\n", name); return 0; }
printf("PASS [%s]: AF_INET6 socket exists\n", name);
int v6s = ni_list_count((struct _ni_head*)ni->v6_sock_meta);
int v6s = topo_list_count((struct _topo_head*)ni->v6_sock_meta);
if (v6s != expect_socks) { printf("FAIL [%s]: v6_socks=%d expected=%d\n", name, v6s, expect_socks); return 0; }
printf("PASS [%s]: v6_sockets=%d\n", name, v6s);
int v6a = ni_list_count((struct _ni_head*)ni->v6_addrs);
int v6a = topo_list_count((struct _topo_head*)ni->v6_addrs);
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);
int v6sub = inst->bgp->local_node->routes ? ni_list_count((struct _ni_head*)inst->bgp->local_node->routes->v6_subnets) : 0;
int v6sub = inst->bgp->local_node->subnets ? topo_list_count((struct _topo_head*)inst->bgp->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; }
printf("PASS [%s]: v6_subnets=%d\n", name, v6sub);
{ const struct NI_IPV6_SOCKET_META* m = ni->v6_sock_meta; int i = 0;
{ const struct TOPO_SOCKMETA6* m = ni->v6_sock_meta; int i = 0;
while (m) {
if (m->config_type != CFG_SERVER_TYPE_PUBLIC) { printf("FAIL [%s]: v6 socket meta[%d] config_type=%d expected=%d\n", name, i, m->config_type, CFG_SERVER_TYPE_PUBLIC); return 0; }
printf("PASS [%s]: v6 socket meta[%d] id=%d config=%d nat=%d\n", name, i, m->id, m->config_type, m->nat_type);
i++; m = m->next;
}
}
{ const struct NI_IPV6_ADDR* a = ni->v6_addrs; int i = 0;
{ const struct TOPO_ADDR6* a = ni->v6_addrs; int i = 0;
while (a) {
if (a->port == 0) { printf("FAIL [%s]: v6 addr port=0\n", name); return 0; }
if (a->type != ADDR_TYPE_INTERFACE) { printf("FAIL [%s]: v6 addr[%d] type=%d expected=%d(INTERFACE)\n", name, i, a->type, ADDR_TYPE_INTERFACE); return 0; }
if (a->type != TOPO_ADDR_INTERFACE) { printf("FAIL [%s]: v6 addr[%d] type=%d expected=%d(INTERFACE)\n", name, i, a->type, TOPO_ADDR_INTERFACE); return 0; }
printf("PASS [%s]: v6 addr[%d] port=%d type=%d socket_id=%d\n", name, i, a->port, a->type, a->socket_id);
i++; a = a->next;
}
}
if (expect_subnets > 0 && inst->bgp->local_node->routes) {
const struct NI_IPV6_SUBNET* subs = inst->bgp->local_node->routes->v6_subnets;
if (expect_subnets > 0 && inst->bgp->local_node->subnets) {
const struct TOPO_SUBNET6* subs = inst->bgp->local_node->subnets->v6_subnets;
if (subs) {
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; }
@ -189,17 +189,17 @@ 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) {
if (!inst || !inst->bgp) { printf("FAIL [%s]: no bgp\n", name); return 0; }
struct NODEINFO_Q* nq = nodeinfo_find_by_id(inst->bgp, peer_node_id);
struct TOPO_NODEQ* nq = topo_node_find_by_id(inst->bgp, 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; }
printf("PASS [%s]: remote node %016llx found\n", name, (unsigned long long)peer_node_id);
if (!nq->node->v6_sock_meta) { printf("FAIL [%s]: remote node has no v6 sockets\n", name); return 0; }
printf("PASS [%s]: remote node v6_sockets=%d\n", name, ni_list_count((struct _ni_head*)nq->node->v6_sock_meta));
printf("PASS [%s]: remote node v6_sockets=%d\n", name, topo_list_count((struct _topo_head*)nq->node->v6_sock_meta));
if (!nq->node->v6_addrs) { printf("FAIL [%s]: remote node has no v6 addrs\n", name); return 0; }
printf("PASS [%s]: remote node v6_addrs=%d\n", name, ni_list_count((struct _ni_head*)nq->node->v6_addrs));
printf("PASS [%s]: remote node v6_addrs=%d\n", name, topo_list_count((struct _topo_head*)nq->node->v6_addrs));
const struct NI_IPV6_ADDR* a = nq->node->v6_addrs;
const struct TOPO_ADDR6* a = nq->node->v6_addrs;
if (a) {
uint8_t loopback[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
if (memcmp(a->addr, loopback, 16) != 0) { printf("FAIL [%s]: remote v6 addr not ::1\n", name); return 0; }

32
tests/test_nat_detection.c

@ -21,9 +21,9 @@
#include "../src/config_updater.h"
#include "../src/utun_instance.h"
#include "../src/routing.h"
#include "../src/route_bgp.h"
#include "../src/topo_bgp.h"
#include "../src/route_ping.h"
#include "../src/route_node.h"
#include "../src/topo_node.h"
#include "../src/tun_if.h"
#include "../src/secure_channel.h"
#include "../lib/u_async.h"
@ -216,7 +216,7 @@ int main(void) {
}
// Разрешаем NAT check для localhost (для теста)
if (inst_s->bgp) route_bgp_set_nat_check_local(inst_s->bgp, 1);
if (inst_s->bgp) topo_bgp_set_nat_check_local(inst_s->bgp, 1);
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");
@ -244,16 +244,16 @@ int main(void) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for BGP exchange (S learns C1 and C2)...");
int bgp_wait_cycles = 0;
while (!test_timed_out && bgp_wait_cycles < 500) {
if (inst_s->bgp && nodeinfo_find_by_id(inst_s->bgp, NODE_ID_C1) != NULL &&
nodeinfo_find_by_id(inst_s->bgp, NODE_ID_C2) != NULL) {
if (inst_s->bgp && topo_node_find_by_id(inst_s->bgp, NODE_ID_C1) != NULL &&
topo_node_find_by_id(inst_s->bgp, NODE_ID_C2) != NULL) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "S learned about C1 and C2");
break;
}
uasync_poll(ua, 10);
bgp_wait_cycles++;
}
if (!inst_s->bgp || nodeinfo_find_by_id(inst_s->bgp, NODE_ID_C1) == NULL ||
nodeinfo_find_by_id(inst_s->bgp, NODE_ID_C2) == NULL) {
if (!inst_s->bgp || topo_node_find_by_id(inst_s->bgp, NODE_ID_C1) == NULL ||
topo_node_find_by_id(inst_s->bgp, NODE_ID_C2) == NULL) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "S did not learn about C1/C2 in time");
goto cleanup;
}
@ -313,9 +313,9 @@ int main(void) {
}
// 5. Verify all NAT fields on server
struct NODEINFO_Q* node_c1 = nodeinfo_find_by_id(inst_s->bgp, NODE_ID_C1);
struct TOPO_NODEQ* node_c1 = topo_node_find_by_id(inst_s->bgp, NODE_ID_C1);
if (!node_c1) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "NODEINFO_Q for C1 disappeared");
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "TOPO_NODEQ for C1 disappeared");
goto cleanup;
}
if (link_sc1->nat_check_status != NAT_CHECK_EIM) {
@ -363,7 +363,7 @@ int main(void) {
// 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) {
int found = 0;
for (const struct NI_IPV4_SOCKET_META* m = inst_c1->bgp->local_node->node->v4_sock_meta; m; m = m->next) {
for (const struct TOPO_SOCKMETA4* m = inst_c1->bgp->local_node->node->v4_sock_meta; m; m = m->next) {
if (m->id == sock_c1->sock_id) {
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);
@ -375,8 +375,8 @@ int main(void) {
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
int nat_found = 0;
for (const struct NI_IPV4_ADDR* a = inst_c1->bgp->local_node->node->v4_addrs; a; a = a->next) {
if (a->type == ADDR_TYPE_NAT && a->socket_id == sock_c1->sock_id) {
for (const struct TOPO_ADDR4* a = inst_c1->bgp->local_node->node->v4_addrs; a; a = a->next) {
if (a->type == TOPO_ADDR_NAT && a->socket_id == sock_c1->sock_id) {
uint32_t addr_ip; memcpy(&addr_ip, a->addr, 4);
if (addr_ip != link_sc1->nat_ip || a->port != link_sc1->nat_port) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: NAT addr mismatch in local_node: addr=%08x nat_ip=%08x port=%u nat_port=%u",
@ -395,9 +395,9 @@ int main(void) {
bgp_wait_cycles = 0;
int c2_verified_nat = 0;
while (!test_timed_out && bgp_wait_cycles < 500) {
struct NODEINFO_Q* node_c1_on_c2 = inst_c2->bgp ? nodeinfo_find_by_id(inst_c2->bgp, NODE_ID_C1) : NULL;
struct TOPO_NODEQ* node_c1_on_c2 = inst_c2->bgp ? topo_node_find_by_id(inst_c2->bgp, NODE_ID_C1) : NULL;
if (node_c1_on_c2 && node_c1_on_c2->node) {
for (const struct NI_IPV4_SOCKET_META* 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 (c2_verified_nat) break;
@ -459,14 +459,14 @@ int main(void) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for C2 to learn C1 nodeinfo...");
bgp_wait_cycles = 0;
while (!test_timed_out && bgp_wait_cycles < 500) {
if (inst_c2->bgp && nodeinfo_find_by_id(inst_c2->bgp, NODE_ID_C1) != NULL) {
if (inst_c2->bgp && topo_node_find_by_id(inst_c2->bgp, NODE_ID_C1) != NULL) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "C2 learned C1 nodeinfo");
break;
}
uasync_poll(ua, 10);
bgp_wait_cycles++;
}
if (!inst_c2->bgp || nodeinfo_find_by_id(inst_c2->bgp, NODE_ID_C1) == NULL) {
if (!inst_c2->bgp || topo_node_find_by_id(inst_c2->bgp, NODE_ID_C1) == NULL) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: C2 did not learn C1 nodeinfo in time");
goto cleanup;
}

6
tests/test_nat_transport.c

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

54
tests/test_route6_lib.c

@ -3,7 +3,7 @@
#include <string.h>
#include <time.h>
#include <assert.h>
#include "../src/route_node.h"
#include "../src/topo_node.h"
#include "../src/route6_lib.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
@ -19,20 +19,20 @@ static int tests_run = 0;
/* ──── helpers ──── */
static struct NODEINFO_Q *make_node(uint64_t node_id,
static struct TOPO_NODEQ *make_node(uint64_t node_id,
const uint8_t addrs[][16],
const uint8_t *plens, int N) {
struct NODEINFO_Q *nq = u_calloc(1, sizeof(*nq));
struct NODEINFO *ni = u_calloc(1, sizeof(struct NODEINFO));
struct TOPO_NODEQ *nq = u_calloc(1, sizeof(*nq));
struct TOPO_NODE *ni = u_calloc(1, sizeof(struct TOPO_NODE));
if (!nq || !ni) { u_free(nq); u_free(ni); return NULL; }
ni->ref_count = 1; ni->node_id = node_id;
nq->node = ni; nq->hash_node_id = node_id;
if (N > 0) {
struct NODEINFO_ROUTES *r = u_calloc(1, sizeof(struct NODEINFO_ROUTES));
nq->routes = r;
struct NI_IPV6_SUBNET *head = NULL;
struct TOPO_NODESUBNETS *r = u_calloc(1, sizeof(struct TOPO_NODESUBNETS));
nq->subnets = r;
struct TOPO_SUBNET6 *head = NULL;
for (int i = N-1; i >= 0; i--) {
struct NI_IPV6_SUBNET *s = u_calloc(1, sizeof(struct NI_IPV6_SUBNET));
struct TOPO_SUBNET6 *s = u_calloc(1, sizeof(struct TOPO_SUBNET6));
memcpy(s->addr, addrs[i], 16); s->prefix_length = plens[i];
s->next = head; head = s;
}
@ -41,12 +41,12 @@ static struct NODEINFO_Q *make_node(uint64_t node_id,
return nq;
}
static void free_node(struct NODEINFO_Q *nq) {
static void free_node(struct TOPO_NODEQ *nq) {
if (nq) {
if (nq->routes) {
struct NI_IPV6_SUBNET *s = nq->routes->v6_subnets;
while (s) { struct NI_IPV6_SUBNET *next = s->next; u_free(s); s = next; }
u_free(nq->routes);
if (nq->subnets) {
struct TOPO_SUBNET6 *s = nq->subnets->v6_subnets;
while (s) { struct TOPO_SUBNET6 *next = s->next; u_free(s); s = next; }
u_free(nq->subnets);
}
if (nq->node) u_free(nq->node);
u_free(nq);
@ -69,7 +69,7 @@ static void test_insert_null_args(void) {
assert(t != NULL);
assert(route6_insert(NULL, NULL) == false);
assert(route6_insert(t, NULL) == false);
assert(route6_insert(NULL, t ? (struct NODEINFO_Q*)(uintptr_t)t : NULL) == false);
assert(route6_insert(NULL, t ? (struct TOPO_NODEQ*)(uintptr_t)t : NULL) == false);
route6_table_destroy(t);
uasync_destroy(ua, 0);
}
@ -81,7 +81,7 @@ static void test_insert_zero_subnets(void) {
int addr[16] = {0};
uint8_t zero_plen = 0;
struct NODEINFO_Q *nq = make_node(1, (const uint8_t(*)[16])addr, &zero_plen, 0);
struct TOPO_NODEQ *nq = make_node(1, (const uint8_t(*)[16])addr, &zero_plen, 0);
assert(route6_insert(t, nq) == false);
const uint8_t any[16] = {0};
@ -99,7 +99,7 @@ static void test_insert_duplicate(void) {
uint8_t addr[16] = {0xfd, 0};
uint8_t plen = 64;
struct NODEINFO_Q *nq = make_node(10, &addr, &plen, 1);
struct TOPO_NODEQ *nq = make_node(10, &addr, &plen, 1);
assert(route6_insert(t, nq) == true);
assert(route6_insert(t, nq) == true); // re-insert should not crash
@ -117,7 +117,7 @@ static void test_insert_delete_reinsert(void) {
uint8_t addrs[2][16] = {{0xfd, 1}, {0xfd, 2}};
uint8_t plens[2] = {64, 64};
struct NODEINFO_Q *nq = make_node(20, addrs, plens, 2);
struct TOPO_NODEQ *nq = make_node(20, addrs, plens, 2);
assert(route6_insert(t, nq) == true);
assert(route6_lookup(t, addrs[0]) != NULL);
@ -146,8 +146,8 @@ static void test_delete_nonexistent(void) {
uint8_t addr[16] = {0xfd, 10};
uint8_t plen = 64;
struct NODEINFO_Q *nq1 = make_node(1, &addr, &plen, 1);
struct NODEINFO_Q *nq2 = make_node(2, &addr, &plen, 1);
struct TOPO_NODEQ *nq1 = make_node(1, &addr, &plen, 1);
struct TOPO_NODEQ *nq2 = make_node(2, &addr, &plen, 1);
assert(route6_insert(t, nq1) == true);
route6_delete(t, nq2); // nq2 not in table — should not crash
@ -165,7 +165,7 @@ static void test_delete_null_args(void) {
route6_delete(NULL, NULL);
route6_delete(t, NULL);
route6_delete(NULL, (struct NODEINFO_Q*)(uintptr_t)t);
route6_delete(NULL, (struct TOPO_NODEQ*)(uintptr_t)t);
route6_table_destroy(t);
uasync_destroy(ua, 0);
@ -178,7 +178,7 @@ static void test_delete_multi_subnet(void) {
uint8_t addrs[3][16] = {{0xfc, 1}, {0xfc, 2}, {0xfc, 3}};
uint8_t plens[3] = {48, 56, 64};
struct NODEINFO_Q *nq = make_node(30, addrs, plens, 3);
struct TOPO_NODEQ *nq = make_node(30, addrs, plens, 3);
assert(route6_insert(t, nq) == true);
assert(route6_lookup(t, addrs[0]) != NULL);
@ -204,8 +204,8 @@ static void test_delete_one_of_two(void) {
uint8_t addr_a[16] = {0xfc, 0};
uint8_t addr_b[16] = {0xfd, 0};
uint8_t plen = 64;
struct NODEINFO_Q *nqa = make_node(100, &addr_a, &plen, 1);
struct NODEINFO_Q *nqb = make_node(200, &addr_b, &plen, 1);
struct TOPO_NODEQ *nqa = make_node(100, &addr_a, &plen, 1);
struct TOPO_NODEQ *nqb = make_node(200, &addr_b, &plen, 1);
assert(route6_insert(t, nqa) == true);
assert(route6_insert(t, nqb) == true);
@ -240,7 +240,7 @@ static void test_lookup_returns_correct_data(void) {
uint8_t addr[16] = {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
uint8_t plen = 64;
struct NODEINFO_Q *nq = make_node(42, &addr, &plen, 1);
struct TOPO_NODEQ *nq = make_node(42, &addr, &plen, 1);
assert(route6_insert(t, nq) == true);
const struct ROUTE6_DATA *rd = route6_lookup(t, addr);
@ -301,7 +301,7 @@ static void test_stress(void) {
struct saved_route sr[MAX_SAVED];
int nsr = 0;
struct NODEINFO_Q *nodes[STRESS_NODES + STRESS_OPS];
struct TOPO_NODEQ *nodes[STRESS_NODES + STRESS_OPS];
// create nodes with random subnets
int n_created = 0;
@ -392,7 +392,7 @@ static void test_stress(void) {
{
uint8_t addr[16] = {0xfc, 0};
uint8_t plen = 64;
struct NODEINFO_Q *ghost = make_node(999999, &addr, &plen, 1);
struct TOPO_NODEQ *ghost = make_node(999999, &addr, &plen, 1);
route6_delete(t, ghost); // should no-op
free_node(ghost);
}
@ -401,7 +401,7 @@ static void test_stress(void) {
{
uint8_t addr[16] = {0};
uint8_t zero_plen = 0;
struct NODEINFO_Q *z = make_node(777, (const uint8_t(*)[16])addr, &zero_plen, 0);
struct TOPO_NODEQ *z = make_node(777, (const uint8_t(*)[16])addr, &zero_plen, 0);
assert(route6_insert(t, z) == false);
free_node(z);
}

36
tests/test_route_lib.c

@ -2,7 +2,7 @@
* FULL REFACTORED TEST for new NODEINFO-based routing system
*
* Tests:
* - NODEINFO_Q creation and insertion
* - TOPO_NODEQ creation and insertion
* - paths management (add/remove)
* - versioning (ver field)
* - WITHDRAW when no paths left
@ -20,7 +20,7 @@
#include <time.h>
//#include "../src/utun_instance.h"
#include "route_node.h"
#include "topo_node.h"
#include "route_lib.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
@ -37,14 +37,14 @@ struct ETCP_CONN {
struct UTUN_INSTANCE {
uint64_t node_id;
struct ROUTE_TABLE* rt;
struct ROUTE_BGP* bgp;
struct TOPO_BGP* bgp;
};
/* Helper to create test NODEINFO_Q with subnet in linked list */
static struct NODEINFO_Q* create_test_node(uint64_t node_id, uint8_t ver, uint32_t subnet_net, uint8_t prefix) {
struct NODEINFO_Q* nq = u_calloc(1, sizeof(struct NODEINFO_Q));
/* Helper to create test TOPO_NODEQ with subnet in linked list */
static struct TOPO_NODEQ* create_test_node(uint64_t node_id, uint8_t ver, uint32_t subnet_net, uint8_t prefix) {
struct TOPO_NODEQ* nq = u_calloc(1, sizeof(struct TOPO_NODEQ));
if (!nq) return NULL;
struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO));
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
if (!ni) { u_free(nq); return NULL; }
ni->ref_count = 1;
ni->node_id = htobe64(node_id);
@ -53,21 +53,21 @@ static struct NODEINFO_Q* create_test_node(uint64_t node_id, uint8_t ver, uint32
nq->hash_node_id = ni->node_id;
nq->hop_count = 0;
nq->paths = queue_new(NULL, 16, 0, 0, "test_paths");
struct NODEINFO_ROUTES* r = u_calloc(1, sizeof(struct NODEINFO_ROUTES));
struct TOPO_NODESUBNETS* r = u_calloc(1, sizeof(struct TOPO_NODESUBNETS));
if (r) {
struct NI_IPV4_SUBNET* sn = u_calloc(1, sizeof(struct NI_IPV4_SUBNET));
struct TOPO_SUBNET4* sn = u_calloc(1, sizeof(struct TOPO_SUBNET4));
uint32_t net = htonl(subnet_net);
memcpy(sn->addr, &net, 4); sn->prefix_length = prefix;
r->v4_subnets = sn;
nq->routes = r;
nq->subnets = r;
}
return nq;
}
static void free_test_node(struct NODEINFO_Q* nq) {
static void free_test_node(struct TOPO_NODEQ* nq) {
if (nq) {
if (nq->paths) queue_free(nq->paths);
if (nq->routes) { u_free(nq->routes->v4_subnets); u_free(nq->routes); }
if (nq->subnets) { u_free(nq->subnets->v4_subnets); u_free(nq->subnets); }
if (nq->node) { u_free(nq->node->node_name); u_free(nq->node); }
u_free(nq);
}
@ -118,9 +118,9 @@ static void test_table_create_destroy(void) {
}
static void test_nodeinfo_insert(void) {
TEST("NODEINFO_Q insert into routing table");
TEST("TOPO_NODEQ insert into routing table");
struct ROUTE_TABLE *t = route_table_create();
struct NODEINFO_Q* nq = create_test_node(0x12345678ULL, 1, 0x0a000000, 8);
struct TOPO_NODEQ* nq = create_test_node(0x12345678ULL, 1, 0x0a000000, 8);
bool inserted = route_insert(t, nq);
ASSERT(inserted, "insert nodeinfo");
@ -134,8 +134,8 @@ static void test_nodeinfo_insert(void) {
static void test_versioning(void) {
TEST("NODEINFO multiple nodes");
struct ROUTE_TABLE *t = route_table_create();
struct NODEINFO_Q* nq1 = create_test_node(0x1111ULL, 5, 0x0a000000, 8);
struct NODEINFO_Q* nq2 = create_test_node(0x2222ULL, 1, 0xac100000, 12);
struct TOPO_NODEQ* nq1 = create_test_node(0x1111ULL, 5, 0x0a000000, 8);
struct TOPO_NODEQ* nq2 = create_test_node(0x2222ULL, 1, 0xac100000, 12);
route_insert(t, nq1);
bool ins2 = route_insert(t, nq2);
@ -157,7 +157,7 @@ static void test_performance_1000_nodes(void) {
for (int i = 0; i < 1000; i++) {
uint32_t sub = 0x0a000000 + (i * 0x100); /* distinct 10.0.x.0/24 to avoid overlap */
struct NODEINFO_Q* nq = create_test_node(0x1000000ULL + i, 1, sub, 24);
struct TOPO_NODEQ* nq = create_test_node(0x1000000ULL + i, 1, sub, 24);
route_insert(t, nq);
/* note: nq not freed here (table holds ref to it), freed in test cleanup if needed */
}
@ -175,7 +175,7 @@ static void test_performance_1000_nodes(void) {
static void test_destroy_refcount(void) {
TEST("destroy with multiple paths (ref_count safety)");
struct ROUTE_TABLE *t = route_table_create();
/* NODEINFO_Q memory managed externally, table only holds pointers */
/* TOPO_NODEQ memory managed externally, table only holds pointers */
route_table_destroy(t);
PASS();
}

10
tests/test_route_ping.c

@ -21,7 +21,7 @@
#include "../src/config_updater.h"
#include "../src/utun_instance.h"
#include "../src/routing.h"
#include "../src/route_bgp.h"
#include "../src/topo_bgp.h"
#include "../src/route_ping.h"
#include "../src/tun_if.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)...");
int bgp_wait_cycles = 0;
while (!test_timed_out && bgp_wait_cycles < 500) {
if (inst_b->bgp && nodeinfo_find_by_id(inst_b->bgp, NODE_ID_C) != NULL) {
if (inst_b->bgp && topo_node_find_by_id(inst_b->bgp, NODE_ID_C) != NULL) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "B learned about C");
break;
}
uasync_poll(ua, 10);
bgp_wait_cycles++;
}
if (!inst_b->bgp || nodeinfo_find_by_id(inst_b->bgp, NODE_ID_C) == NULL) {
if (!inst_b->bgp || topo_node_find_by_id(inst_b->bgp, NODE_ID_C) == NULL) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "B did not learn about C in time");
goto cleanup;
}
@ -271,9 +271,9 @@ int main(void) {
/* addr[] в network byte order, port в host byte order */
uint32_t target_ip = 0;
uint16_t target_port = 0;
struct NODEINFO_Q* nq = inst_b->bgp ? nodeinfo_find_by_id(inst_b->bgp, NODE_ID_C) : NULL;
struct TOPO_NODEQ* nq = inst_b->bgp ? topo_node_find_by_id(inst_b->bgp, NODE_ID_C) : NULL;
if (nq && nq->node) {
const struct NI_IPV4_ADDR* a = nq->node->v4_addrs;
const struct TOPO_ADDR4* a = nq->node->v4_addrs;
if (a) {
memcpy(&target_ip, a->addr, 4);
target_port = a->port;

6
tests/test_stcp_traffic.c

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

6
tools/chatgui/libutun/CMakeLists.txt

@ -56,10 +56,10 @@ set(UTUN_COMMON_SOURCES
${SRC_DIR}/config_updater.c
${SRC_DIR}/route_lib.c
${SRC_DIR}/route6_lib.c
${SRC_DIR}/route_bgp.c
${SRC_DIR}/topo_bgp.c
${SRC_DIR}/route_ping.c
${SRC_DIR}/route_node.c
${SRC_DIR}/route_node_lmdb.c
${SRC_DIR}/topo_node.c
${SRC_DIR}/topo_node_lmdb.c
${SRC_DIR}/route_connectivity.c
${SRC_DIR}/conn_mgr.c
${TRANSPORT_DIR}/db_sync_stub.c

6
tools/chatgui/transport/chat_core.c

@ -12,8 +12,8 @@
#include "../../../src/utun_instance.h"
#include "../../../src/etcp_router.h"
#include "../../../src/etcp_api.h"
#include "../../../src/route_bgp.h"
#include "../../../src/route_node.h"
#include "../../../src/topo_bgp.h"
#include "../../../src/topo_node.h"
#include "../../../src/conn_mgr.h"
#include "../../../src/secure_channel.h"
#include "../../../lib/u_async.h"
@ -625,7 +625,7 @@ void chat_core_connect_from_invite(struct chat_invite* inv) {
}
uint64_t node_id = inv->node_id;
struct ROUTE_BGP* bgp = g_cc.inst->bgp;
struct TOPO_BGP* bgp = g_cc.inst->bgp;
if (nodeinfo_find_by_id(bgp, node_id)) {
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: node 0x%016llx already in BGP, connecting",

4
tools/etcpmon/etcpmon_protocol.h

@ -294,8 +294,8 @@ struct etcpmon_tun_metrics {
uint32_t rt_count; /* Total routes in table */
uint32_t rt_local; /* Local routes */
uint32_t rt_learned; /* Learned routes (BGP) */
uint32_t rt_bgp_senders; /* BGP senders_list count (ROUTE_BGP) */
uint32_t rt_bgp_nodes; /* BGP nodes count (ROUTE_BGP) */
uint32_t rt_bgp_senders; /* BGP senders_list count (TOPO_BGP) */
uint32_t rt_bgp_nodes; /* BGP nodes count (TOPO_BGP) */
};
/* Router congestion metrics — aggregated over all router_conns */

Loading…
Cancel
Save