Skip to content

Commit 33983c5

Browse files
committed
LocalIP: improve preferred IPv6 address detection
1 parent 8cfee9d commit 33983c5

1 file changed

Lines changed: 20 additions & 6 deletions

File tree

src/detection/localip/localip_linux.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <stdio.h>
1313
#include <sys/ioctl.h>
1414
#include <inttypes.h>
15+
#include <fcntl.h>
1516

1617
#ifdef __linux__
1718
#include <linux/ethtool.h>
@@ -142,12 +143,26 @@ static bool isIPv6AddressPreferred(const char* ifname, struct sockaddr_in6* addr
142143
#define IN6_IS_ADDR_GLOBAL(a) \
143144
((((const uint32_t *) (a))[0] & htonl(0x70000000)) == htonl(0x20000000))
144145
#endif
145-
if (!IN6_IS_ADDR_GLOBAL(&addr->sin6_addr))
146+
#ifndef IN6_IS_ADDR_UNIQUE_LOCAL
147+
#define IN6_IS_ADDR_UNIQUE_LOCAL(a) \
148+
((((const uint32_t *) (a))[0] & htonl(0xfe000000)) == htonl(0xfc000000))
149+
#endif
150+
if (!IN6_IS_ADDR_GLOBAL(&addr->sin6_addr) && !IN6_IS_ADDR_UNIQUE_LOCAL(&addr->sin6_addr))
146151
return false;
147152

148153
#ifdef SIOCGIFAFLAG_IN6
149154
static int sockfd = 0;
150-
if (sockfd == 0) sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
155+
if (sockfd == 0)
156+
{
157+
sockfd = socket(AF_INET6, SOCK_DGRAM
158+
#ifdef SOCK_CLOEXEC
159+
| SOCK_CLOEXEC
160+
#endif
161+
, 0);
162+
#ifndef SOCK_CLOEXEC
163+
if (sockfd > 0) fcntl(sockfd, F_SETFD, FD_CLOEXEC);
164+
#endif
165+
}
151166
if (sockfd < 0) return true; // Give up
152167

153168
struct in6_ifreq ifr6 = {};
@@ -157,7 +172,7 @@ static bool isIPv6AddressPreferred(const char* ifname, struct sockaddr_in6* addr
157172
if (ioctl(sockfd, SIOCGIFAFLAG_IN6, &ifr6) != 0)
158173
return true;
159174

160-
return !(ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED) && !(ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TEMPORARY);
175+
return !(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY | IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED | IN6_IFF_OPTIMISTIC));
161176
#elif __linux__
162177
FF_UNUSED(ifname);
163178

@@ -181,9 +196,8 @@ static bool isIPv6AddressPreferred(const char* ifname, struct sockaddr_in6* addr
181196
&entry->s6_addr[8], &entry->s6_addr[9], &entry->s6_addr[10], &entry->s6_addr[11],
182197
&entry->s6_addr[12], &entry->s6_addr[13], &entry->s6_addr[14], &entry->s6_addr[15],
183198
&flags) != 17 ||
184-
!IN6_IS_ADDR_GLOBAL(entry) ||
185-
(flags & IFA_F_DEPRECATED) ||
186-
(flags & IFA_F_TEMPORARY)
199+
(!IN6_IS_ADDR_GLOBAL(entry) && !IN6_IS_ADDR_UNIQUE_LOCAL(entry)) ||
200+
(flags & (IFA_F_DEPRECATED | IFA_F_TEMPORARY | IFA_F_TENTATIVE | IFA_F_DADFAILED | IFA_F_OPTIMISTIC))
187201
)
188202
--addresses.length;
189203
}

0 commit comments

Comments
 (0)