chat: BGP-driven address sync, member identity verify, join_sig fix
- Адреса узлов вынесены из wire-протокола member_sync/merkle/join/welcome в BGP/topo_group: node_addresses теперь пишет только topo_node_sqlite_addrs_put (источник истины ni->v4/v6_addrs), классификация config_type/nat_type в sockmeta - Жёсткая анти-подделка: node_id=derive(x25519), ed25519 сверяется с доверенной таблицей nodes, NODEINFO node_id/pubkey mismatch отклоняется как forgery - Единые member_sync_build_join_msg (112Б) и member_sync_build_update_msg: устранён баг _verify_join_sig (join_ts по смещению 80 вместо 104, длина 104→112), который рушил приём мемберов; все 7 мест подписи/проверки join_sig через хелпер - Единое обновление своего мембера chat_core_update_my_member (вместо sync_my_addresses) - Android standby: пауза таймеров (broadcast/db_sync/merkle_sync/chat_sync) через standby_wait - name[16] → name[MAX_CONN_NAME_LEN] с truncation-warning в парсере - conn_mgr: etcp_connect_cancel_by_node (use-after-free при отмене invite), промоушен conn в ncd после успешного invite - Android GUI: foreground-gating опросов, сохранение портов интерфейсов, фикс udp-log flush - chatgui: персистентный db_path; мелкие DEBUG-логи epoll/pool
This commit is contained in:
1 parent
c07bd385ca
commit
5c2501b4f3
34 files changed
+808
-882
No files matched your search
@@ -2,6 +2,7 @@
|
||||
#include "topo_node.h"
|
||||
#include "topo_group.h"
|
||||
#include "etcp_connections.h"
|
||||
#include "../config_parser.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include "../lib/mem.h"
|
||||
#include "../lib/memory_pool.h"
|
||||
@@ -30,6 +31,137 @@ static void peers_table_name(const char* ch_id, char* buf, size_t sz) {
|
||||
snprintf(buf, sz, "peers_%s", san);
|
||||
}
|
||||
|
||||
/* ── Классификация адресов (локально, по IP) ── */
|
||||
|
||||
static int addr_type_from_ip(int family, const uint8_t* addr) {
|
||||
if (!addr) return ADDR_TYPE_NETIF;
|
||||
if (family == 4) {
|
||||
uint8_t b0 = addr[0], b1 = addr[1];
|
||||
if (b0 == 0 || b0 == 10 || b0 == 127) return ADDR_TYPE_NETIF;
|
||||
if (b0 == 169 && b1 == 254) return ADDR_TYPE_NETIF;
|
||||
if (b0 >= 224 && b0 <= 239) return ADDR_TYPE_NETIF;
|
||||
if (b0 == 172 && b1 >= 16 && b1 <= 31) return ADDR_TYPE_NETIF;
|
||||
if (b0 == 100 && b1 >= 64 && b1 <= 127) return ADDR_TYPE_NETIF; /* 100.64.0.0/10 (CGNAT) */
|
||||
if (b0 == 192 && b1 == 168) return ADDR_TYPE_NETIF;
|
||||
{ uint32_t ip; memcpy(&ip, addr, 4); if (ip == 0 || ip == 0xffffffff) return ADDR_TYPE_NETIF; }
|
||||
return ADDR_TYPE_DIRECT;
|
||||
} else {
|
||||
if (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) return ADDR_TYPE_NETIF;
|
||||
if (addr[0] == 0xfc || addr[0] == 0xfd) return ADDR_TYPE_NETIF;
|
||||
{ static const uint8_t z[16]; if (!memcmp(addr, z, 16)) return ADDR_TYPE_NETIF; }
|
||||
{ static const uint8_t lb[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; if (!memcmp(addr,lb,16)) return ADDR_TYPE_NETIF; }
|
||||
return ADDR_TYPE_DIRECT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Итоговая классификация: конфиг + автоопределение + IP (всё локально). */
|
||||
static int addr_type_classify(int config_type, int nat_type, int family, const uint8_t* ip) {
|
||||
if (config_type == CFG_SERVER_TYPE_PUBLIC) return ADDR_TYPE_DIRECT;
|
||||
if (config_type == CFG_SERVER_TYPE_PRIVATE || config_type == CFG_SERVER_TYPE_LOCAL) return ADDR_TYPE_NETIF;
|
||||
if (nat_type == NAT_TYPE_EIM) return ADDR_TYPE_NAT_EIM;
|
||||
if (nat_type == NAT_TYPE_STRICT) return ADDR_TYPE_NAT_STRICT;
|
||||
if (nat_type == NAT_TYPE_DIRECT) return ADDR_TYPE_DIRECT;
|
||||
return addr_type_from_ip(family, ip);
|
||||
}
|
||||
|
||||
static void smeta4_lookup(struct TOPO_SOCKMETA4* head, uint8_t sid, uint8_t* cfg, uint8_t* nat) {
|
||||
*cfg = CFG_SERVER_TYPE_UNKNOWN; *nat = NAT_TYPE_UNKNOWN;
|
||||
for (const struct TOPO_SOCKMETA4* m = head; m; m = m->next)
|
||||
if (m->id == sid) { *cfg = m->config_type; *nat = m->nat_type; return; }
|
||||
}
|
||||
|
||||
static void smeta6_lookup(struct TOPO_SOCKMETA6* head, uint8_t sid, uint8_t* cfg, uint8_t* nat) {
|
||||
*cfg = CFG_SERVER_TYPE_UNKNOWN; *nat = NAT_TYPE_UNKNOWN;
|
||||
for (const struct TOPO_SOCKMETA6* m = head; m; m = m->next)
|
||||
if (m->id == sid) { *cfg = m->config_type; *nat = m->nat_type; return; }
|
||||
}
|
||||
|
||||
/* ── Персистенция адресов узла (источник истины — BGP/topo_group) ── */
|
||||
|
||||
int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE* ni) {
|
||||
if (!db || !ni) return -1;
|
||||
sqlite3_exec(db, "BEGIN", NULL, NULL, NULL);
|
||||
|
||||
sqlite3_stmt* ds = NULL;
|
||||
if (sqlite3_prepare_v2(db, "DELETE FROM node_addresses WHERE node_id=?", -1, &ds, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(ds, 1, (sqlite3_int64)node_id);
|
||||
sqlite3_step(ds);
|
||||
sqlite3_finalize(ds);
|
||||
}
|
||||
|
||||
sqlite3_stmt* is = NULL;
|
||||
if (sqlite3_prepare_v2(db,
|
||||
"INSERT INTO node_addresses(node_id,family,protocol,address,port,addr_type,config_type,nat_type,socket_id)"
|
||||
" VALUES(?,?,?,?,?,?,?,?,?)", -1, &is, NULL) != SQLITE_OK) {
|
||||
sqlite3_exec(db, "COMMIT", NULL, NULL, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int written = 0;
|
||||
for (const struct TOPO_ADDR4* a = ni->v4_addrs; a; a = a->next) {
|
||||
uint8_t cfg, nat; smeta4_lookup(ni->v4_sock_meta, a->socket_id, &cfg, &nat);
|
||||
int at = (a->type == TOPO_ADDR_INTERFACE) ? ADDR_TYPE_NETIF
|
||||
: addr_type_classify(cfg, nat, 4, a->addr);
|
||||
sqlite3_bind_int64(is, 1, (sqlite3_int64)node_id);
|
||||
sqlite3_bind_int(is, 2, 4);
|
||||
sqlite3_bind_int(is, 3, (int)a->protocol);
|
||||
sqlite3_bind_blob(is, 4, a->addr, 4, SQLITE_STATIC);
|
||||
sqlite3_bind_int(is, 5, (int)a->port);
|
||||
sqlite3_bind_int(is, 6, at);
|
||||
sqlite3_bind_int(is, 7, (int)cfg);
|
||||
sqlite3_bind_int(is, 8, (int)nat);
|
||||
sqlite3_bind_int(is, 9, (int)a->socket_id);
|
||||
sqlite3_step(is); sqlite3_reset(is);
|
||||
written++;
|
||||
}
|
||||
for (const struct TOPO_ADDR6* a = ni->v6_addrs; a; a = a->next) {
|
||||
uint8_t cfg, nat; smeta6_lookup(ni->v6_sock_meta, a->socket_id, &cfg, &nat);
|
||||
int at = (a->type == TOPO_ADDR_INTERFACE) ? ADDR_TYPE_NETIF
|
||||
: addr_type_classify(cfg, nat, 6, a->addr);
|
||||
sqlite3_bind_int64(is, 1, (sqlite3_int64)node_id);
|
||||
sqlite3_bind_int(is, 2, 6);
|
||||
sqlite3_bind_int(is, 3, (int)a->protocol);
|
||||
sqlite3_bind_blob(is, 4, a->addr, 16, SQLITE_STATIC);
|
||||
sqlite3_bind_int(is, 5, (int)a->port);
|
||||
sqlite3_bind_int(is, 6, at);
|
||||
sqlite3_bind_int(is, 7, (int)cfg);
|
||||
sqlite3_bind_int(is, 8, (int)nat);
|
||||
sqlite3_bind_int(is, 9, (int)a->socket_id);
|
||||
sqlite3_step(is); sqlite3_reset(is);
|
||||
written++;
|
||||
}
|
||||
sqlite3_finalize(is);
|
||||
sqlite3_exec(db, "COMMIT", NULL, NULL, NULL);
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "addrs_put: node=%016llx v4=%d v6=%d total=%d",
|
||||
(unsigned long long)node_id,
|
||||
topo_list_count((struct _topo_head*)ni->v4_addrs),
|
||||
topo_list_count((struct _topo_head*)ni->v6_addrs), written);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int topo_node_sqlite_member_exists(sqlite3* db, uint64_t node_id) {
|
||||
if (!db) return 0;
|
||||
sqlite3_stmt* s = NULL;
|
||||
if (sqlite3_prepare_v2(db,
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'peers\\_%' ESCAPE '\\'",
|
||||
-1, &s, NULL) != SQLITE_OK) return 0;
|
||||
char sql[256]; int found = 0;
|
||||
while (!found && sqlite3_step(s) == SQLITE_ROW) {
|
||||
const char* tbl = (const char*)sqlite3_column_text(s, 0);
|
||||
if (!tbl) continue;
|
||||
snprintf(sql, sizeof(sql), "SELECT 1 FROM \"%s\" WHERE node_id=?", tbl);
|
||||
sqlite3_stmt* m = NULL;
|
||||
if (sqlite3_prepare_v2(db, sql, -1, &m, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(m, 1, (sqlite3_int64)node_id);
|
||||
if (sqlite3_step(m) == SQLITE_ROW) found = 1;
|
||||
sqlite3_finalize(m);
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(s);
|
||||
return found;
|
||||
}
|
||||
|
||||
int topo_node_sqlite_init(sqlite3* db) {
|
||||
if (!db) return -1;
|
||||
|
||||
@@ -55,6 +187,8 @@ int topo_node_sqlite_init(sqlite3* db) {
|
||||
" port INTEGER NOT NULL CHECK(port > 0 AND port <= 65535),"
|
||||
" rtt INTEGER,"
|
||||
" addr_type INTEGER DEFAULT 0,"
|
||||
" config_type INTEGER DEFAULT 0,"
|
||||
" nat_type INTEGER DEFAULT 0,"
|
||||
" socket_id INTEGER NOT NULL DEFAULT 0,"
|
||||
" created_at INTEGER DEFAULT (unixepoch())"
|
||||
");"
|
||||
@@ -105,44 +239,14 @@ int topo_node_sqlite_init(sqlite3* db) {
|
||||
}
|
||||
|
||||
sqlite3_exec(db, "ALTER TABLE nodes ADD COLUMN client_type INTEGER NOT NULL DEFAULT 0", NULL, NULL, NULL);
|
||||
sqlite3_exec(db, "ALTER TABLE node_addresses ADD COLUMN config_type INTEGER DEFAULT 0", NULL, NULL, NULL);
|
||||
sqlite3_exec(db, "ALTER TABLE node_addresses ADD COLUMN nat_type INTEGER DEFAULT 0", NULL, NULL, NULL);
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "topo_node_sqlite tables initialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int topo_node_sqlite_node_put(sqlite3* db, struct TOPO_GROUPS* groups, struct TOPO_GROUP_NODE* nq, time_t now_sec) {
|
||||
if (!db || !nq) return -1;
|
||||
struct TOPO_NODE* ni = topo_node_registry_find(groups, nq->node_id);
|
||||
if (!ni) return -1;
|
||||
|
||||
sqlite3_exec(db, "BEGIN", NULL, NULL, NULL);
|
||||
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
if (sqlite3_prepare_v2(db,
|
||||
"INSERT INTO nodes(node_id, name, x25519_pubkey, ed25519_pubkey, client_type, last_seen_at, online)"
|
||||
" VALUES(?,?,?,?,?,?,1)"
|
||||
" ON CONFLICT(node_id) DO UPDATE SET"
|
||||
" name=CASE WHEN excluded.name != '' THEN excluded.name ELSE nodes.name END, x25519_pubkey=excluded.x25519_pubkey,"
|
||||
" ed25519_pubkey=excluded.ed25519_pubkey, client_type=CASE WHEN excluded.client_type!=0 THEN excluded.client_type ELSE nodes.client_type END,"
|
||||
" last_seen_at=excluded.last_seen_at,\n"
|
||||
" created_at=COALESCE(nodes.created_at, excluded.created_at)",
|
||||
-1, &stmt, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(stmt, 1, (sqlite3_int64)ni->node_id);
|
||||
sqlite3_bind_text(stmt, 2, ni->node_name ? ni->node_name : "", -1, SQLITE_STATIC);
|
||||
sqlite3_bind_blob(stmt, 3, ni->public_key, 32, SQLITE_STATIC);
|
||||
sqlite3_bind_blob(stmt, 4, ni->ed25519_public_key, 32, SQLITE_STATIC);
|
||||
sqlite3_bind_int(stmt, 5, (int)ni->client_type);
|
||||
sqlite3_bind_int64(stmt, 6, (sqlite3_int64)now_sec);
|
||||
sqlite3_step(stmt); sqlite3_finalize(stmt);
|
||||
}
|
||||
|
||||
sqlite3_exec(db, "COMMIT", NULL, NULL, NULL);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "node_put: nid=%016llx COMMITTED (nodes only, addrs via member_sync)",
|
||||
(unsigned long long)ni->node_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int topo_node_sqlite_channel_put(sqlite3* db, const char* channel_id,
|
||||
const char* name, uint64_t owner_node_id,
|
||||
const uint8_t* x25519_pub, const uint8_t* x25519_priv,
|
||||
@@ -463,45 +567,9 @@ int topo_node_sqlite_channel_peers_all(sqlite3* db, const char* channel_id,
|
||||
uint8_t nl = puserinfo ? (uint8_t)strnlen(puserinfo, 255) : 0;
|
||||
uint8_t atl = adm_tags_s ? (uint8_t)strnlen(adm_tags_s, 255) : 0;
|
||||
|
||||
sqlite3_stmt* ast = NULL;
|
||||
snprintf(sql, sizeof(sql),
|
||||
"SELECT family, socket_id, protocol, address, port FROM node_addresses"
|
||||
" WHERE node_id=? LIMIT 16");
|
||||
if (sqlite3_prepare_v2(db, sql, -1, &ast, NULL) != SQLITE_OK) continue;
|
||||
sqlite3_bind_int64(ast, 1, (sqlite3_int64)node_id);
|
||||
|
||||
uint8_t addr_cnt = 0; size_t addr_start = 0;
|
||||
while (sqlite3_step(ast) == SQLITE_ROW && addr_cnt < 255) {
|
||||
int family = sqlite3_column_int(ast, 0);
|
||||
int sock_id = sqlite3_column_int(ast, 1);
|
||||
int proto = sqlite3_column_int(ast, 2);
|
||||
int ip_len = (family == 4) ? 4 : 16;
|
||||
const uint8_t* ip = (const uint8_t*)sqlite3_column_blob(ast, 3);
|
||||
uint16_t port = (uint16_t)sqlite3_column_int(ast, 4);
|
||||
if (!ip) continue;
|
||||
if (off + 1 + 1 + 1 + ip_len + 2 > buf_sz) { sqlite3_finalize(ast); sqlite3_finalize(stmt); return -2; }
|
||||
if (addr_cnt == 0) addr_start = off;
|
||||
buf[off++] = (uint8_t)family;
|
||||
buf[off++] = (uint8_t)sock_id;
|
||||
buf[off++] = (uint8_t)proto;
|
||||
memcpy(buf + off, ip, (size_t)ip_len); off += (size_t)ip_len;
|
||||
buf[off++] = (uint8_t)((port >> 8) & 0xFF);
|
||||
buf[off++] = (uint8_t)(port & 0xFF);
|
||||
addr_cnt++;
|
||||
}
|
||||
sqlite3_finalize(ast);
|
||||
|
||||
uint8_t flags = (join_sig && join_ts) ? PEERS_FLAG_HAS_JOIN : 0;
|
||||
size_t peer_needed = 8 + 32 + 32 + 1 + (flags & PEERS_FLAG_HAS_JOIN ? 64+8 : 0) + 64 + 8 + 1 + (size_t)nl + 1 + 1 + (size_t)atl + 64;
|
||||
size_t addr_sz = off - addr_start;
|
||||
if (addr_cnt > 0) {
|
||||
if (off + peer_needed > buf_sz) { sqlite3_finalize(stmt); return -2; }
|
||||
memmove(buf + addr_start + peer_needed, buf + addr_start, addr_sz);
|
||||
off = addr_start;
|
||||
} else {
|
||||
if (off + peer_needed + 1 > buf_sz) { sqlite3_finalize(stmt); return -2; }
|
||||
addr_sz = 0;
|
||||
}
|
||||
size_t peer_needed = 8 + 32 + 32 + 1 + (flags & PEERS_FLAG_HAS_JOIN ? 64+8 : 0) + 64 + 8 + 1 + (size_t)nl + 1 + (size_t)atl + 64;
|
||||
if (off + peer_needed > buf_sz) { sqlite3_finalize(stmt); return -2; }
|
||||
memcpy(buf + off, &node_id, 8); off += 8;
|
||||
memcpy(buf + off, x25519, 32); off += 32;
|
||||
memcpy(buf + off, ed_pub, 32); off += 32;
|
||||
@@ -519,12 +587,10 @@ int topo_node_sqlite_channel_peers_all(sqlite3* db, const char* channel_id,
|
||||
}
|
||||
buf[off++] = nl;
|
||||
if (nl) { memcpy(buf + off, puserinfo, nl); off += nl; }
|
||||
buf[off++] = addr_cnt;
|
||||
buf[off++] = atl;
|
||||
if (atl) { memcpy(buf + off, adm_tags_s, atl); off += atl; }
|
||||
if (adm_tags_sig_b && sqlite3_column_bytes(stmt, 9) >= 64) { memcpy(buf + off, adm_tags_sig_b, 64); off += 64; }
|
||||
else { memset(buf + off, 0, 64); off += 64; }
|
||||
off += addr_sz;
|
||||
(*cnt_ptr)++;
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
@@ -705,11 +771,12 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
|
||||
if (!found) { u_free(name); return NULL; }
|
||||
|
||||
struct TOPO_ADDR4* v4_head = NULL; struct TOPO_ADDR4* v4_tail = NULL;
|
||||
struct TOPO_SOCKMETA4* m4_head = NULL; struct TOPO_SOCKMETA4* m4_tail = NULL;
|
||||
uint8_t sock_id_counter = 0;
|
||||
{
|
||||
sqlite3_stmt* s = NULL;
|
||||
if (sqlite3_prepare_v2(db,
|
||||
"SELECT address,port,addr_type,socket_id,protocol FROM node_addresses"
|
||||
"SELECT address,port,addr_type,socket_id,protocol,config_type,nat_type FROM node_addresses"
|
||||
" WHERE node_id=? AND family=4 ORDER BY addr_type",
|
||||
-1, &s, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id);
|
||||
@@ -729,16 +796,31 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
|
||||
a4->type = type; a4->socket_id = sock_id; a4->protocol = (uint8_t)proto;
|
||||
if (!v4_head) v4_head = v4_tail = a4;
|
||||
else { v4_tail->next = a4; v4_tail = a4; }
|
||||
|
||||
struct TOPO_SOCKMETA4* ex = m4_head;
|
||||
while (ex && ex->id != sock_id) ex = ex->next;
|
||||
if (!ex) {
|
||||
struct TOPO_SOCKMETA4* m4 = memory_pool_alloc(groups->v4_sock_meta_pool);
|
||||
if (m4) {
|
||||
m4->id = sock_id;
|
||||
m4->config_type = (uint8_t)sqlite3_column_int(s, 5);
|
||||
m4->nat_type = (uint8_t)sqlite3_column_int(s, 6);
|
||||
m4->next = NULL;
|
||||
if (!m4_head) m4_head = m4_tail = m4;
|
||||
else { m4_tail->next = m4; m4_tail = m4; }
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(s);
|
||||
}
|
||||
}
|
||||
/* IPv6 addresses */
|
||||
struct TOPO_ADDR6* v6_head = NULL; struct TOPO_ADDR6* v6_tail = NULL;
|
||||
struct TOPO_SOCKMETA6* m6_head = NULL; struct TOPO_SOCKMETA6* m6_tail = NULL;
|
||||
{
|
||||
sqlite3_stmt* s = NULL;
|
||||
if (sqlite3_prepare_v2(db,
|
||||
"SELECT address,port,addr_type,socket_id,protocol FROM node_addresses"
|
||||
"SELECT address,port,addr_type,socket_id,protocol,config_type,nat_type FROM node_addresses"
|
||||
" WHERE node_id=? AND family=6 ORDER BY addr_type",
|
||||
-1, &s, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(s, 1, (sqlite3_int64)node_id);
|
||||
@@ -758,6 +840,20 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
|
||||
a6->type = type; a6->socket_id = sock_id; a6->protocol = (uint8_t)proto6;
|
||||
if (!v6_head) v6_head = v6_tail = a6;
|
||||
else { v6_tail->next = a6; v6_tail = a6; }
|
||||
|
||||
struct TOPO_SOCKMETA6* ex = m6_head;
|
||||
while (ex && ex->id != sock_id) ex = ex->next;
|
||||
if (!ex) {
|
||||
struct TOPO_SOCKMETA6* m6 = memory_pool_alloc(groups->v6_sock_meta_pool);
|
||||
if (m6) {
|
||||
m6->id = sock_id;
|
||||
m6->config_type = (uint8_t)sqlite3_column_int(s, 5);
|
||||
m6->nat_type = (uint8_t)sqlite3_column_int(s, 6);
|
||||
m6->next = NULL;
|
||||
if (!m6_head) m6_head = m6_tail = m6;
|
||||
else { m6_tail->next = m6; m6_tail = m6; }
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(s);
|
||||
}
|
||||
@@ -772,6 +868,8 @@ struct TOPO_NODE* topo_node_sqlite_node_load(sqlite3* db, struct TOPO_GROUPS* gr
|
||||
ni->node_name = name;
|
||||
ni->v4_addrs = v4_head;
|
||||
ni->v6_addrs = v6_head;
|
||||
ni->v4_sock_meta = m4_head;
|
||||
ni->v6_sock_meta = m6_head;
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "node_load: node 0x%016llx loaded from DB name=%s v4=%d v6=%d",
|
||||
(unsigned long long)node_id, name ? name : "",
|
||||
|
||||
Reference in new issue
Block a user