auto_socket: Windows-скан + список сокетов в Network Settings (add/remove, чистый rewrite конфига)

This commit is contained in:
Evgeny committed 2026-08-13 22:58:52 +03:00
1 parent d5119ac7c6
commit f82dca3185
8 files changed
+545 -160

No files matched your search

+75 -3
View File
@@ -698,19 +698,91 @@ static void auto_socket_scan_all(struct AUTO_SOCKET* as) {
#else /* _WIN32 */
/* Собирает IfIndex всех UP не-loopback адаптеров. Возвращает число найденных (до max_count). */
static int win_collect_up_ifaces(uint32_t* out_ifindex, int max_count) {
PIP_ADAPTER_ADDRESSES adapters = NULL;
ULONG size = 0;
ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
DWORD rv = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &size);
if (rv != ERROR_BUFFER_OVERFLOW) return 0;
adapters = (PIP_ADAPTER_ADDRESSES)u_malloc(size);
if (!adapters) return 0;
rv = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapters, &size);
if (rv != NO_ERROR) { u_free(adapters); return 0; }
int count = 0;
for (PIP_ADAPTER_ADDRESSES a = adapters; a && count < max_count; a = a->Next) {
if (a->OperStatus != IfOperStatusUp) continue;
if (a->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue;
out_ifindex[count++] = a->IfIndex;
}
u_free(adapters);
return count;
}
static int scan_and_classify_iface(uint32_t ifindex, const char* ifname,
int* out_has_v4, int* out_has_v6,
uint8_t* out_v4_type, uint8_t* out_v6_type) {
(void)ifindex; (void)ifname;
(void)ifname;
*out_has_v4 = 0; *out_has_v6 = 0;
*out_v4_type = CFG_SERVER_TYPE_NAT;
*out_v6_type = CFG_SERVER_TYPE_NAT;
PIP_ADAPTER_ADDRESSES adapters = NULL;
ULONG size = 0;
ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
DWORD rv = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &size);
if (rv != ERROR_BUFFER_OVERFLOW) return -1;
adapters = (PIP_ADAPTER_ADDRESSES)u_malloc(size);
if (!adapters) return -1;
rv = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapters, &size);
if (rv != NO_ERROR) { u_free(adapters); return -1; }
PIP_ADAPTER_ADDRESSES a = adapters;
while (a && a->IfIndex != ifindex) a = a->Next;
if (!a || a->OperStatus != IfOperStatusUp || a->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
u_free(adapters);
return 0;
}
for (PIP_ADAPTER_UNICAST_ADDRESS u = a->FirstUnicastAddress; u; u = u->Next) {
if (!u->Address.lpSockaddr) continue;
if (u->Address.lpSockaddr->sa_family == AF_INET) {
const struct sockaddr_in* sin = (const struct sockaddr_in*)u->Address.lpSockaddr;
if (sin->sin_addr.s_addr == INADDR_ANY) continue;
*out_has_v4 = 1;
if (is_ipv4_public(sin->sin_addr.s_addr)) *out_v4_type = CFG_SERVER_TYPE_PUBLIC;
} else if (u->Address.lpSockaddr->sa_family == AF_INET6) {
const struct sockaddr_in6* sin6 = (const struct sockaddr_in6*)u->Address.lpSockaddr;
int cls = v6_classify(sin6->sin6_addr.s6_addr);
if (cls == AS_V6_OTH || cls == AS_V6_LL) continue;
*out_has_v6 = 1;
if (cls == AS_V6_DIR) *out_v6_type = CFG_SERVER_TYPE_PUBLIC;
}
}
u_free(adapters);
return 0;
}
static void auto_socket_scan_all(struct AUTO_SOCKET* as) {
(void)as;
DEBUG_INFO(DEBUG_CATEGORY_AS, "[as] Windows: auto_socket_scan_all not yet implemented");
uint32_t up[64];
int up_count = win_collect_up_ifaces(up, 64);
for (int i = 0; i < up_count; i++) {
char ifname[IF_NAMESIZE];
if (!if_indextoname(up[i], ifname)) snprintf(ifname, sizeof(ifname), "if%u", up[i]);
reconcile_iface(as, up[i], ifname);
}
/* prune: удаляем сокеты адаптеров, которых больше нет в UP-списке (или они DOWN) */
struct auto_sock_iface** pp = &as->ifaces;
while (*pp) {
struct auto_sock_iface* ifa = *pp;
int found = 0;
for (int i = 0; i < up_count; i++) if (up[i] == ifa->netif_index) { found = 1; break; }
if (!found) { remove_iface_sockets(as, ifa->netif_index); continue; }
pp = &ifa->next;
}
}
#endif /* _WIN32 */