mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-01-14 16:57:57 +00:00
IPv6 node support
This will make bitcoin relay valid routable IPv6 addresses, and when USE_IPV6 is enabled, listen on IPv6 interfaces and attempt connections to IPv6 addresses.
This commit is contained in:
parent
508471bbc0
commit
23aa78c405
@ -2,7 +2,7 @@ TEMPLATE = app
|
|||||||
TARGET =
|
TARGET =
|
||||||
VERSION = 0.6.99
|
VERSION = 0.6.99
|
||||||
INCLUDEPATH += src src/json src/qt
|
INCLUDEPATH += src src/json src/qt
|
||||||
DEFINES += QT_GUI BOOST_THREAD_USE_LIB
|
DEFINES += QT_GUI BOOST_THREAD_USE_LIB USE_IPV6
|
||||||
CONFIG += no_include_pwd
|
CONFIG += no_include_pwd
|
||||||
|
|
||||||
# for boost 1.37, add -mt to the boost libraries
|
# for boost 1.37, add -mt to the boost libraries
|
||||||
|
@ -44,7 +44,7 @@ sudo port install qrencode
|
|||||||
4. Now you should be able to build bitcoind:
|
4. Now you should be able to build bitcoind:
|
||||||
|
|
||||||
cd bitcoin/src
|
cd bitcoin/src
|
||||||
make -f makefile.osx
|
make -f makefile.osx USE_IPV6=1
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
./bitcoind --help # for a list of command-line options.
|
./bitcoind --help # for a list of command-line options.
|
||||||
|
@ -43,6 +43,9 @@ your package manager. Set USE_QRCODE to control this:
|
|||||||
USE_QRCODE=0 (the default) No QRCode support - libarcode not required
|
USE_QRCODE=0 (the default) No QRCode support - libarcode not required
|
||||||
USE_QRCODE=1 QRCode support enabled
|
USE_QRCODE=1 QRCode support enabled
|
||||||
|
|
||||||
|
IPv6 support may be enabled by setting
|
||||||
|
USE_IPV6=1 Enable IPv6 support
|
||||||
|
|
||||||
Licenses of statically linked libraries:
|
Licenses of statically linked libraries:
|
||||||
Berkeley DB New BSD license with additional requirement that linked
|
Berkeley DB New BSD license with additional requirement that linked
|
||||||
software must be free open source
|
software must be free open source
|
||||||
@ -80,7 +83,7 @@ emerge -av1 --noreplace boost glib openssl sys-libs/db:4.8
|
|||||||
|
|
||||||
Take the following steps to build (no UPnP support):
|
Take the following steps to build (no UPnP support):
|
||||||
cd ${BITCOIN_DIR}/src
|
cd ${BITCOIN_DIR}/src
|
||||||
make -f makefile.unix USE_UPNP= BDB_INCLUDE_PATH='/usr/include/db4.8'
|
make -f makefile.unix USE_UPNP= USE_IPV6=1 BDB_INCLUDE_PATH='/usr/include/db4.8'
|
||||||
strip bitcoind
|
strip bitcoind
|
||||||
|
|
||||||
|
|
||||||
|
@ -2424,9 +2424,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||||||
{
|
{
|
||||||
if (fShutdown)
|
if (fShutdown)
|
||||||
return true;
|
return true;
|
||||||
// ignore IPv6 for now, since it isn't implemented anyway
|
|
||||||
if (!addr.IsIPv4())
|
|
||||||
continue;
|
|
||||||
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
|
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
|
||||||
addr.nTime = nNow - 5 * 24 * 60 * 60;
|
addr.nTime = nNow - 5 * 24 * 60 * 60;
|
||||||
pfrom->AddAddressKnown(addr);
|
pfrom->AddAddressKnown(addr);
|
||||||
|
@ -27,7 +27,7 @@ LIBS= \
|
|||||||
-l ssl \
|
-l ssl \
|
||||||
-l crypto
|
-l crypto
|
||||||
|
|
||||||
DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB
|
DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DUSE_IPV6
|
||||||
DEBUGFLAGS=-g
|
DEBUGFLAGS=-g
|
||||||
CFLAGS=-O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
CFLAGS=-O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ LIBS= \
|
|||||||
-l ssl \
|
-l ssl \
|
||||||
-l crypto
|
-l crypto
|
||||||
|
|
||||||
DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB
|
DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DUSE_IPV6
|
||||||
DEBUGFLAGS=-g
|
DEBUGFLAGS=-g
|
||||||
CFLAGS=-mthreads -O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
CFLAGS=-mthreads -O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ LIBS += \
|
|||||||
TESTDEFS += -DBOOST_TEST_DYN_LINK
|
TESTDEFS += -DBOOST_TEST_DYN_LINK
|
||||||
endif
|
endif
|
||||||
|
|
||||||
DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0
|
DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DUSE_IPV6
|
||||||
|
|
||||||
ifdef RELEASE
|
ifdef RELEASE
|
||||||
# Compile for maximum compatibility and smallest size.
|
# Compile for maximum compatibility and smallest size.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
USE_UPNP:=0
|
USE_UPNP:=0
|
||||||
|
|
||||||
DEFS=
|
DEFS=-DUSE_IPV6
|
||||||
|
|
||||||
DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
|
DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
|
||||||
LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
|
LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
|
||||||
|
56
src/net.cpp
56
src/net.cpp
@ -733,7 +733,11 @@ void ThreadSocketHandler2(void* parg)
|
|||||||
//
|
//
|
||||||
if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
|
if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
|
||||||
{
|
{
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
struct sockaddr_in6 sockaddr;
|
||||||
|
#else
|
||||||
struct sockaddr_in sockaddr;
|
struct sockaddr_in sockaddr;
|
||||||
|
#endif
|
||||||
socklen_t len = sizeof(sockaddr);
|
socklen_t len = sizeof(sockaddr);
|
||||||
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
|
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
|
||||||
CAddress addr;
|
CAddress addr;
|
||||||
@ -1390,7 +1394,7 @@ void ThreadOpenConnections2(void* parg)
|
|||||||
CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
|
CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
|
||||||
|
|
||||||
// if we selected an invalid address, restart
|
// if we selected an invalid address, restart
|
||||||
if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
|
if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
nTries++;
|
nTries++;
|
||||||
@ -1620,6 +1624,7 @@ void ThreadMessageHandler2(void* parg)
|
|||||||
|
|
||||||
bool BindListenPort(string& strError)
|
bool BindListenPort(string& strError)
|
||||||
{
|
{
|
||||||
|
unsigned short nPort = GetListenPort();
|
||||||
strError = "";
|
strError = "";
|
||||||
int nOne = 1;
|
int nOne = 1;
|
||||||
|
|
||||||
@ -1636,7 +1641,12 @@ bool BindListenPort(string& strError)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create socket for listening for incoming connections
|
// Create socket for listening for incoming connections
|
||||||
hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
#ifdef USE_IPV6
|
||||||
|
int nFamily = AF_INET6;
|
||||||
|
#else
|
||||||
|
int nFamily = AF_INET;
|
||||||
|
#endif
|
||||||
|
hListenSocket = socket(nFamily, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (hListenSocket == INVALID_SOCKET)
|
if (hListenSocket == INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
|
strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
|
||||||
@ -1669,22 +1679,36 @@ bool BindListenPort(string& strError)
|
|||||||
|
|
||||||
// The sockaddr_in structure specifies the address family,
|
// The sockaddr_in structure specifies the address family,
|
||||||
// IP address, and port for the socket that is being bound
|
// IP address, and port for the socket that is being bound
|
||||||
struct sockaddr_in sockaddr;
|
#ifdef USE_IPV6
|
||||||
|
struct sockaddr_in6 sockaddr = sockaddr_in6();
|
||||||
|
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||||
|
sockaddr.sin6_family = AF_INET6;
|
||||||
|
sockaddr.sin6_addr = in6addr_any; // bind to all IPs on this computer
|
||||||
|
sockaddr.sin6_port = htons(nPort);
|
||||||
|
# ifdef WIN32
|
||||||
|
int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
|
||||||
|
int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
|
||||||
|
// this call is allowed to fail
|
||||||
|
setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
struct sockaddr_in sockaddr = sockaddr_in();
|
||||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||||
sockaddr.sin_family = AF_INET;
|
sockaddr.sin_family = AF_INET;
|
||||||
sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
|
sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
|
||||||
sockaddr.sin_port = htons(GetListenPort());
|
sockaddr.sin_port = htons(nPort);
|
||||||
|
#endif
|
||||||
if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
|
if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
int nErr = WSAGetLastError();
|
int nErr = WSAGetLastError();
|
||||||
if (nErr == WSAEADDRINUSE)
|
if (nErr == WSAEADDRINUSE)
|
||||||
strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
|
strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), nPort);
|
||||||
else
|
else
|
||||||
strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
|
strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d, %s)", nPort, nErr, strerror(nErr));
|
||||||
printf("%s\n", strError.c_str());
|
printf("%s\n", strError.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
|
printf("Bound to port %d\n", (int)nPort);
|
||||||
|
|
||||||
// Listen for incoming connections
|
// Listen for incoming connections
|
||||||
if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
|
if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
|
||||||
@ -1727,28 +1751,22 @@ void static Discover()
|
|||||||
if ((ifa->ifa_flags & IFF_UP) == 0) continue;
|
if ((ifa->ifa_flags & IFF_UP) == 0) continue;
|
||||||
if (strcmp(ifa->ifa_name, "lo") == 0) continue;
|
if (strcmp(ifa->ifa_name, "lo") == 0) continue;
|
||||||
if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
|
if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
|
||||||
char pszIP[100];
|
|
||||||
if (ifa->ifa_addr->sa_family == AF_INET)
|
if (ifa->ifa_addr->sa_family == AF_INET)
|
||||||
{
|
{
|
||||||
struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
|
struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
|
||||||
if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
|
|
||||||
printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
|
|
||||||
|
|
||||||
// Take the first IP that isn't loopback 127.x.x.x
|
|
||||||
CNetAddr addr(s4->sin_addr);
|
CNetAddr addr(s4->sin_addr);
|
||||||
AddLocal(addr, LOCAL_IF);
|
if (AddLocal(addr, LOCAL_IF))
|
||||||
|
printf("ipv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
|
||||||
}
|
}
|
||||||
|
#ifdef USE_IPV6
|
||||||
else if (ifa->ifa_addr->sa_family == AF_INET6)
|
else if (ifa->ifa_addr->sa_family == AF_INET6)
|
||||||
{
|
{
|
||||||
struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
|
struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
|
||||||
if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
|
|
||||||
printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
|
|
||||||
|
|
||||||
#ifdef USE_IPV6
|
|
||||||
CNetAddr addr(s6->sin6_addr);
|
CNetAddr addr(s6->sin6_addr);
|
||||||
AddLocal(addr, LOCAL_IF);
|
if (AddLocal(addr, LOCAL_IF))
|
||||||
#endif
|
printf("ipv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
freeifaddrs(myaddrs);
|
freeifaddrs(myaddrs);
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,37 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
|||||||
{
|
{
|
||||||
hSocketRet = INVALID_SOCKET;
|
hSocketRet = INVALID_SOCKET;
|
||||||
|
|
||||||
SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
struct sockaddr_storage sockaddr;
|
||||||
|
int nFamily = 0;
|
||||||
|
size_t nSockAddrLen = 0;
|
||||||
|
|
||||||
|
if (addrConnect.IsIPv4())
|
||||||
|
{
|
||||||
|
// Use IPv4 stack to connect to IPv4 addresses
|
||||||
|
struct sockaddr_in sockaddr4;
|
||||||
|
if (!addrConnect.GetSockAddr(&sockaddr4))
|
||||||
|
return false;
|
||||||
|
memcpy(&sockaddr, &sockaddr4, sizeof(sockaddr4));
|
||||||
|
nSockAddrLen = sizeof(sockaddr4);
|
||||||
|
nFamily = AF_INET;
|
||||||
|
}
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
else if (addrConnect.IsIPv6())
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 sockaddr6;
|
||||||
|
if (!addrConnect.GetSockAddr6(&sockaddr6))
|
||||||
|
return false;
|
||||||
|
memcpy(&sockaddr, &sockaddr6, sizeof(sockaddr6));
|
||||||
|
nSockAddrLen = sizeof(sockaddr6);
|
||||||
|
nFamily = AF_INET6;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else {
|
||||||
|
printf("Cannot connect to %s: unsupported network\n", addrConnect.ToString().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET hSocket = socket(nFamily, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (hSocket == INVALID_SOCKET)
|
if (hSocket == INVALID_SOCKET)
|
||||||
return false;
|
return false;
|
||||||
#ifdef SO_NOSIGPIPE
|
#ifdef SO_NOSIGPIPE
|
||||||
@ -313,13 +343,6 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
|||||||
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
|
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct sockaddr_in sockaddr;
|
|
||||||
if (!addrConnect.GetSockAddr(&sockaddr))
|
|
||||||
{
|
|
||||||
closesocket(hSocket);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
u_long fNonblock = 1;
|
u_long fNonblock = 1;
|
||||||
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
|
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
|
||||||
@ -332,7 +355,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
|
if (connect(hSocket, (struct sockaddr*)&sockaddr, nSockAddrLen) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
// WSAEINVAL is here because some legacy version of winsock uses it
|
// WSAEINVAL is here because some legacy version of winsock uses it
|
||||||
if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
|
if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
|
||||||
@ -531,6 +554,11 @@ bool CNetAddr::IsIPv4() const
|
|||||||
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
|
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CNetAddr::IsIPv6() const
|
||||||
|
{
|
||||||
|
return (!IsIPv4());
|
||||||
|
}
|
||||||
|
|
||||||
bool CNetAddr::IsRFC1918() const
|
bool CNetAddr::IsRFC1918() const
|
||||||
{
|
{
|
||||||
return IsIPv4() && (
|
return IsIPv4() && (
|
||||||
@ -919,12 +947,16 @@ std::vector<unsigned char> CService::GetKey() const
|
|||||||
|
|
||||||
std::string CService::ToStringPort() const
|
std::string CService::ToStringPort() const
|
||||||
{
|
{
|
||||||
return strprintf(":%i", port);
|
return strprintf("%i", port);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CService::ToStringIPPort() const
|
std::string CService::ToStringIPPort() const
|
||||||
{
|
{
|
||||||
return ToStringIP() + ToStringPort();
|
if (IsIPv4()) {
|
||||||
|
return ToStringIP() + ":" + ToStringPort();
|
||||||
|
} else {
|
||||||
|
return "[" + ToStringIP() + "]:" + ToStringPort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CService::ToString() const
|
std::string CService::ToString() const
|
||||||
|
@ -31,6 +31,7 @@ class CNetAddr
|
|||||||
void Init();
|
void Init();
|
||||||
void SetIP(const CNetAddr& ip);
|
void SetIP(const CNetAddr& ip);
|
||||||
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
||||||
|
bool IsIPv6() const; // IPv6 address (not IPv4)
|
||||||
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
||||||
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
|
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
|
||||||
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
|
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
|
||||||
|
Loading…
Reference in New Issue
Block a user