Browse Source

etcp: cyclic link_id, link close on addr change, inflight nullify; test rewrite

topo_upd
evgeny 2 months ago
parent
commit
b503fa4418
  1. 3
      AGENTS.md
  2. 4
      src/transport_layer/auto_socket.c
  3. 6
      src/transport_layer/etcp.c
  4. 1
      src/transport_layer/etcp.h
  5. 59
      src/transport_layer/etcp_connections.c
  6. 148
      tests/test_auto_socket_dynamic.c

3
AGENTS.md

@ -22,6 +22,9 @@ This file contains essential information for AI coding agents working in the uTu
Ты постоянно тупишь на отладке и раздалбываешь код. Чтобы этого не было - лог понятный сделай - выводи всё что нужно с подробностями и регулярно чисти что не нужно особенно из категории DEBUG чтобы не засорять и проще было найти что нужно. И всё бустро найдешь. И нечего гадать когда можно просто посмотреть нормальный, правильно сделанный лог и сразу УВИДЕТЬ проблему не гадать, ошибаться, запарывать код еще сильнее и застревать в куче говна
При поиске багов всегда проверяй достаточно ли отладочной информации. Если не достаточно - фокусируйся на том чтобы добавить нужную информацию в вывод.
Помни что отладка управляется фильтрами по категормяи, которые нужно проверить и при необходимости правильно настроить (в конфиге или в коде).
## Quick Reference
**Repository:** uTun - Secure VPN tunnel with ETCP protocol

4
src/transport_layer/auto_socket.c

@ -807,9 +807,9 @@ static void reconcile_iface(struct AUTO_SOCKET* as, uint32_t ifindex, const char
else
DEBUG_INFO(DEBUG_CATEGORY_AS, "[as] v4 UDP (%s) addr changed: %s→%s", ifname,
sockaddr_storage_to_str(&old4).str, sockaddr_storage_to_str(&sock->interface_addr).str);
create_iface_udp_socket(as, ifindex, ifname, AF_INET, new_type);
ncd_remove_socket_links(as->instance, sock);
etcp_socket_remove(sock);
create_iface_udp_socket(as, ifindex, ifname, AF_INET, new_type);
ifa->v4_type = new_type;
{ struct ETCP_SOCKET* s = as->instance->etcp_sockets;
while (s) { if (s->netif_index == ifindex && s->local_addr.ss_family == AF_INET) { ifa->v4_udp = s; break; } s = s->next; } }
@ -852,9 +852,9 @@ static void reconcile_iface(struct AUTO_SOCKET* as, uint32_t ifindex, const char
else
DEBUG_INFO(DEBUG_CATEGORY_AS, "[as] v6 UDP (%s) addr changed: %s→%s", ifname,
sockaddr_storage_to_str(&old6).str, sockaddr_storage_to_str(&sock->interface_addr).str);
create_iface_udp_socket(as, ifindex, ifname, AF_INET6, new_type);
ncd_remove_socket_links(as->instance, sock);
etcp_socket_remove(sock);
create_iface_udp_socket(as, ifindex, ifname, AF_INET6, new_type);
ifa->v6_type = new_type;
{ struct ETCP_SOCKET* s = as->instance->etcp_sockets;
while (s) { if (s->netif_index == ifindex && s->local_addr.ss_family == AF_INET6) { ifa->v6_udp = s; break; } s = s->next; } }

6
src/transport_layer/etcp.c

@ -1112,8 +1112,10 @@ struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* etcp) {
// Always subtract from previous last_link (if any) – this handles retransmission
if (inf_pkt->last_link) {
inf_pkt->last_link->total_retransmissions++;
inf_pkt->last_link->bbr_loss_since_ack += inf_pkt->ll.len;
bbr_note_loss(inf_pkt->last_link->bbr);
if (inf_pkt->last_link->bbr) {
inf_pkt->last_link->bbr_loss_since_ack += inf_pkt->ll.len;
bbr_note_loss(inf_pkt->last_link->bbr);
}
inf_pkt->last_link->inflight_bytes -= inf_pkt->ll.len;
inf_pkt->last_link->inflight_packets--;
}

1
src/transport_layer/etcp.h

@ -150,6 +150,7 @@ struct ETCP_CONN {
struct ETCP_LINK* links;
struct ETCP_LINK* last_rr_link; // последний линк, выбранный round-robin
uint8_t tcp_link_count; // количество UP TCP линков
uint8_t last_assigned_link_id; // последний выданный link_id (для циклического перебора)
// Crypto and state
struct secure_channel crypto_ctx;

59
src/transport_layer/etcp_connections.c

@ -565,15 +565,13 @@ int etcp_find_free_local_link_id(struct ETCP_CONN* etcp) {
link = link->next;
}
// Ищем первый свободный id
for (int i = 0; i < 32; i++) {
if (used_ids[i] != 0xFF) {
// Есть свободные биты в этом байте
for (int bit = 0; bit < 8; bit++) {
if (!(used_ids[i] & (1 << bit))) {
return (i << 3) + bit;
}
}
// Ищем первый свободный id, начиная с last_assigned_link_id + 1 (циклический перебор)
for (int i = 0; i < 256; i++) {
int id = ((etcp->last_assigned_link_id + 1 + i) & 0xFF);
if (id == 0) continue;
if (!(used_ids[id >> 3] & (1 << (id & 7)))) {
etcp->last_assigned_link_id = (uint8_t)id;
return id;
}
}
@ -861,7 +859,13 @@ void etcp_socket_remove(struct ETCP_SOCKET* conn) {
queue_free(conn->links_queue);
conn->links_queue = NULL;
}
if (conn->instance) {
struct ETCP_SOCKET** pp = &conn->instance->etcp_sockets;
while (*pp && *pp != conn) pp = &(*pp)->next;
if (*pp) *pp = conn->next;
}
u_free(conn);
}
@ -1111,6 +1115,8 @@ void etcp_link_close(struct ETCP_LINK* link) {
if (link->shaper_timer) uasync_cancel_timeout(link->etcp->instance->ua, link->shaper_timer);
if (link->keepalive_timer) uasync_cancel_timeout(link->etcp->instance->ua, link->keepalive_timer);
etcp_conn_on_inflight_lim_changed(link->etcp);
etcp_inflight_nullify_link(link->etcp->input_wait_ack, link);
etcp_inflight_nullify_link(link->etcp->input_send_q, link);
u_free(link->bbr);
u_free(link);
return;
@ -2238,20 +2244,11 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] found existing link for id=%d, socket=[%s]", conn->log_name, req->link_id, e_sock->name);
link = existing_link;
if (!sockaddr_equal(&link->remote_addr, &addr)) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] IP:port changed for remote_link_id=%d socket:[%s]", conn->log_name, req->link_id, e_sock->name);
remove_link_from_queue(link); // remove from old socket queue
link->conn = e_sock;
memcpy(&link->remote_addr, &addr, sizeof(addr));
if (insert_link_queue(link->conn, link) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Failed to reinsert link after addr change");
goto ec_fr;
}
// Cancel pending NAT check and reset status
nat_detection_cancel_for_conn(link->etcp->instance->nat_det, link->etcp);
link->nat_check_status = NAT_CHECK_NONE;
link->nat_type = NAT_TYPE_UNKNOWN;
}
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] IP:port changed for remote_link_id=%d socket:[%s] — closing old link, creating new",
conn->log_name, req->link_id, e_sock->name);
etcp_link_close(link);
goto create_new_link;
}
// Link exists - reuse it for recovery
link->remote_link_id = req->link_id;
link->remote_socket_id = req->socket_id;
@ -2284,14 +2281,15 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
if (ml->init_timer) { uasync_cancel_timeout(conn->instance->ua, ml->init_timer); ml->init_timer = NULL; }
}
/* Sync session_id; reset if remote is clean and we're dirty, or request reset if we're clean and remote is dirty */
/* Sync session_id; reset only if remote session changed */
{ int sess_changed = (conn->session_id != session_id);
conn->session_id = session_id;
if (req->code == ETCP_INIT_REQUEST) {
if (conn->got_initial_pkt) etcp_conn_reinit(conn, "duplicate INIT");
if (sess_changed || conn->got_initial_pkt) etcp_conn_reinit(conn, "duplicate INIT");
send_reset = 0;
} else {
if (conn->got_initial_pkt == 0) send_reset = 1;
}
} }
}
// Cancel existing timers
@ -2300,6 +2298,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
link->init_timer = NULL;
}
} else {
create_new_link:
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] NO existing link for id=%d, socket=[%s]", conn->log_name, req->link_id, e_sock->name);
// Create new link
link = etcp_link_new(conn, e_sock, &addr, 1);
@ -2328,14 +2327,16 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
return;
}
// Always sync session_id; reset if new session or data was flowing
// Always sync session_id; reset only if remote session changed
{ int sess_changed = (conn->session_id != session_id);
conn->session_id = session_id;
if (sess_changed || conn->got_initial_pkt) {
if (sess_changed) {
send_reset = 1;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[%s] REINIT new link: code=0x%02x sess=%08x→%08x got_init=%d initialized=%d links_up=%d",
conn->log_name, code, conn->session_id, session_id, conn->got_initial_pkt, conn->initialized, conn->links_up);
etcp_conn_reinit(conn, "session changed");
} else if (conn->got_initial_pkt == 0) {
send_reset = 1;
} }
}
uint16_t client_ka = (req->keepalive[0]<<8) | req->keepalive[1];

148
tests/test_auto_socket_dynamic.c

@ -38,14 +38,14 @@ static struct test_ctx {
struct UASYNC* ua;
int round; /* 0..7 */
int step;
int keep_tcp;
int ip_changes_on_last;
char cur_iface[IFNAMSIZ];
char prev_iface[IFNAMSIZ];
struct ETCP_CONN* srv_conn;
int connected; /* etcp_connect callback fired */
uint64_t srv_node_id;
uint8_t srv_pubkey[SC_PUBKEY_SIZE];
int result; /* 0=running, 1=fail, 2=pass */
uint32_t recv_at_ip_change; /* total_recv на момент смены IP */
/* traffic */
uint32_t send_seq, send_count, pong_count, total_recv;
@ -58,16 +58,15 @@ static char scf[256], ccf[256];
/* ── rounds ── */
static const struct {
const char* ifname, *ip1, *ip2;
int keep_tcp;
} rounds[] = {
{"dummy_cli1", "10.90.0.2/24", "10.90.1.2/24", 1},
{"dummy_cli2", "10.90.0.3/24", "10.90.1.3/24", 1},
{"dummy_cli3", "10.90.0.4/24", "10.90.1.4/24", 0},
{"dummy_cli4", "10.90.0.5/24", "10.90.1.5/24", 0},
{"dummy_cli5", "10.90.0.6/24", "10.90.1.6/24", 1},
{"dummy_cli6", "10.90.0.7/24", "10.90.1.7/24", 1},
{"dummy_cli7", "10.90.0.8/24", "10.90.1.8/24", 0},
{"dummy_cli8", "10.90.0.9/24", "10.90.1.9/24", 0},
{"dummy_cli1", "10.90.0.2/16", "10.90.1.2/16"},
{"dummy_cli2", "10.90.0.3/16", "10.90.1.3/16"},
{"dummy_cli3", "10.90.0.4/16", "10.90.1.4/16"},
{"dummy_cli4", "10.90.0.5/16", "10.90.1.5/16"},
{"dummy_cli5", "10.90.0.6/16", "10.90.1.6/16"},
{"dummy_cli6", "10.90.0.7/16", "10.90.1.7/16"},
{"dummy_cli7", "10.90.0.8/16", "10.90.1.8/16"},
{"dummy_cli8", "10.90.0.9/16", "10.90.1.9/16"},
};
#define N_ROUNDS (int)(sizeof(rounds)/sizeof(rounds[0]))
@ -88,35 +87,21 @@ static void fail(const char* msg) {
}
static void to_cb(void* arg) { (void)arg; fprintf(stderr, "TIMEOUT\n"); ctx.result = 1; }
static int count_links_to_srv(void) {
static int link_on_iface(const struct ETCP_LINK* l, const char* ifname) {
if (!l->conn || !l->conn->name || !ifname || !ifname[0]) return 1;
/* socket name: as_<ifname>_<v4/v6>_<udp/tcp> */
size_t ifl = strlen(ifname);
return strncmp(l->conn->name + 3, ifname, ifl) == 0 && l->conn->name[3 + ifl] == '_';
}
static int count_links_to_srv(const char* ifname) {
int n = 0; struct ll_entry* e = ctx.client->connections->head;
while (e) { struct conn_queue_entry* ce = (struct conn_queue_entry*)e->data;
if (ce->conn->peer_node_id == ctx.srv_node_id) {
struct ETCP_LINK* l = ce->conn->links;
while (l) { if (l->initialized && l->link_status) n++; l = l->next; }
while (l) { if (l->initialized && l->link_status && link_on_iface(l, ifname)) n++; l = l->next; }
} e = e->next; }
return n;
}
static int all_links_are_type(void) {
struct ll_entry* e = ctx.client->connections->head;
while (e) { struct conn_queue_entry* ce = (struct conn_queue_entry*)e->data;
if (ce->conn->peer_node_id == ctx.srv_node_id) {
struct ETCP_LINK* l = ce->conn->links;
while (l) { if (l->initialized && l->link_status && l->is_tcp != ctx.keep_tcp) return 0; l = l->next; }
} e = e->next; }
return 1;
}
/* ── filter sockets ── */
static void keep_only_socket_type(int keep_tcp) {
struct ETCP_SOCKET *s = ctx.client->etcp_sockets, *rm[16];
int n = 0;
while (s) { if (s->local_addr.ss_family == AF_INET && s->is_tcp != keep_tcp && n < 16) rm[n++] = s; s = s->next; }
for (int i = 0; i < n; i++) {
ncd_remove_socket_links(ctx.client, rm[i]);
etcp_socket_remove(rm[i]);
}
}
/* ── server node (2 addrs: UDP + TCP) ── */
static struct TOPO_GROUP_NODE* mk_srv_node(void) {
@ -148,7 +133,7 @@ static struct TOPO_GROUP_NODE* mk_srv_node(void) {
return nq;
}
/* ── traffic ── */
#define TD(fmt, ...) (void)0
static void srv_traffic_handler(struct ETCP_CONN* conn, struct ll_entry* entry) {
if (!entry || entry->len < 5) { if (entry) queue_entry_free(entry); return; }
struct ll_entry* reply = queue_entry_new(0);
@ -168,12 +153,13 @@ static void cli_traffic_handler(struct ETCP_CONN* conn, struct ll_entry* entry)
static void traffic_send_timer(void* arg) {
(void)arg;
if (ctx.result) return;
if (ctx.srv_conn && ctx.srv_conn->state != 2) {
struct ETCP_CONN* conn = instance_find_conn(ctx.client, ctx.srv_node_id);
if (conn && conn->state != 2) {
uint8_t buf[5]; buf[0] = ETCP_RT_ID_TEST;
ctx.send_seq++; memcpy(buf + 1, &ctx.send_seq, 4);
struct ll_entry* e = queue_entry_new(0);
if (e) { e->dgram = u_malloc(5); if (e->dgram) { memcpy(e->dgram, buf, 5); e->len = 5;
etcp_send(ctx.srv_conn, e); ctx.send_count++; } else queue_entry_free(e); }
etcp_send(conn, e); ctx.send_count++; } else queue_entry_free(e); }
}
if (!ctx.result) timeout_handle = uasync_set_timeout(ctx.ua, TRAF_SEND_TB, NULL, traffic_send_timer, "traf_snd");
}
@ -188,9 +174,8 @@ static void traffic_monitor_timer(void* arg) {
/* ── etcp_connect callback ── */
static void connect_cb(void* arg, struct ETCP_CONN* conn, int type) {
(void)arg;
if (type == ETCP_CONNECT_EARLY || type == ETCP_CONNECT_LATE)
{ if (conn) { ctx.srv_conn = conn; ctx.step = 9; } }
(void)arg; (void)conn;
if (type == ETCP_CONNECT_EARLY || type == ETCP_CONNECT_LATE) ctx.connected = 1;
}
static void start_traffic(void) {
@ -230,6 +215,7 @@ static void phase_del_prev(void* arg);
static void phase_check_add(void* arg);
static void phase_add(void* arg);
static void phase_del_last(void* arg);
static void phase_check_del_last(void* arg);
static void phase_done(void* arg);
static void phase_done(void* arg) {
@ -244,32 +230,42 @@ static void phase_del_last(void* arg) {
if (ctx.result) return;
ctx.step = 11;
ip_link_del(rounds[N_ROUNDS-1].ifname);
uasync_set_timeout(ctx.ua, STEP_TB, NULL, (timeout_cb)phase_del_last, "chk_del_last");
return; /* перепланируем один раз для проверки */
uasync_set_timeout(ctx.ua, STEP_TB, NULL, phase_check_del_last, "chk_del_last");
}
/* ══ check wrappers ══ */
static void do_check(void) {
int l = count_links_to_srv();
int l = count_links_to_srv(ctx.cur_iface);
if (l < 1) { fail("no links"); return; }
if (!all_links_are_type()) { fail("wrong link type"); return; }
}
static void phase_check_del_last(void* arg) {
(void)arg;
ctx.step = 12;
int l = count_links_to_srv();
if (l > 0) { fail("links survived last del"); return; }
/* повторная проверка через 300ms — после второго захода считаем ОК */
static int cnt = 0;
if (++cnt < 2) { uasync_set_timeout(ctx.ua, STEP_TB, NULL, (timeout_cb)phase_check_del_last, "chk_del_last"); return; }
int l = count_links_to_srv(rounds[N_ROUNDS-1].ifname);
if (l > 0) {
/* повторная проверка через 300ms — после второго захода считаем ОК */
static int cnt = 0;
if (++cnt < 2) { uasync_set_timeout(ctx.ua, STEP_TB, NULL, (timeout_cb)phase_check_del_last, "chk_del_last"); return; }
fail("links survived last del"); return;
}
fprintf(stderr, " r=%d s=%d: no links after del_last (OK)\n", ctx.round, ctx.step); fflush(stderr);
uasync_set_timeout(ctx.ua, STEP_TB, NULL, phase_done, "done");
}
static void phase_check_ip(void* arg) {
(void)arg; if (ctx.result) return;
static uint64_t wait_start = 0;
ctx.step = 6;
if (count_links_to_srv(ctx.cur_iface) == 0 || ctx.total_recv <= ctx.recv_at_ip_change) {
if (!wait_start) wait_start = get_time_tb();
if (get_time_tb() - wait_start < (uint64_t)STEP_TB * 10) {
uasync_set_timeout(ctx.ua, STEP_TB/3, NULL, phase_check_ip, "chk_ip"); return;
}
fail("traffic not recovered after IP change");
return;
}
wait_start = 0;
do_check(); if (ctx.result) return;
if (ctx.round == N_ROUNDS - 1 && ctx.ip_changes_on_last < 2) {
@ -282,6 +278,7 @@ static void phase_check_ip(void* arg) {
fflush(stderr);
uasync_set_timeout(ctx.ua, STEP_TB, NULL, phase_del_last, "del_last");
} else {
strncpy(ctx.prev_iface, ctx.cur_iface, IFNAMSIZ - 1);
ctx.round++;
uasync_set_timeout(ctx.ua, STEP_TB, NULL, phase_add, "next_add");
}
@ -289,12 +286,14 @@ static void phase_check_ip(void* arg) {
static void phase_change_ip(void* arg) {
(void)arg; if (ctx.result) return;
TD("CHG r=%d start", ctx.round);
ctx.step = 5;
const char* old_ip = (ctx.ip_changes_on_last >= 2) ? rounds[ctx.round].ip2 : rounds[ctx.round].ip1;
const char* new_ip = (ctx.ip_changes_on_last >= 2) ? rounds[ctx.round].ip1 : rounds[ctx.round].ip2;
ip_addr_del(rounds[ctx.round].ifname, old_ip);
ip_addr_add(rounds[ctx.round].ifname, new_ip);
keep_only_socket_type(ctx.keep_tcp);
ctx.recv_at_ip_change = ctx.total_recv;
TD("CHG r=%d sys done", ctx.round);
uasync_set_timeout(ctx.ua, STEP_TB, NULL, phase_check_ip, "chk_ip");
}
@ -302,7 +301,7 @@ static void phase_check_del(void* arg) {
(void)arg; if (ctx.result) return;
ctx.step = 4;
do_check(); if (ctx.result) return;
fprintf(stderr, " r=%d s=%d: del_prev OK links=%d\n", ctx.round, ctx.step, count_links_to_srv());
fprintf(stderr, " r=%d s=%d: del_prev OK links=%d\n", ctx.round, ctx.step, count_links_to_srv(ctx.cur_iface));
fflush(stderr);
uasync_set_timeout(ctx.ua, STEP_TB, NULL, phase_change_ip, "chg_ip");
}
@ -316,16 +315,16 @@ static void phase_del_prev(void* arg) {
static void phase_check_add(void* arg) {
(void)arg; if (ctx.result) return;
TD("CHKADD r=%d start", ctx.round);
ctx.step = 2;
/* wait for etcp_connect on round 0 */
if (ctx.round == 0 && ctx.step == 2 && !ctx.srv_conn) {
if (ctx.round == 0 && !ctx.connected) {
uasync_set_timeout(ctx.ua, STEP_TB / 3, NULL, phase_check_add, "chk_add");
return;
}
if (ctx.round == 0 && !ctx.srv_conn) { fail("etcp_connect didn't fire"); return; }
do_check(); if (ctx.result) return;
fprintf(stderr, " r=%d s=%d: add OK links=%d type=%s\n",
ctx.round, ctx.step, count_links_to_srv(), ctx.keep_tcp ? "TCP" : "UDP");
fprintf(stderr, " r=%d s=%d: add OK links=%d\n",
ctx.round, ctx.step, count_links_to_srv(ctx.cur_iface));
fflush(stderr);
if (ctx.round == 0) start_traffic();
@ -339,14 +338,14 @@ static void phase_check_add(void* arg) {
static void phase_add(void* arg) {
(void)arg; if (ctx.result) return;
TD("ADD r=%d start", ctx.round);
ctx.step = 1;
ctx.keep_tcp = rounds[ctx.round].keep_tcp;
strncpy(ctx.cur_iface, rounds[ctx.round].ifname, IFNAMSIZ - 1);
ip_link_add(ctx.cur_iface);
ip_addr_add(ctx.cur_iface, rounds[ctx.round].ip1);
ip_link_up(ctx.cur_iface);
keep_only_socket_type(ctx.keep_tcp);
TD("ADD r=%d sys done", ctx.round);
if (ctx.round == 0) {
struct TOPO_GROUP_NODE* sn = mk_srv_node();
@ -367,7 +366,6 @@ static void cleanup_ifaces(void) {
static void setup(void) {
if (geteuid() != 0) { fprintf(stderr, "SKIP: test requires root\n"); exit(77); }
atexit(cleanup_ifaces);
cleanup_ifaces();
test_mkdtemp(tdir);
snprintf(scf, sizeof(scf), "%s/s.conf", tdir);
@ -379,7 +377,7 @@ static void setup(void) {
/* server: fixed [server] on dummy_srv */
ip_link_add("dummy_srv");
ip_addr_add("dummy_srv", "10.90.0.1/24");
ip_addr_add("dummy_srv", "10.90.0.1/16");
ip_link_up("dummy_srv");
/* client: first interface */
@ -387,7 +385,7 @@ static void setup(void) {
ip_addr_add(rounds[0].ifname, rounds[0].ip1);
ip_link_up(rounds[0].ifname);
/* write initial configs */
/* Step 1: write minimal configs → generate keys + node_id via config_ensure */
wf(scf, "[global]\ntun_ip=10.99.0.1/24\ntun_ifname=tun_srv\ntun_test_mode=1\n"
"auto_sockets=no\ndb_path=%s/db_srv\n"
"[server: fixed]\naddr=10.90.0.1:9001\ntype=public\n[allowed_keys]\nallow_all=1\n", tdir);
@ -396,33 +394,23 @@ static void setup(void) {
config_ensure_keys_and_node_id(scf);
config_ensure_keys_and_node_id(ccf);
{ struct utun_config* cs = parse_config(scf); ctx.srv_node_id = cs->global.my_node_id; free_config(cs); }
{ struct utun_config* cc = parse_config(ccf); (void)cc->global.my_node_id; free_config(cc); }
/* Step 2: read generated keys and node_id */
char *spub = gv(scf, "pub"), *spriv = gv(scf, "priv");
char *cpub = gv(ccf, "pub"), *cpriv = gv(ccf, "priv");
{ struct utun_config* cs = parse_config(scf); ctx.srv_node_id = cs->global.my_node_id; free_config(cs); }
wf(scf, "[global]\nmy_private_key=%s\nmy_public_key=%s\ntun_ip=10.99.0.1/24\ntun_ifname=tun_srv\n"
"tun_test_mode=1\nauto_sockets=no\ndb_path=%s/db_srv\n"
/* Step 3: write final configs with all values embedded */
wf(scf, "[global]\nmy_private_key=%s\nmy_public_key=%s\nmy_node_id=0x%016llx\n"
"tun_ip=10.99.0.1/24\ntun_ifname=tun_srv\ntun_test_mode=1\n"
"auto_sockets=no\ndb_path=%s/db_srv\n"
"[server: fixed]\naddr=10.90.0.1:9001\ntype=public\n[allowed_keys]\nallow_all=1\n",
spriv, spub, tdir);
wf(ccf, "[global]\nmy_private_key=%s\nmy_public_key=%s\ntun_ip=10.99.0.2/24\ntun_ifname=tun_cli\n"
"tun_test_mode=1\nauto_sockets=yes\ndb_path=%s/db_cli\n[allowed_keys]\nallow_all=1\n",
spriv, spub, (unsigned long long)ctx.srv_node_id, tdir);
wf(ccf, "[global]\nmy_private_key=%s\nmy_public_key=%s\n"
"tun_ip=10.99.0.2/24\ntun_ifname=tun_cli\ntun_test_mode=1\n"
"auto_sockets=yes\ndb_path=%s/db_cli\n[allowed_keys]\nallow_all=1\n",
cpriv, cpub, tdir);
/* verify config */
{ struct utun_config* ck = parse_config(ccf);
fprintf(stderr, " [setup] client: auto_sockets=%d node_id=0x%016llx\n",
ck ? ck->global.auto_sockets : -1,
(unsigned long long)(ck ? ck->global.my_node_id : 0));
free_config(ck);
ck = parse_config(scf);
fprintf(stderr, " [setup] server: auto_sockets=%d node_id=0x%016llx\n",
ck ? ck->global.auto_sockets : -1,
(unsigned long long)(ck ? ck->global.my_node_id : 0));
fflush(stderr);
free_config(ck); }
/* extract server pubkey binary */
struct utun_config* cs2 = parse_config(scf);
if (cs2 && cs2->global.my_public_key_hex)
sc_hex_to_binary(cs2->global.my_public_key_hex, ctx.srv_pubkey, SC_PUBKEY_SIZE);

Loading…
Cancel
Save