aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bitcoin-qt.pro2
-rw-r--r--doc/build-osx.txt2
-rw-r--r--doc/build-unix.txt5
-rw-r--r--src/main.cpp3
-rw-r--r--src/makefile.linux-mingw2
-rw-r--r--src/makefile.mingw2
-rw-r--r--src/makefile.osx2
-rw-r--r--src/makefile.unix2
-rw-r--r--src/net.cpp56
-rw-r--r--src/netbase.cpp54
-rw-r--r--src/netbase.h1
11 files changed, 91 insertions, 40 deletions
diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro
index 112e8e9389..c9bbc873b1 100644
--- a/bitcoin-qt.pro
+++ b/bitcoin-qt.pro
@@ -2,7 +2,7 @@ TEMPLATE = app
TARGET =
VERSION = 0.6.99
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
# for boost 1.37, add -mt to the boost libraries
diff --git a/doc/build-osx.txt b/doc/build-osx.txt
index 2ae77067fc..256614f7ab 100644
--- a/doc/build-osx.txt
+++ b/doc/build-osx.txt
@@ -44,7 +44,7 @@ sudo port install qrencode
4. Now you should be able to build bitcoind:
cd bitcoin/src
-make -f makefile.osx
+make -f makefile.osx USE_IPV6=1
Run:
./bitcoind --help # for a list of command-line options.
diff --git a/doc/build-unix.txt b/doc/build-unix.txt
index c5b4205084..eb59736816 100644
--- a/doc/build-unix.txt
+++ b/doc/build-unix.txt
@@ -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=1 QRCode support enabled
+IPv6 support may be enabled by setting
+ USE_IPV6=1 Enable IPv6 support
+
Licenses of statically linked libraries:
Berkeley DB New BSD license with additional requirement that linked
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):
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
diff --git a/src/main.cpp b/src/main.cpp
index b0ed28aa14..f9691a5d52 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2424,9 +2424,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
if (fShutdown)
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)
addr.nTime = nNow - 5 * 24 * 60 * 60;
pfrom->AddAddressKnown(addr);
diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw
index 645f0a16e4..373b49ab0a 100644
--- a/src/makefile.linux-mingw
+++ b/src/makefile.linux-mingw
@@ -27,7 +27,7 @@ LIBS= \
-l ssl \
-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
CFLAGS=-O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
diff --git a/src/makefile.mingw b/src/makefile.mingw
index bb6466954f..156eb17cc1 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -23,7 +23,7 @@ LIBS= \
-l ssl \
-l crypto
-DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB
+DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DUSE_IPV6
DEBUGFLAGS=-g
CFLAGS=-mthreads -O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
diff --git a/src/makefile.osx b/src/makefile.osx
index eb9ae4ba7f..9c05d500ae 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -53,7 +53,7 @@ LIBS += \
TESTDEFS += -DBOOST_TEST_DYN_LINK
endif
-DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0
+DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DUSE_IPV6
ifdef RELEASE
# Compile for maximum compatibility and smallest size.
diff --git a/src/makefile.unix b/src/makefile.unix
index 53fb1f0b8d..ce8b55cdf6 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -4,7 +4,7 @@
USE_UPNP:=0
-DEFS=
+DEFS=-DUSE_IPV6
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))
diff --git a/src/net.cpp b/src/net.cpp
index 8603514f91..75c8bbabaf 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -733,7 +733,11 @@ void ThreadSocketHandler2(void* parg)
//
if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
{
+#ifdef USE_IPV6
+ struct sockaddr_in6 sockaddr;
+#else
struct sockaddr_in sockaddr;
+#endif
socklen_t len = sizeof(sockaddr);
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
CAddress addr;
@@ -1390,7 +1394,7 @@ void ThreadOpenConnections2(void* parg)
CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
// 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;
nTries++;
@@ -1620,6 +1624,7 @@ void ThreadMessageHandler2(void* parg)
bool BindListenPort(string& strError)
{
+ unsigned short nPort = GetListenPort();
strError = "";
int nOne = 1;
@@ -1636,7 +1641,12 @@ bool BindListenPort(string& strError)
#endif
// 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)
{
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,
// 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));
sockaddr.sin_family = AF_INET;
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)
{
int nErr = WSAGetLastError();
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
- 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());
return false;
}
- printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
+ printf("Bound to port %d\n", (int)nPort);
// Listen for incoming connections
if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
@@ -1727,28 +1751,22 @@ void static Discover()
if ((ifa->ifa_flags & IFF_UP) == 0) continue;
if (strcmp(ifa->ifa_name, "lo") == 0) continue;
if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
- char pszIP[100];
if (ifa->ifa_addr->sa_family == AF_INET)
{
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);
- 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)
{
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);
- AddLocal(addr, LOCAL_IF);
-#endif
+ if (AddLocal(addr, LOCAL_IF))
+ printf("ipv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
}
+#endif
}
freeifaddrs(myaddrs);
}
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 48709dc5c6..a22d42a967 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -305,7 +305,37 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
{
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)
return false;
#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));
#endif
- struct sockaddr_in sockaddr;
- if (!addrConnect.GetSockAddr(&sockaddr))
- {
- closesocket(hSocket);
- return false;
- }
-
#ifdef WIN32
u_long fNonblock = 1;
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
@@ -332,7 +355,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
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
if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
@@ -531,6 +554,11 @@ bool CNetAddr::IsIPv4() const
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
}
+bool CNetAddr::IsIPv6() const
+{
+ return (!IsIPv4());
+}
+
bool CNetAddr::IsRFC1918() const
{
return IsIPv4() && (
@@ -919,12 +947,16 @@ std::vector<unsigned char> CService::GetKey() const
std::string CService::ToStringPort() const
{
- return strprintf(":%i", port);
+ return strprintf("%i", port);
}
std::string CService::ToStringIPPort() const
{
- return ToStringIP() + ToStringPort();
+ if (IsIPv4()) {
+ return ToStringIP() + ":" + ToStringPort();
+ } else {
+ return "[" + ToStringIP() + "]:" + ToStringPort();
+ }
}
std::string CService::ToString() const
diff --git a/src/netbase.h b/src/netbase.h
index e5c466e4f0..acbcc36d18 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -31,6 +31,7 @@ class CNetAddr
void Init();
void SetIP(const CNetAddr& ip);
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 IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)