From 88c2d7a4e3052b1b2c9514e310eda9efdfcbf62a Mon Sep 17 00:00:00 2001 From: evgeny Date: Sun, 25 Oct 2026 17:44:52 +0100 Subject: [PATCH] Share LAN interface matching for socket announcements and NCD --- src/routing_layer/sock_match.c | 24 ++++++++++++++++++++++++ src/routing_layer/sock_match.h | 5 +++++ src/transport_layer/node_conn_direct.h | 5 +++++ 3 files changed, 34 insertions(+) diff --git a/src/routing_layer/sock_match.c b/src/routing_layer/sock_match.c index 51ad8be2..956b5ea3 100644 --- a/src/routing_layer/sock_match.c +++ b/src/routing_layer/sock_match.c @@ -50,3 +50,27 @@ int sock_collect_views(struct UTUN_INSTANCE *instance, struct sock_view *out, in } return count; } + +/* Одинаковый подбор интерфейса при публикации endpoint и при создании LAN-линка. */ +int sock_matches_lan(const struct ETCP_SOCKET* socket, const struct sockaddr_storage* local, uint32_t ifindex) { + if (!socket || !local || !ifindex || socket->probe_only || socket->socks_udp || + socket->local_addr.ss_family != local->ss_family || (socket->netif_index && socket->netif_index != ifindex)) return 0; + const struct sockaddr_storage* bound = &socket->local_addr; + if (local->ss_family == AF_INET) { + uint32_t ip = ((const struct sockaddr_in*)bound)->sin_addr.s_addr; + uint32_t target = ((const struct sockaddr_in*)local)->sin_addr.s_addr; + if (ip) return ip == target; + if (socket->netif_index) return 1; + return socket->interface_addr.ss_family == AF_INET && + ((const struct sockaddr_in*)&socket->interface_addr)->sin_addr.s_addr == target; + } + if (local->ss_family == AF_INET6) { + const struct in6_addr* ip = &((const struct sockaddr_in6*)bound)->sin6_addr; + const struct in6_addr* target = &((const struct sockaddr_in6*)local)->sin6_addr; + if (!IN6_IS_ADDR_UNSPECIFIED(ip)) return !memcmp(ip, target, 16); + if (socket->netif_index) return 1; + return socket->interface_addr.ss_family == AF_INET6 && + !memcmp(&((const struct sockaddr_in6*)&socket->interface_addr)->sin6_addr, target, 16); + } + return 0; +} diff --git a/src/routing_layer/sock_match.h b/src/routing_layer/sock_match.h index 7d1ef01e..ca79a488 100644 --- a/src/routing_layer/sock_match.h +++ b/src/routing_layer/sock_match.h @@ -9,6 +9,7 @@ struct UTUN_INSTANCE; struct ETCP_SOCKET; +struct sockaddr_storage; #define SOCK_ROLE_DIRECT 0 #define SOCK_ROLE_OUTGOING 1 @@ -38,5 +39,9 @@ int sock_match(const struct sock_view *view, uint8_t address_type, uint8_t confi /* В потоке ядра заполнить до max views обычных IPv4-сокетов, включая TCP; probe_only исключены. * Возвращает число заполненных (0 также при неверных аргументах); специальной сортировки нет. */ int sock_collect_views(struct UTUN_INSTANCE *instance, struct sock_view *out, int max); +/* 1, если обычный прямой сокет принимает IP local_address на локальном ifindex. + * Проверяет family, bind IP/interface; wildcard без ifindex допускает только известный interface_addr. + * Probe/SOCKS UDP исключены. Адреса заимствованы, порт local_address не используется. */ +int sock_matches_lan(const struct ETCP_SOCKET* socket, const struct sockaddr_storage* local_address, uint32_t ifindex); #endif diff --git a/src/transport_layer/node_conn_direct.h b/src/transport_layer/node_conn_direct.h index 2a8135fb..d84c361c 100644 --- a/src/transport_layer/node_conn_direct.h +++ b/src/transport_layer/node_conn_direct.h @@ -50,6 +50,7 @@ struct NODE_CONN_DIRECT; /* Рабочий ETCP, совместимая исходящая пара либо возможность reverse на наш опубликованный адрес. * Без линков/handles/таймеров/проб. Исходящие пары — тот же обход, что open; reverse — sock_match/публикуемые адреса. * Учитывает IPv6 и исходящий TCP fallback; 1 — кандидат есть, 0 — нет/ошибка. SQLite не загружает. + * Для подтверждённого LAN-кандидата может прочитать идентичность из SQLite без регистрации. * Возможность попытки не доказывает достижимость и не подтверждает готовность группы. */ int node_conn_direct_compatible(struct UTUN_INSTANCE* inst, uint64_t node_id); @@ -100,6 +101,10 @@ void node_conn_direct_close(struct NODE_CONN_DIRECT* h); * Не создаёт соединение и не приобретает handle. Число новых линков, 0 при отсутствии записи/транспорта, -1 при ошибке. * Добавляет недостающие пары и обновляет TCP/REALITY; работающие линки по исчезнувшим адресам сохраняются. */ int node_conn_direct_update_node(struct UTUN_INSTANCE* inst, uint64_t node_id); +/* Применить текущие nonce-подтверждённые LAN-адреса к существующему NCD вне FIN_WAIT. + * Не создаёт транспорт/handle, не меняет snapshot. Число новых линков либо -1; без транспорта — 0. + * Неподтверждённые ETCP-пробы удаляются после истечения LAN-кандидата; работающие линки сохраняются. */ +int node_conn_direct_update_local(struct UTUN_INSTANCE* inst, uint64_t node_id); /* Как close, но последний handle закрывает транспорт сразу, без fin_wait. * При наличии других handle общий транспорт и их callbacks сохраняются. */