From 5066cff333970508deedb322618203ba354969cf Mon Sep 17 00:00:00 2001 From: evgeny Date: Thu, 6 Aug 2026 13:17:39 +0300 Subject: [PATCH] fix: IPv6 bind to permanent SLAAC address instead of :: - etcp_connections.c: detect interface_addr before bind(), use specific IPv6 addr instead of in6addr_any (netlink path for Linux, connect trick for Android) - chat_profile.c: filter PRIVATE/LOCAL sockets from node_addresses sync - conn_mgr_core.c: diagnostic logs in cm_invite_tcp_connect, continue to next addr on TCP connect failure - node_conn_direct.c: diagnostic logs in ncd_create_links - auto_socket.c: suppress spurious ADDR_CHANGED events - etcp_api.c: extended socket event log --- src/chat/chat_profile.c | 7 +- src/routing_layer/conn_mgr_core.c | 17 +++-- src/transport_layer/auto_socket.c | 14 +++- src/transport_layer/etcp_api.c | 9 ++- src/transport_layer/etcp_connections.c | 91 ++++++++++++++------------ src/transport_layer/node_conn_direct.c | 12 ++-- 6 files changed, 95 insertions(+), 55 deletions(-) diff --git a/src/chat/chat_profile.c b/src/chat/chat_profile.c index 9c4dd97e..70d8a803 100644 --- a/src/chat/chat_profile.c +++ b/src/chat/chat_profile.c @@ -114,9 +114,10 @@ void chat_core_sync_my_addresses(void) { } struct ETCP_SOCKET* sock = g_cc.inst->etcp_sockets; - int sock_count = 0, written = 0, tcp_written = 0; + int sock_count = 0, written = 0, tcp_written = 0, skipped = 0; while (sock) { sock_count++; + if (sock->type == CFG_SERVER_TYPE_PRIVATE || sock->type == CFG_SERVER_TYPE_LOCAL) { skipped++; sock = sock->next; continue; } int sock_family = sock->local_addr.ss_family ? sock->local_addr.ss_family : 0; struct sockaddr_storage* sa = (sock->interface_addr.ss_family == sock_family) ? &sock->interface_addr : NULL; if (!sa) sa = sock->local_addr.ss_family ? &sock->local_addr : NULL; @@ -200,8 +201,8 @@ void chat_core_sync_my_addresses(void) { else if (written == 0 && tcp_written == 0) DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] %d sockets found but 0 addresses written", CC_ID, sock_count); else - DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] DONE: %d UDP + %d TCP = %d total, my_node=0x%016llx", - CC_ID, written, tcp_written, written + tcp_written, (unsigned long long)g_cc.my_node_id); + DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] DONE: %d UDP + %d TCP = %d total (skipped %d PRIVATE/LOCAL), my_node=0x%016llx", + CC_ID, written, tcp_written, written + tcp_written, skipped, (unsigned long long)g_cc.my_node_id); sqlite3_stmt* chk = NULL; sqlite3_prepare_v2(g_cc.db, "SELECT COUNT(*) FROM node_addresses WHERE node_id=? AND addr_type=0", -1, &chk, NULL); diff --git a/src/routing_layer/conn_mgr_core.c b/src/routing_layer/conn_mgr_core.c index 4a58da91..1d20d0f3 100644 --- a/src/routing_layer/conn_mgr_core.c +++ b/src/routing_layer/conn_mgr_core.c @@ -943,7 +943,10 @@ static void cm_tcp_close_cb(struct stcp_link* link, int err, void* arg) { static int cm_invite_tcp_connect(struct cm_invite_pending* inv, const struct TOPO_NODE* ni) { for (const struct TOPO_ADDR4* a = ni->v4_addrs; a; a = a->next) { - if (!(a->protocol & TOPO_PROTO_TCP)) continue; + if (!(a->protocol & TOPO_PROTO_TCP)) { + DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[cm_invite] v4 skip proto=%02x port=%d node=0x%016llx", a->protocol, (int)a->port, (unsigned long long)inv->node_id); + continue; + } struct sockaddr_in sin; memset(&sin,0,sizeof(sin)); sin.sin_family=AF_INET; memcpy(&sin.sin_addr.s_addr,a->addr,4); sin.sin_port=htons(a->port); struct sockaddr_storage sa; memcpy(&sa,&sin,sizeof(sin)); @@ -954,15 +957,21 @@ static int cm_invite_tcp_connect(struct cm_invite_pending* inv, const struct TOP DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "invite: TCP connecting to %d.%d.%d.%d:%d", a->addr[0], a->addr[1], a->addr[2], a->addr[3], (int)a->port); return 1; } - return 0; + DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[cm_invite] v4 connect FAIL %d.%d.%d.%d:%d node=0x%016llx", + a->addr[0], a->addr[1], a->addr[2], a->addr[3], (int)a->port, (unsigned long long)inv->node_id); } for (const struct TOPO_ADDR6* a6 = ni->v6_addrs; a6; a6 = a6->next) { - if (!(a6->protocol & TOPO_PROTO_TCP)) continue; + if (!(a6->protocol & TOPO_PROTO_TCP)) { + DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[cm_invite] v6 skip proto=%02x port=%d node=0x%016llx", a6->protocol, (int)a6->port, (unsigned long long)inv->node_id); + continue; + } struct sockaddr_in6 sin6; memset(&sin6,0,sizeof(sin6)); sin6.sin6_family=AF_INET6; memcpy(&sin6.sin6_addr,a6->addr,16); sin6.sin6_port=htons(a6->port); if (cm_classify_v6_addr(a6->addr) == CM_V6_LL) { struct ETCP_SOCKET* sv = inv->mgr->instance->etcp_sockets; while (sv) { if (sv->local_addr.ss_family == AF_INET6 && sv->netif_index) { sin6.sin6_scope_id = sv->netif_index; break; } sv = sv->next; } + if (sin6.sin6_scope_id == 0) + DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "[cm_invite] v6 LL no scope_id port=%d node=0x%016llx", (int)a6->port, (unsigned long long)inv->node_id); } struct sockaddr_storage sa; memcpy(&sa,&sin6,sizeof(sin6)); struct stcp_link_config cfg = {.ua=inv->mgr->instance->ua, .my_keys=&inv->mgr->instance->my_keys, .inst=inv->mgr->instance, @@ -972,7 +981,7 @@ static int cm_invite_tcp_connect(struct cm_invite_pending* inv, const struct TOP DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "invite: TCP6 connecting to port %d", (int)a6->port); return 1; } - return 0; + DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[cm_invite] v6 connect FAIL port=%d node=0x%016llx", (int)a6->port, (unsigned long long)inv->node_id); } return 0; } diff --git a/src/transport_layer/auto_socket.c b/src/transport_layer/auto_socket.c index 0ccb8112..d568c65e 100644 --- a/src/transport_layer/auto_socket.c +++ b/src/transport_layer/auto_socket.c @@ -384,8 +384,13 @@ static void reconcile_iface(struct AUTO_SOCKET* as, uint32_t ifindex, const char { struct ETCP_SOCKET* s = as->instance->etcp_sockets; while (s) { if (s->netif_index == ifindex && s->local_addr.ss_family == AF_INET) { ifa->v4_sock = s; break; } s = s->next; } } } else if (has_v4 && sock) { + struct sockaddr_storage old4 = sock->interface_addr; socket_monitor_update_if_addr(sock); - etcp_socket_cbk_fire(sock, ETCP_SOCKET_EVENT_ADDR_CHANGED); + if (memcmp(&old4, &sock->interface_addr, sizeof(old4)) != 0) { + DEBUG_INFO(DEBUG_CATEGORY_AS, "[as] v4 interface_addr changed: %s -> %s", + sockaddr_storage_to_str(&old4).str, sockaddr_storage_to_str(&sock->interface_addr).str); + etcp_socket_cbk_fire(sock, ETCP_SOCKET_EVENT_ADDR_CHANGED); + } } } @@ -414,8 +419,13 @@ static void reconcile_iface(struct AUTO_SOCKET* as, uint32_t ifindex, const char { struct ETCP_SOCKET* s = as->instance->etcp_sockets; while (s) { if (s->netif_index == ifindex && s->local_addr.ss_family == AF_INET6) { ifa->v6_sock = s; break; } s = s->next; } } } else if (has_v6 && sock) { + struct sockaddr_storage old6 = sock->interface_addr; socket_monitor_update_if_addr(sock); - etcp_socket_cbk_fire(sock, ETCP_SOCKET_EVENT_ADDR_CHANGED); + if (memcmp(&old6, &sock->interface_addr, sizeof(old6)) != 0) { + DEBUG_INFO(DEBUG_CATEGORY_AS, "[as] v6 interface_addr changed: %s -> %s", + sockaddr_storage_to_str(&old6).str, sockaddr_storage_to_str(&sock->interface_addr).str); + etcp_socket_cbk_fire(sock, ETCP_SOCKET_EVENT_ADDR_CHANGED); + } } } diff --git a/src/transport_layer/etcp_api.c b/src/transport_layer/etcp_api.c index 61667416..4504dcbe 100644 --- a/src/transport_layer/etcp_api.c +++ b/src/transport_layer/etcp_api.c @@ -137,7 +137,14 @@ void etcp_socket_cbk_fire(struct ETCP_SOCKET* sock, int event) { if (!sock || !sock->instance) return; static const char* names[] = { "ADDR_CHANGED", "STATUS_CHANGED" }; int idx = 0, e = event; while (e >>= 1) idx++; - DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket %s event: %s", sock->name, (idx >= 0 && idx < (int)(sizeof(names)/sizeof(names[0]))) ? names[idx] : "?"); + const char* name = (idx >= 0 && idx < (int)(sizeof(names)/sizeof(names[0]))) ? names[idx] : "?"; + DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socket %s event: %s", sock->name, name); + DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "socket %s event: %s if_addr=%s local=%s nat=%s type=%d netif=%u", + sock->name, name, + sockaddr_storage_to_str(&sock->interface_addr).str, + sockaddr_storage_to_str(&sock->local_addr).str, + sockaddr_storage_to_str(&sock->nat_addr).str, + sock->type, sock->netif_index); struct etcp_socket_cbk_entry* cbe = sock->instance->socket_cbks; while (cbe) { struct etcp_socket_cbk_entry* n = cbe->next; if (cbe->event_mask & event) cbe->fn(sock, event, cbe->arg); cbe = n; } } diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index 2355dc27..146410fa 100644 --- a/src/transport_layer/etcp_connections.c +++ b/src/transport_layer/etcp_connections.c @@ -609,36 +609,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S } #endif - // Store the local address and bind socket if provided - if (ip) { - memcpy(&e_sock->local_addr, ip, sizeof(struct sockaddr_storage)); - - // CRITICAL: Actually bind the socket to the address - socklen_t addr_len = (ip->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - if (bind(e_sock->fd, (struct sockaddr*)ip, addr_len) < 0) { - DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[ETCP] Failed to bind socket to address family %d: %s", - ip->ss_family, socket_strerror(socket_get_error())); - if (ip->ss_family == AF_INET) { - struct sockaddr_in* sin = (struct sockaddr_in*)ip; - DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[ETCP] Failed to bind to %s:%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port)); - } else if (ip->ss_family == AF_INET6) { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ip; - DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[ETCP] Failed to bind to %s:%d", ip_to_str(&sin6->sin6_addr, AF_INET6).str, ntohs(sin6->sin6_port)); - } - socket_close_wrapper(e_sock->fd); - u_free(e_sock); - return NULL; - } - - if (ip->ss_family == AF_INET) { - struct sockaddr_in* sin = (struct sockaddr_in*)ip; - DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Successfully bound socket to local address, family=AF_INET %s:%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port)); - } else if (ip->ss_family == AF_INET6) { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ip; - DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Successfully bound socket to local address, family=AF_INET6 %s:%d", ip_to_str(&sin6->sin6_addr, AF_INET6).str, ntohs(sin6->sin6_port)); - } - } - // Определяем interface_addr: IP интерфейса или из конфига + // Определяем interface_addr до bind, чтобы забиндить на конкретный адрес memset(&e_sock->interface_addr, 0, sizeof(e_sock->interface_addr)); if (netif_index > 0 && ip && ip->ss_family == AF_INET) { uint32_t if_ip = get_interface_ip_by_index(netif_index); @@ -651,7 +622,6 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S if (ip->ss_family == AF_INET) { struct sockaddr_in* sin = (struct sockaddr_in*)ip; if (sin->sin_addr.s_addr == 0) { - // 0.0.0.0 — определяем через default route struct sockaddr_storage remote; memset(&remote, 0, sizeof(remote)); struct sockaddr_in* rem_sin = (struct sockaddr_in*)&remote; @@ -665,7 +635,6 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S } else if (ip->ss_family == AF_INET6) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ip; if (memcmp(&sin6->sin6_addr, &in6addr_any, sizeof(struct in6_addr)) == 0) { - // :: — приоритет: permanent > temporary > get_outgoing_local_ip uint16_t v6if = (netif_index > 0) ? netif_index : get_default_route_netif_index(AF_INET6); if (v6if > 0) { uint8_t v6addr[16]; @@ -675,6 +644,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S struct sockaddr_in6* if6 = (struct sockaddr_in6*)&e_sock->interface_addr; if6->sin6_family = AF_INET6; memcpy(&if6->sin6_addr, v6addr, 16); + if6->sin6_port = sin6->sin6_port; } } if (e_sock->interface_addr.ss_family == 0) { @@ -684,15 +654,15 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S rem_sin6->sin6_family = AF_INET6; rem_sin6->sin6_port = htons(53); inet_pton(AF_INET6, "2001:4860:4860::8888", &rem_sin6->sin6_addr); - if (get_outgoing_local_ip(ip, &remote, &e_sock->interface_addr) != 0) { - DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to detect outgoing local IPv6 for socket %s", e_sock->name); + if (get_outgoing_local_ip(ip, &remote, &e_sock->interface_addr) == 0) { + struct sockaddr_in6* if6 = (struct sockaddr_in6*)&e_sock->interface_addr; + if6->sin6_port = sin6->sin6_port; } } } } } if (e_sock->interface_addr.ss_family == 0) { - // Не удалось определить автоматически — используем адрес из конфига if (ip) memcpy(&e_sock->interface_addr, ip, sizeof(struct sockaddr_storage)); } // Копируем порт из конфига в interface_addr @@ -708,6 +678,36 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S } } + // Bind — используем interface_addr если определён, иначе ip из конфига + { + struct sockaddr_storage* bind_addr = (e_sock->interface_addr.ss_family != 0) ? &e_sock->interface_addr : ip; + if (bind_addr && bind_addr->ss_family != 0) { + memcpy(&e_sock->local_addr, bind_addr, sizeof(struct sockaddr_storage)); + socklen_t addr_len = (bind_addr->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); + if (bind(e_sock->fd, (struct sockaddr*)bind_addr, addr_len) < 0) { + DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[ETCP] Failed to bind socket to address family %d: %s", + bind_addr->ss_family, socket_strerror(socket_get_error())); + if (bind_addr->ss_family == AF_INET) { + struct sockaddr_in* sin = (struct sockaddr_in*)bind_addr; + DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[ETCP] Failed to bind to %s:%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port)); + } else if (bind_addr->ss_family == AF_INET6) { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)bind_addr; + DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[ETCP] Failed to bind to %s:%d", ip_to_str(&sin6->sin6_addr, AF_INET6).str, ntohs(sin6->sin6_port)); + } + socket_close_wrapper(e_sock->fd); + u_free(e_sock); + return NULL; + } + if (bind_addr->ss_family == AF_INET) { + struct sockaddr_in* sin = (struct sockaddr_in*)bind_addr; + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Successfully bound socket to local address, family=AF_INET %s:%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port)); + } else if (bind_addr->ss_family == AF_INET6) { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)bind_addr; + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Successfully bound socket to local address, family=AF_INET6 %s:%d", ip_to_str(&sin6->sin6_addr, AF_INET6).str, ntohs(sin6->sin6_port)); + } + } + } + char config_str[64] = "none"; char netif_str[64] = "none"; if (e_sock->local_addr.ss_family != 0) { @@ -1065,11 +1065,10 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) { struct sockaddr_storage* addr=&dgram->link->remote_addr; socklen_t addr_len = (addr->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - - // Debug: print where we're sending the packet - if (addr->ss_family == AF_INET) { - struct sockaddr_in* sin = (struct sockaddr_in*)addr; - // inet_ntop removed - use ip_to_str + if (addr->ss_family == AF_INET6) { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr; + DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[v6_send] fd=%d dst=%-39s scope=%u", dgram->link->conn->fd, + sockaddr_storage_to_str(addr).str, sin6->sin6_scope_id); } ssize_t sent = etcp_udp_send(dgram->link, dgram->link->conn->fd, enc_buf, enc_buf_len + dgram->noencrypt_len, @@ -1663,7 +1662,17 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { socklen_t addr_len=sizeof(addr); memset(&addr, 0, sizeof(addr)); ssize_t recv_len = socket_recvfrom(sock, data, PACKET_DATA_SIZE, (struct sockaddr*)&addr, &addr_len); - + if (recv_len > 0 && addr.ss_family == AF_INET6) { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&addr; + DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[v6_recv] sock=%s fd=%d src=[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d len=%zd scope=%u", + e_sock->name, (int)sock, + sin6->sin6_addr.s6_addr[0],sin6->sin6_addr.s6_addr[1],sin6->sin6_addr.s6_addr[2],sin6->sin6_addr.s6_addr[3], + sin6->sin6_addr.s6_addr[4],sin6->sin6_addr.s6_addr[5],sin6->sin6_addr.s6_addr[6],sin6->sin6_addr.s6_addr[7], + sin6->sin6_addr.s6_addr[8],sin6->sin6_addr.s6_addr[9],sin6->sin6_addr.s6_addr[10],sin6->sin6_addr.s6_addr[11], + sin6->sin6_addr.s6_addr[12],sin6->sin6_addr.s6_addr[13],sin6->sin6_addr.s6_addr[14],sin6->sin6_addr.s6_addr[15], + (int)ntohs(sin6->sin6_port), recv_len, sin6->sin6_scope_id); + } + if (recv_len <= 0) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "recvfrom failed, error=%zd, sock_err=%d", recv_len, socket_get_error()); return; diff --git a/src/transport_layer/node_conn_direct.c b/src/transport_layer/node_conn_direct.c index 7fcf2cb6..02adb21d 100644 --- a/src/transport_layer/node_conn_direct.c +++ b/src/transport_layer/node_conn_direct.c @@ -130,6 +130,7 @@ static int ncd_create_links(struct ncd_entry* entry, struct TOPO_NODE* ni, struct ETCP_CONN* conn = entry->conn; struct UTUN_INSTANCE* inst = conn->instance; int link_count = 0; + uint64_t nid = entry->node_id; /* ---- IPv4 ---- */ { @@ -142,13 +143,14 @@ static int ncd_create_links(struct ncd_entry* entry, struct TOPO_NODE* ni, if (s->local_addr.ss_family == AF_INET && s->type != CFG_SERVER_TYPE_PRIVATE) socks[sock_count++] = s; } + if (sock_count == 0) DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[ncd] v4 sock_count=0 node=0x%016llx", (unsigned long long)nid); if (sock_count > 0) { int rr = 0; for (const struct TOPO_ADDR4* a = ni->v4_addrs; a; a = a->next) { - if (a->port == 0 || !(a->protocol & TOPO_PROTO_UDP)) continue; + if (a->port == 0 || !(a->protocol & TOPO_PROTO_UDP)) { DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[ncd] v4 skip proto=%02x port=%d node=0x%016llx", a->protocol, (int)a->port, (unsigned long long)nid); continue; } int zero = 1; for (int j = 0; j < 4; j++) if (a->addr[j] != 0) { zero = 0; break; } - if (zero) continue; + if (zero) { DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[ncd] v4 skip zero-addr node=0x%016llx", (unsigned long long)nid); continue; } struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; memcpy(&sin.sin_addr.s_addr, a->addr, 4); sin.sin_port = htons(a->port); struct sockaddr_storage sa; memcpy(&sa, &sin, sizeof(sin)); @@ -191,12 +193,14 @@ static int ncd_create_links(struct ncd_entry* entry, struct TOPO_NODE* ni, socks[sock_count++] = s; } + if (sock_count == 0) DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[ncd] v6 sock_count=0 node=0x%016llx", (unsigned long long)nid); + if (sock_count > 0) { int rr = 0; for (const struct TOPO_ADDR6* a = ni->v6_addrs; a; a = a->next) { - if (a->port == 0 || !(a->protocol & TOPO_PROTO_UDP)) continue; + if (a->port == 0 || !(a->protocol & TOPO_PROTO_UDP)) { DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[ncd] v6 skip proto=%02x port=%d node=0x%016llx", a->protocol, (int)a->port, (unsigned long long)nid); continue; } int zero = 1; for (int j = 0; j < 16; j++) if (a->addr[j] != 0) { zero = 0; break; } - if (zero) continue; + if (zero) { DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[ncd] v6 skip zero-addr node=0x%016llx", (unsigned long long)nid); continue; } struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; memcpy(&sin6.sin6_addr, a->addr, 16); sin6.sin6_port = htons(a->port); struct ETCP_SOCKET* use_sock = socks[rr++ % sock_count];