Verify autosocket protocol modes across IPv4 and IPv6 lifecycle

This commit is contained in:
evgeny committed 2026-10-25 16:35:54 +01:00
1 parent fc8a06547d
commit 7bcdccc4d6
2 files changed
+55

No files matched your search

+3
View File
@@ -41,6 +41,9 @@ free_config(cfg);
- Обработка длинных значений зависит от поля: часть строк обрезается, `assign_string` отклоняет значение без изменения поля.
- Ключи клиента `link` требуют, чтобы сервер (`[server:имя]`) был объявлен выше по файлу. Иначе ошибка.
- `tun_enabled` по умолчанию `0`. При явном включении и отсутствии имени интерфейса используется `tun0`.
- При `auto_sockets=yes` параметр `[global] auto_socket_protocols=tcp|udp|tcp+udp` выбирает протоколы автосокетов.
По умолчанию `tcp+udp`; неизвестное или пустое значение отклоняется. Ручные `[server]` используют свой `transport`.
В Android выбранные протоколы генерирует frontend в отдельные `[server]` с портами на интерфейс/семейство/протокол.
- IPv6-адреса в `[server:...] addr` поддерживают префиксы `temporary_ipv6:` и `permanent_ipv6:`.
- HEX декодируется после проверки каждого символа. Ошибочный список REALITY `short_ids` отклоняется целиком и оставляет `short_id_count=0`; ошибочный последний REALITY-ключ сбрасывает соответствующий `has_*_key`.
+52
View File
@@ -23,6 +23,7 @@
#include "topo_node.h"
#include "secure_channel.h"
#include "../src/transport_layer/node_conn_direct.h"
#include "../src/transport_layer/auto_socket.h"
#include "../lib/u_async.h"
#include "../lib/ll_queue.h"
#include "../lib/debug_config.h"
@@ -775,6 +776,55 @@ static void cleanup(void) {
if (nftw(tdir, cleanup_path, 16, FTW_DEPTH | FTW_PHYS) != 0) fail("temporary directory cleanup failed");
}
/* Проверяет фактический набор TCP/UDP для обоих семейств на одном интерфейсе. */
static void check_protocol_sockets(struct UTUN_INSTANCE* inst, uint32_t ifindex, int protocols) {
int actual = 0, count = 0;
for (struct ETCP_SOCKET* sock = inst->etcp_sockets; sock; sock = sock->next) {
if (sock->netif_index != ifindex || sock->probe_only) continue;
int bit = sock->is_tcp ? CFG_AUTO_SOCKET_TCP : CFG_AUTO_SOCKET_UDP;
if (sock->local_addr.ss_family == AF_INET6) bit <<= 2;
actual |= bit; count++;
}
int expected = protocols | (protocols << 2);
int expected_count = protocols == CFG_AUTO_SOCKET_BOTH ? 4 : protocols ? 2 : 0;
if (actual != expected || count != expected_count) fail("selected auto socket protocols do not match actual IPv4/IPv6 sockets");
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "auto protocol check: mask=%d actual=%d sockets=%d expected=%d",
protocols, actual, count, expected_count);
}
/* Проверяет начальное сканирование, явное добавление и повторную сверку во всех трёх режимах. */
static void test_protocol_modes(void) {
if (system("ip -6 addr add fd42::2/64 nodad dev dummy_cli1")) { fail("cannot add IPv6 protocol test address"); return; }
uint32_t ifindex = if_nametoindex(rounds[0].ifname);
const int modes[] = {CFG_AUTO_SOCKET_TCP, CFG_AUTO_SOCKET_UDP, CFG_AUTO_SOCKET_BOTH};
for (size_t i = 0; i < sizeof(modes) / sizeof(modes[0]) && !ctx.result; i++) {
struct utun_config* config = parse_config(ccf);
if (!config) { fail("cannot parse protocol test config"); break; }
config->global.auto_socket_protocols = modes[i];
config->global.auto_socket_skip_no_default_route = 0;
config->global.db_path[0] = '\0';
struct UTUN_INSTANCE* inst = utun_instance_create_from_config(ctx.ua, config);
if (!inst) { free_config(config); fail("cannot create protocol test instance"); break; }
if (utun_instance_init(inst) < 0) fail("protocol test socket initialization failed");
if (!ctx.result) {
check_protocol_sockets(inst, ifindex, modes[i]);
auto_socket_remove_interface(inst, ifindex);
check_protocol_sockets(inst, ifindex, 0);
int added = auto_socket_add_interface(inst, ifindex, rounds[0].ifname, 1, 1,
CFG_SERVER_TYPE_NAT, CFG_SERVER_TYPE_NAT);
if (added != (modes[i] == CFG_AUTO_SOCKET_BOTH ? 4 : 2)) fail("explicit auto socket add returned wrong count");
check_protocol_sockets(inst, ifindex, modes[i]);
auto_socket_on_network_change(inst);
uasync_poll(ctx.ua, 0);
check_protocol_sockets(inst, ifindex, modes[i]);
}
inst->running = 0;
utun_instance_destroy(inst);
uasync_poll(ctx.ua, 0);
}
if (ip_addr_del(rounds[0].ifname, "fd42::2/64")) fail("cannot remove IPv6 protocol test address");
}
int main(void) {
debug_config_init();
debug_set_level(DEBUG_LEVEL_WARN);
@@ -791,6 +841,8 @@ int main(void) {
if (ctx.result) return 1;
ctx.ua = uasync_create();
test_protocol_modes();
if (ctx.result) goto done;
ctx.server = utun_instance_create(ctx.ua, scf);
ctx.client = utun_instance_create(ctx.ua, ccf);
if (!ctx.server || !ctx.client) goto done;