From 33983c5402f07a4e0a42ddac22d35ef1b1f7dc1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Aug 2025 14:16:46 +0800 Subject: [PATCH] LocalIP: improve preferred IPv6 address detection --- src/detection/localip/localip_linux.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 5f9869083..ed2bf866c 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef __linux__ #include @@ -142,12 +143,26 @@ static bool isIPv6AddressPreferred(const char* ifname, struct sockaddr_in6* addr #define IN6_IS_ADDR_GLOBAL(a) \ ((((const uint32_t *) (a))[0] & htonl(0x70000000)) == htonl(0x20000000)) #endif - if (!IN6_IS_ADDR_GLOBAL(&addr->sin6_addr)) +#ifndef IN6_IS_ADDR_UNIQUE_LOCAL +#define IN6_IS_ADDR_UNIQUE_LOCAL(a) \ + ((((const uint32_t *) (a))[0] & htonl(0xfe000000)) == htonl(0xfc000000)) +#endif + if (!IN6_IS_ADDR_GLOBAL(&addr->sin6_addr) && !IN6_IS_ADDR_UNIQUE_LOCAL(&addr->sin6_addr)) return false; #ifdef SIOCGIFAFLAG_IN6 static int sockfd = 0; - if (sockfd == 0) sockfd = socket(AF_INET6, SOCK_DGRAM, 0); + if (sockfd == 0) + { + sockfd = socket(AF_INET6, SOCK_DGRAM + #ifdef SOCK_CLOEXEC + | SOCK_CLOEXEC + #endif + , 0); + #ifndef SOCK_CLOEXEC + if (sockfd > 0) fcntl(sockfd, F_SETFD, FD_CLOEXEC); + #endif + } if (sockfd < 0) return true; // Give up struct in6_ifreq ifr6 = {}; @@ -157,7 +172,7 @@ static bool isIPv6AddressPreferred(const char* ifname, struct sockaddr_in6* addr if (ioctl(sockfd, SIOCGIFAFLAG_IN6, &ifr6) != 0) return true; - return !(ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED) && !(ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TEMPORARY); + return !(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY | IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED | IN6_IFF_OPTIMISTIC)); #elif __linux__ FF_UNUSED(ifname); @@ -181,9 +196,8 @@ static bool isIPv6AddressPreferred(const char* ifname, struct sockaddr_in6* addr &entry->s6_addr[8], &entry->s6_addr[9], &entry->s6_addr[10], &entry->s6_addr[11], &entry->s6_addr[12], &entry->s6_addr[13], &entry->s6_addr[14], &entry->s6_addr[15], &flags) != 17 || - !IN6_IS_ADDR_GLOBAL(entry) || - (flags & IFA_F_DEPRECATED) || - (flags & IFA_F_TEMPORARY) + (!IN6_IS_ADDR_GLOBAL(entry) && !IN6_IS_ADDR_UNIQUE_LOCAL(entry)) || + (flags & (IFA_F_DEPRECATED | IFA_F_TEMPORARY | IFA_F_TENTATIVE | IFA_F_DADFAILED | IFA_F_OPTIMISTIC)) ) --addresses.length; }