diff --git a/AGENTS.md b/AGENTS.md index 088d4731..24676a91 100644 --- a/AGENTS.md +++ b/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 diff --git a/src/transport_layer/auto_socket.c b/src/transport_layer/auto_socket.c index 6d9dd498..e233fc17 100644 --- a/src/transport_layer/auto_socket.c +++ b/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; } } diff --git a/src/transport_layer/etcp.c b/src/transport_layer/etcp.c index 87b22ecd..4af19ca5 100644 --- a/src/transport_layer/etcp.c +++ b/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--; } diff --git a/src/transport_layer/etcp.h b/src/transport_layer/etcp.h index 3b5d074e..35ab45ee 100644 --- a/src/transport_layer/etcp.h +++ b/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; diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index eb966287..8879795b 100644 --- a/src/transport_layer/etcp_connections.c +++ b/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]; diff --git a/tests/test_auto_socket_dynamic.c b/tests/test_auto_socket_dynamic.c index a6354268..f5e7f3c5 100644 --- a/tests/test_auto_socket_dynamic.c +++ b/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___ */ + 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);