Roll back required TUN mappings and verify instance startup failures

This commit is contained in:
evgeny committed 2026-10-24 13:36:22 +02:00
1 parent c4eddfe50e
commit bb2ef05157
2 files changed
+39 -4

No files matched your search

+16 -3
View File
@@ -752,6 +752,9 @@ struct tcp_proxy_client* tcp_proxy_client_create(struct UTUN_INSTANCE* inst, str
}
int need_tun = tun_name && tun_name[0] && tun_ip && tun_ip[0];
if ((tun_name && tun_name[0]) != (tun_ip && tun_ip[0])) {
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy client: TUN requires both name and IP"); return NULL;
}
if (!need_tun && !socks_enabled && !http_proxy_enabled) {
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "no proxy mode enabled"); return NULL;
}
@@ -784,10 +787,20 @@ struct tcp_proxy_client* tcp_proxy_client_create(struct UTUN_INSTANCE* inst, str
int j; for (j = 0; j < mapping_count; j++) {
uint16_t port_net = htons(mappings[j].local_port);
struct tcp_pcb *lpcb = tcp_new(p->lwip);
if (!lpcb) continue;
tcp_bind(lpcb, INADDR_ANY, port_net);
if (!lpcb) {
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy client: mapping PCB allocation failed port=%u", mappings[j].local_port);
tcp_proxy_client_destroy(p); return NULL;
}
if (tcp_bind(lpcb, INADDR_ANY, port_net) != LERR_OK) {
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy client: mapping bind failed port=%u", mappings[j].local_port);
tcp_abort(lpcb); tcp_proxy_client_destroy(p); return NULL;
}
struct tcp_pcb *listen_pcb = tcp_listen(lpcb);
if (listen_pcb) { tcp_arg(listen_pcb, p); tcp_accept(listen_pcb, tcp_proxy_client_accept_cb); }
if (!listen_pcb) {
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy client: mapping listen failed port=%u", mappings[j].local_port);
tcp_abort(lpcb); tcp_proxy_client_destroy(p); return NULL;
}
tcp_arg(listen_pcb, p); tcp_accept(listen_pcb, tcp_proxy_client_accept_cb);
}
}
}
+23 -1
View File
@@ -184,6 +184,26 @@ static int ownership(int unused) {
CHECK_EQ(tcp_proxy_server_init(f.inst), 0); cleanup(&f); return 0;
}
// Конструктор instance сам откатывает proxy-ресурсы, сохраняя заимствованный config при отказе.
static int instance_rollback(int kind) {
struct UASYNC* ua = uasync_create(); CHECK(ua);
const char* text = "[global]\ntun_enabled=no\n"
"my_private_key=704f2e012c8fa8768130cb0f988a997dccb628372bc5ceccacc78dcbfec5916f\n"
"my_public_key=b3193173def895bd0fcea6f86af077c7d77216f10395275f627ac18242ec0f01\n"
"[server: s1]\naddr=127.0.0.1:0\ntype=public\n[tcp_proxy_server]\nconnect_timeout=2000\n";
struct utun_config* cfg = parse_config_from_buf(text, strlen(text), "proxy-failure"); CHECK(cfg);
if (kind == 0) regression_fault_arm(FAULT_CALLOC, "udp_proxy.c", 1);
else if (kind == 1) regression_fault_arm(FAULT_CALLOC, "icmp_proxy.c", 1);
else {
cfg->global.tcp_proxy_client_socks_enabled = 1;
strcpy(cfg->global.tcp_proxy_client_socks_addr, "invalid");
}
struct UTUN_INSTANCE* inst = utun_instance_create_from_config(ua, cfg);
if (kind < 2) CHECK(regression_fault_hit());
regression_fault_reset(); CHECK(!inst); CHECK_EQ(cfg->global.tcp_proxy_server_enabled, 1);
free_config(cfg); uasync_destroy(ua, 0); return 0;
}
int main(int argc, char** argv) {
const struct regression_case cases[] = {
{"UDP flow allocation", udp_failures, 0}, {"UDP socket", udp_failures, 1},
@@ -194,7 +214,9 @@ int main(int argc, char** argv) {
{"UDP empty datagram", udp_failures, 10}, {"UDP context OOM", context_oom, 0},
{"ICMP context OOM", context_oom, 1}, {"ICMP unavailable raw", icmp_failures, 0},
{"ICMP nonblocking", icmp_failures, 1}, {"ICMP read registration", icmp_failures, 2},
{"ICMP expiry and renewal", icmp_failures, 3}, {"Shared contexts and listener rollback", ownership, 0}
{"ICMP expiry and renewal", icmp_failures, 3}, {"Shared contexts and listener rollback", ownership, 0},
{"Instance UDP rollback", instance_rollback, 0}, {"Instance ICMP rollback", instance_rollback, 1},
{"Instance listener rollback", instance_rollback, 2}
};
return regression_run(argc, argv, cases, sizeof(cases) / sizeof(cases[0]));
}