1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
10 #include <sys/fcntl.h>
14 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
19 typedef std::pair
<CService
, int> proxyType
;
20 static proxyType proxyInfo
[NET_MAX
];
21 static proxyType nameproxyInfo
;
22 int nConnectTimeout
= 5000;
23 bool fNameLookup
= false;
25 static const unsigned char pchIPv4
[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
27 enum Network
ParseNetwork(std::string net
) {
29 if (net
== "ipv4") return NET_IPV4
;
30 if (net
== "ipv6") return NET_IPV6
;
31 if (net
== "tor") return NET_TOR
;
32 if (net
== "i2p") return NET_I2P
;
33 return NET_UNROUTABLE
;
36 void SplitHostPort(std::string in
, int &portOut
, std::string
&hostOut
) {
37 size_t colon
= in
.find_last_of(':');
38 // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
39 bool fHaveColon
= colon
!= in
.npos
;
40 bool fBracketed
= fHaveColon
&& (in
[0]=='[' && in
[colon
-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
41 bool fMultiColon
= fHaveColon
&& (in
.find_last_of(':',colon
-1) != in
.npos
);
42 if (fHaveColon
&& (colon
==0 || fBracketed
|| !fMultiColon
)) {
44 int n
= strtol(in
.c_str() + colon
+ 1, &endp
, 10);
45 if (endp
&& *endp
== 0 && n
>= 0) {
46 in
= in
.substr(0, colon
);
47 if (n
> 0 && n
< 0x10000)
51 if (in
.size()>0 && in
[0] == '[' && in
[in
.size()-1] == ']')
52 hostOut
= in
.substr(1, in
.size()-2);
57 bool static LookupIntern(const char *pszName
, std::vector
<CNetAddr
>& vIP
, unsigned int nMaxSolutions
, bool fAllowLookup
)
63 if (addr
.SetSpecial(std::string(pszName
))) {
69 struct addrinfo aiHint
;
70 memset(&aiHint
, 0, sizeof(struct addrinfo
));
72 aiHint
.ai_socktype
= SOCK_STREAM
;
73 aiHint
.ai_protocol
= IPPROTO_TCP
;
76 aiHint
.ai_family
= AF_UNSPEC
;
78 aiHint
.ai_family
= AF_INET
;
80 aiHint
.ai_flags
= fAllowLookup
? 0 : AI_NUMERICHOST
;
83 aiHint
.ai_family
= AF_UNSPEC
;
85 aiHint
.ai_family
= AF_INET
;
87 aiHint
.ai_flags
= fAllowLookup
? AI_ADDRCONFIG
: AI_NUMERICHOST
;
89 struct addrinfo
*aiRes
= NULL
;
90 int nErr
= getaddrinfo(pszName
, NULL
, &aiHint
, &aiRes
);
94 struct addrinfo
*aiTrav
= aiRes
;
95 while (aiTrav
!= NULL
&& (nMaxSolutions
== 0 || vIP
.size() < nMaxSolutions
))
97 if (aiTrav
->ai_family
== AF_INET
)
99 assert(aiTrav
->ai_addrlen
>= sizeof(sockaddr_in
));
100 vIP
.push_back(CNetAddr(((struct sockaddr_in
*)(aiTrav
->ai_addr
))->sin_addr
));
104 if (aiTrav
->ai_family
== AF_INET6
)
106 assert(aiTrav
->ai_addrlen
>= sizeof(sockaddr_in6
));
107 vIP
.push_back(CNetAddr(((struct sockaddr_in6
*)(aiTrav
->ai_addr
))->sin6_addr
));
111 aiTrav
= aiTrav
->ai_next
;
116 return (vIP
.size() > 0);
119 bool LookupHost(const char *pszName
, std::vector
<CNetAddr
>& vIP
, unsigned int nMaxSolutions
, bool fAllowLookup
)
125 strlcpy(psz
, pszName
, sizeof(psz
));
126 if (psz
[0] == '[' && psz
[strlen(psz
)-1] == ']')
129 psz
[strlen(psz
)-1] = 0;
132 return LookupIntern(pszHost
, vIP
, nMaxSolutions
, fAllowLookup
);
135 bool LookupHostNumeric(const char *pszName
, std::vector
<CNetAddr
>& vIP
, unsigned int nMaxSolutions
)
137 return LookupHost(pszName
, vIP
, nMaxSolutions
, false);
140 bool Lookup(const char *pszName
, std::vector
<CService
>& vAddr
, int portDefault
, bool fAllowLookup
, unsigned int nMaxSolutions
)
144 int port
= portDefault
;
145 std::string hostname
= "";
146 SplitHostPort(std::string(pszName
), port
, hostname
);
148 std::vector
<CNetAddr
> vIP
;
149 bool fRet
= LookupIntern(hostname
.c_str(), vIP
, nMaxSolutions
, fAllowLookup
);
152 vAddr
.resize(vIP
.size());
153 for (unsigned int i
= 0; i
< vIP
.size(); i
++)
154 vAddr
[i
] = CService(vIP
[i
], port
);
158 bool Lookup(const char *pszName
, CService
& addr
, int portDefault
, bool fAllowLookup
)
160 std::vector
<CService
> vService
;
161 bool fRet
= Lookup(pszName
, vService
, portDefault
, fAllowLookup
, 1);
168 bool LookupNumeric(const char *pszName
, CService
& addr
, int portDefault
)
170 return Lookup(pszName
, addr
, portDefault
, false);
173 bool static Socks4(const CService
&addrDest
, SOCKET
& hSocket
)
175 printf("SOCKS4 connecting %s\n", addrDest
.ToString().c_str());
176 if (!addrDest
.IsIPv4())
178 closesocket(hSocket
);
179 return error("Proxy destination is not IPv4");
181 char pszSocks4IP
[] = "\4\1\0\0\0\0\0\0user";
182 struct sockaddr_in addr
;
183 socklen_t len
= sizeof(addr
);
184 if (!addrDest
.GetSockAddr((struct sockaddr
*)&addr
, &len
) || addr
.sin_family
!= AF_INET
)
186 closesocket(hSocket
);
187 return error("Cannot get proxy destination address");
189 memcpy(pszSocks4IP
+ 2, &addr
.sin_port
, 2);
190 memcpy(pszSocks4IP
+ 4, &addr
.sin_addr
, 4);
191 char* pszSocks4
= pszSocks4IP
;
192 int nSize
= sizeof(pszSocks4IP
);
194 int ret
= send(hSocket
, pszSocks4
, nSize
, MSG_NOSIGNAL
);
197 closesocket(hSocket
);
198 return error("Error sending to proxy");
201 if (recv(hSocket
, pchRet
, 8, 0) != 8)
203 closesocket(hSocket
);
204 return error("Error reading proxy response");
206 if (pchRet
[1] != 0x5a)
208 closesocket(hSocket
);
209 if (pchRet
[1] != 0x5b)
210 printf("ERROR: Proxy returned error %d\n", pchRet
[1]);
213 printf("SOCKS4 connected %s\n", addrDest
.ToString().c_str());
217 bool static Socks5(string strDest
, int port
, SOCKET
& hSocket
)
219 printf("SOCKS5 connecting %s\n", strDest
.c_str());
220 if (strDest
.size() > 255)
222 closesocket(hSocket
);
223 return error("Hostname too long");
225 char pszSocks5Init
[] = "\5\1\0";
226 char *pszSocks5
= pszSocks5Init
;
227 ssize_t nSize
= sizeof(pszSocks5Init
) - 1;
229 ssize_t ret
= send(hSocket
, pszSocks5
, nSize
, MSG_NOSIGNAL
);
232 closesocket(hSocket
);
233 return error("Error sending to proxy");
236 if (recv(hSocket
, pchRet1
, 2, 0) != 2)
238 closesocket(hSocket
);
239 return error("Error reading proxy response");
241 if (pchRet1
[0] != 0x05 || pchRet1
[1] != 0x00)
243 closesocket(hSocket
);
244 return error("Proxy failed to initialize");
246 string
strSocks5("\5\1");
247 strSocks5
+= '\000'; strSocks5
+= '\003';
248 strSocks5
+= static_cast<char>(std::min((int)strDest
.size(), 255));
249 strSocks5
+= strDest
;
250 strSocks5
+= static_cast<char>((port
>> 8) & 0xFF);
251 strSocks5
+= static_cast<char>((port
>> 0) & 0xFF);
252 ret
= send(hSocket
, strSocks5
.c_str(), strSocks5
.size(), MSG_NOSIGNAL
);
253 if (ret
!= (ssize_t
)strSocks5
.size())
255 closesocket(hSocket
);
256 return error("Error sending to proxy");
259 if (recv(hSocket
, pchRet2
, 4, 0) != 4)
261 closesocket(hSocket
);
262 return error("Error reading proxy response");
264 if (pchRet2
[0] != 0x05)
266 closesocket(hSocket
);
267 return error("Proxy failed to accept request");
269 if (pchRet2
[1] != 0x00)
271 closesocket(hSocket
);
274 case 0x01: return error("Proxy error: general failure");
275 case 0x02: return error("Proxy error: connection not allowed");
276 case 0x03: return error("Proxy error: network unreachable");
277 case 0x04: return error("Proxy error: host unreachable");
278 case 0x05: return error("Proxy error: connection refused");
279 case 0x06: return error("Proxy error: TTL expired");
280 case 0x07: return error("Proxy error: protocol error");
281 case 0x08: return error("Proxy error: address type not supported");
282 default: return error("Proxy error: unknown");
285 if (pchRet2
[2] != 0x00)
287 closesocket(hSocket
);
288 return error("Error: malformed proxy response");
293 case 0x01: ret
= recv(hSocket
, pchRet3
, 4, 0) != 4; break;
294 case 0x04: ret
= recv(hSocket
, pchRet3
, 16, 0) != 16; break;
297 ret
= recv(hSocket
, pchRet3
, 1, 0) != 1;
299 return error("Error reading from proxy");
300 int nRecv
= pchRet3
[0];
301 ret
= recv(hSocket
, pchRet3
, nRecv
, 0) != nRecv
;
304 default: closesocket(hSocket
); return error("Error: malformed proxy response");
308 closesocket(hSocket
);
309 return error("Error reading from proxy");
311 if (recv(hSocket
, pchRet3
, 2, 0) != 2)
313 closesocket(hSocket
);
314 return error("Error reading from proxy");
316 printf("SOCKS5 connected %s\n", strDest
.c_str());
320 bool static ConnectSocketDirectly(const CService
&addrConnect
, SOCKET
& hSocketRet
, int nTimeout
)
322 hSocketRet
= INVALID_SOCKET
;
325 struct sockaddr_storage sockaddr
;
327 struct sockaddr sockaddr
;
329 socklen_t len
= sizeof(sockaddr
);
330 if (!addrConnect
.GetSockAddr((struct sockaddr
*)&sockaddr
, &len
)) {
331 printf("Cannot connect to %s: unsupported network\n", addrConnect
.ToString().c_str());
335 SOCKET hSocket
= socket(((struct sockaddr
*)&sockaddr
)->sa_family
, SOCK_STREAM
, IPPROTO_TCP
);
336 if (hSocket
== INVALID_SOCKET
)
340 setsockopt(hSocket
, SOL_SOCKET
, SO_NOSIGPIPE
, (void*)&set
, sizeof(int));
344 u_long fNonblock
= 1;
345 if (ioctlsocket(hSocket
, FIONBIO
, &fNonblock
) == SOCKET_ERROR
)
347 int fFlags
= fcntl(hSocket
, F_GETFL
, 0);
348 if (fcntl(hSocket
, F_SETFL
, fFlags
| O_NONBLOCK
) == -1)
351 closesocket(hSocket
);
355 if (connect(hSocket
, (struct sockaddr
*)&sockaddr
, len
) == SOCKET_ERROR
)
357 // WSAEINVAL is here because some legacy version of winsock uses it
358 if (WSAGetLastError() == WSAEINPROGRESS
|| WSAGetLastError() == WSAEWOULDBLOCK
|| WSAGetLastError() == WSAEINVAL
)
360 struct timeval timeout
;
361 timeout
.tv_sec
= nTimeout
/ 1000;
362 timeout
.tv_usec
= (nTimeout
% 1000) * 1000;
366 FD_SET(hSocket
, &fdset
);
367 int nRet
= select(hSocket
+ 1, NULL
, &fdset
, NULL
, &timeout
);
370 printf("connection timeout\n");
371 closesocket(hSocket
);
374 if (nRet
== SOCKET_ERROR
)
376 printf("select() for connection failed: %i\n",WSAGetLastError());
377 closesocket(hSocket
);
380 socklen_t nRetSize
= sizeof(nRet
);
382 if (getsockopt(hSocket
, SOL_SOCKET
, SO_ERROR
, (char*)(&nRet
), &nRetSize
) == SOCKET_ERROR
)
384 if (getsockopt(hSocket
, SOL_SOCKET
, SO_ERROR
, &nRet
, &nRetSize
) == SOCKET_ERROR
)
387 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
388 closesocket(hSocket
);
393 printf("connect() failed after select(): %s\n",strerror(nRet
));
394 closesocket(hSocket
);
399 else if (WSAGetLastError() != WSAEISCONN
)
404 printf("connect() failed: %i\n",WSAGetLastError());
405 closesocket(hSocket
);
410 // this isn't even strictly necessary
411 // CNode::ConnectNode immediately turns the socket back to non-blocking
412 // but we'll turn it back to blocking just in case
415 if (ioctlsocket(hSocket
, FIONBIO
, &fNonblock
) == SOCKET_ERROR
)
417 fFlags
= fcntl(hSocket
, F_GETFL
, 0);
418 if (fcntl(hSocket
, F_SETFL
, fFlags
& !O_NONBLOCK
) == SOCKET_ERROR
)
421 closesocket(hSocket
);
425 hSocketRet
= hSocket
;
429 bool SetProxy(enum Network net
, CService addrProxy
, int nSocksVersion
) {
430 assert(net
>= 0 && net
< NET_MAX
);
431 if (nSocksVersion
!= 0 && nSocksVersion
!= 4 && nSocksVersion
!= 5)
433 if (nSocksVersion
!= 0 && !addrProxy
.IsValid())
435 proxyInfo
[net
] = std::make_pair(addrProxy
, nSocksVersion
);
439 bool GetProxy(enum Network net
, CService
&addrProxy
) {
440 assert(net
>= 0 && net
< NET_MAX
);
441 if (!proxyInfo
[net
].second
)
443 addrProxy
= proxyInfo
[net
].first
;
447 bool SetNameProxy(CService addrProxy
, int nSocksVersion
) {
448 if (nSocksVersion
!= 0 && nSocksVersion
!= 5)
450 if (nSocksVersion
!= 0 && !addrProxy
.IsValid())
452 nameproxyInfo
= std::make_pair(addrProxy
, nSocksVersion
);
456 bool GetNameProxy() {
457 return nameproxyInfo
.second
!= 0;
460 bool IsProxy(const CNetAddr
&addr
) {
461 for (int i
=0; i
<NET_MAX
; i
++) {
462 if (proxyInfo
[i
].second
&& (addr
== (CNetAddr
)proxyInfo
[i
].first
))
468 bool ConnectSocket(const CService
&addrDest
, SOCKET
& hSocketRet
, int nTimeout
)
470 const proxyType
&proxy
= proxyInfo
[addrDest
.GetNetwork()];
474 return ConnectSocketDirectly(addrDest
, hSocketRet
, nTimeout
);
476 SOCKET hSocket
= INVALID_SOCKET
;
478 // first connect to proxy server
479 if (!ConnectSocketDirectly(proxy
.first
, hSocket
, nTimeout
))
482 // do socks negotiation
483 switch (proxy
.second
) {
485 if (!Socks4(addrDest
, hSocket
))
489 if (!Socks5(addrDest
.ToStringIP(), addrDest
.GetPort(), hSocket
))
496 hSocketRet
= hSocket
;
500 bool ConnectSocketByName(CService
&addr
, SOCKET
& hSocketRet
, const char *pszDest
, int portDefault
, int nTimeout
)
503 int port
= portDefault
;
504 SplitHostPort(string(pszDest
), port
, strDest
);
506 SOCKET hSocket
= INVALID_SOCKET
;
507 CService
addrResolved(CNetAddr(strDest
, fNameLookup
&& !nameproxyInfo
.second
), port
);
508 if (addrResolved
.IsValid()) {
510 return ConnectSocket(addr
, hSocketRet
, nTimeout
);
512 addr
= CService("0.0.0.0:0");
513 if (!nameproxyInfo
.second
)
515 if (!ConnectSocketDirectly(nameproxyInfo
.first
, hSocket
, nTimeout
))
518 switch(nameproxyInfo
.second
)
521 case 4: return false;
523 if (!Socks5(strDest
, port
, hSocket
))
528 hSocketRet
= hSocket
;
532 void CNetAddr::Init()
537 void CNetAddr::SetIP(const CNetAddr
& ipIn
)
539 memcpy(ip
, ipIn
.ip
, sizeof(ip
));
542 static const unsigned char pchOnionCat
[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
543 static const unsigned char pchGarliCat
[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5};
545 bool CNetAddr::SetSpecial(const std::string
&strName
)
547 if (strName
.size()>6 && strName
.substr(strName
.size() - 6, 6) == ".onion") {
548 std::vector
<unsigned char> vchAddr
= DecodeBase32(strName
.substr(0, strName
.size() - 6).c_str());
549 if (vchAddr
.size() != 16-sizeof(pchOnionCat
))
551 memcpy(ip
, pchOnionCat
, sizeof(pchOnionCat
));
552 for (unsigned int i
=0; i
<16-sizeof(pchOnionCat
); i
++)
553 ip
[i
+ sizeof(pchOnionCat
)] = vchAddr
[i
];
556 if (strName
.size()>11 && strName
.substr(strName
.size() - 11, 11) == ".oc.b32.i2p") {
557 std::vector
<unsigned char> vchAddr
= DecodeBase32(strName
.substr(0, strName
.size() - 11).c_str());
558 if (vchAddr
.size() != 16-sizeof(pchGarliCat
))
560 memcpy(ip
, pchOnionCat
, sizeof(pchGarliCat
));
561 for (unsigned int i
=0; i
<16-sizeof(pchGarliCat
); i
++)
562 ip
[i
+ sizeof(pchGarliCat
)] = vchAddr
[i
];
573 CNetAddr::CNetAddr(const struct in_addr
& ipv4Addr
)
575 memcpy(ip
, pchIPv4
, 12);
576 memcpy(ip
+12, &ipv4Addr
, 4);
580 CNetAddr::CNetAddr(const struct in6_addr
& ipv6Addr
)
582 memcpy(ip
, &ipv6Addr
, 16);
586 CNetAddr::CNetAddr(const char *pszIp
, bool fAllowLookup
)
589 std::vector
<CNetAddr
> vIP
;
590 if (LookupHost(pszIp
, vIP
, 1, fAllowLookup
))
594 CNetAddr::CNetAddr(const std::string
&strIp
, bool fAllowLookup
)
597 std::vector
<CNetAddr
> vIP
;
598 if (LookupHost(strIp
.c_str(), vIP
, 1, fAllowLookup
))
602 int CNetAddr::GetByte(int n
) const
607 bool CNetAddr::IsIPv4() const
609 return (memcmp(ip
, pchIPv4
, sizeof(pchIPv4
)) == 0);
612 bool CNetAddr::IsIPv6() const
614 return (!IsIPv4() && !IsTor() && !IsI2P());
617 bool CNetAddr::IsRFC1918() const
621 (GetByte(3) == 192 && GetByte(2) == 168) ||
622 (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
625 bool CNetAddr::IsRFC3927() const
627 return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
630 bool CNetAddr::IsRFC3849() const
632 return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
635 bool CNetAddr::IsRFC3964() const
637 return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
640 bool CNetAddr::IsRFC6052() const
642 static const unsigned char pchRFC6052
[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0};
643 return (memcmp(ip
, pchRFC6052
, sizeof(pchRFC6052
)) == 0);
646 bool CNetAddr::IsRFC4380() const
648 return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
651 bool CNetAddr::IsRFC4862() const
653 static const unsigned char pchRFC4862
[] = {0xFE,0x80,0,0,0,0,0,0};
654 return (memcmp(ip
, pchRFC4862
, sizeof(pchRFC4862
)) == 0);
657 bool CNetAddr::IsRFC4193() const
659 return ((GetByte(15) & 0xFE) == 0xFC);
662 bool CNetAddr::IsRFC6145() const
664 static const unsigned char pchRFC6145
[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0};
665 return (memcmp(ip
, pchRFC6145
, sizeof(pchRFC6145
)) == 0);
668 bool CNetAddr::IsRFC4843() const
670 return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
673 bool CNetAddr::IsTor() const
675 return (memcmp(ip
, pchOnionCat
, sizeof(pchOnionCat
)) == 0);
678 bool CNetAddr::IsI2P() const
680 return (memcmp(ip
, pchGarliCat
, sizeof(pchGarliCat
)) == 0);
683 bool CNetAddr::IsLocal() const
686 if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
689 // IPv6 loopback (::1/128)
690 static const unsigned char pchLocal
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
691 if (memcmp(ip
, pchLocal
, 16) == 0)
697 bool CNetAddr::IsMulticast() const
699 return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
700 || (GetByte(15) == 0xFF);
703 bool CNetAddr::IsValid() const
705 // Clean up 3-byte shifted addresses caused by garbage in size field
706 // of addr messages from versions before 0.2.9 checksum.
707 // Two consecutive addr messages look like this:
708 // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
709 // so if the first length field is garbled, it reads the second batch
710 // of addr misaligned by 3 bytes.
711 if (memcmp(ip
, pchIPv4
+3, sizeof(pchIPv4
)-3) == 0)
714 // unspecified IPv6 address (::/128)
715 unsigned char ipNone
[16] = {};
716 if (memcmp(ip
, ipNone
, 16) == 0)
719 // documentation IPv6 address
726 uint32_t ipNone
= INADDR_NONE
;
727 if (memcmp(ip
+12, &ipNone
, 4) == 0)
732 if (memcmp(ip
+12, &ipNone
, 4) == 0)
739 bool CNetAddr::IsRoutable() const
741 return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || (IsRFC4193() && !IsTor() && !IsI2P()) || IsRFC4843() || IsLocal());
744 enum Network
CNetAddr::GetNetwork() const
747 return NET_UNROUTABLE
;
761 std::string
CNetAddr::ToStringIP() const
764 return EncodeBase32(&ip
[6], 10) + ".onion";
766 return EncodeBase32(&ip
[6], 10) + ".oc.b32.i2p";
767 CService
serv(*this, 0);
769 struct sockaddr_storage sockaddr
;
771 struct sockaddr sockaddr
;
773 socklen_t socklen
= sizeof(sockaddr
);
774 if (serv
.GetSockAddr((struct sockaddr
*)&sockaddr
, &socklen
)) {
775 char name
[1025] = "";
776 if (!getnameinfo((const struct sockaddr
*)&sockaddr
, socklen
, name
, sizeof(name
), NULL
, 0, NI_NUMERICHOST
))
777 return std::string(name
);
780 return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
782 return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
783 GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12),
784 GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8),
785 GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4),
786 GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0));
789 std::string
CNetAddr::ToString() const
794 bool operator==(const CNetAddr
& a
, const CNetAddr
& b
)
796 return (memcmp(a
.ip
, b
.ip
, 16) == 0);
799 bool operator!=(const CNetAddr
& a
, const CNetAddr
& b
)
801 return (memcmp(a
.ip
, b
.ip
, 16) != 0);
804 bool operator<(const CNetAddr
& a
, const CNetAddr
& b
)
806 return (memcmp(a
.ip
, b
.ip
, 16) < 0);
809 bool CNetAddr::GetInAddr(struct in_addr
* pipv4Addr
) const
813 memcpy(pipv4Addr
, ip
+12, 4);
818 bool CNetAddr::GetIn6Addr(struct in6_addr
* pipv6Addr
) const
820 memcpy(pipv6Addr
, ip
, 16);
825 // get canonical identifier of an address' group
826 // no two connections will be attempted to addresses with the same group
827 std::vector
<unsigned char> CNetAddr::GetGroup() const
829 std::vector
<unsigned char> vchRet
;
830 int nClass
= NET_IPV6
;
834 // all local addresses belong to the same group
841 // all unroutable addresses belong to the same group
844 nClass
= NET_UNROUTABLE
;
847 // for IPv4 addresses, '1' + the 16 higher-order bits of the IP
848 // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
849 else if (IsIPv4() || IsRFC6145() || IsRFC6052())
854 // for 6to4 tunneled addresses, use the encapsulated IPv4 address
855 else if (IsRFC3964())
860 // for Teredo-tunneled IPv6 addresses, use the encapsulated IPv4 address
861 else if (IsRFC4380())
863 vchRet
.push_back(NET_IPV4
);
864 vchRet
.push_back(GetByte(3) ^ 0xFF);
865 vchRet
.push_back(GetByte(2) ^ 0xFF);
880 // for he.net, use /36 groups
881 else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
883 // for the rest of the IPv6 network, use /32 groups
887 vchRet
.push_back(nClass
);
890 vchRet
.push_back(GetByte(15 - nStartByte
));
895 vchRet
.push_back(GetByte(15 - nStartByte
) | ((1 << nBits
) - 1));
900 uint64
CNetAddr::GetHash() const
902 uint256 hash
= Hash(&ip
[0], &ip
[16]);
904 memcpy(&nRet
, &hash
, sizeof(nRet
));
908 void CNetAddr::print() const
910 printf("CNetAddr(%s)\n", ToString().c_str());
913 // private extensions to enum Network, only returned by GetExtNetwork,
914 // and only used in GetReachabilityFrom
915 static const int NET_UNKNOWN
= NET_MAX
+ 0;
916 static const int NET_TEREDO
= NET_MAX
+ 1;
917 int static GetExtNetwork(const CNetAddr
*addr
)
921 if (addr
->IsRFC4380())
923 return addr
->GetNetwork();
926 /** Calculates a metric for how reachable (*this) is from a given partner */
927 int CNetAddr::GetReachabilityFrom(const CNetAddr
*paddrPartner
) const
940 return REACH_UNREACHABLE
;
942 int ourNet
= GetExtNetwork(this);
943 int theirNet
= GetExtNetwork(paddrPartner
);
944 bool fTunnel
= IsRFC3964() || IsRFC6052() || IsRFC6145();
949 default: return REACH_DEFAULT
;
950 case NET_IPV4
: return REACH_IPV4
;
954 default: return REACH_DEFAULT
;
955 case NET_TEREDO
: return REACH_TEREDO
;
956 case NET_IPV4
: return REACH_IPV4
;
957 case NET_IPV6
: return fTunnel
? REACH_IPV6_WEAK
: REACH_IPV6_STRONG
; // only prefer giving our IPv6 address if it's not tunneled
961 default: return REACH_DEFAULT
;
962 case NET_IPV4
: return REACH_IPV4
; // Tor users can connect to IPv4 as well
963 case NET_TOR
: return REACH_PRIVATE
;
967 default: return REACH_DEFAULT
;
968 case NET_I2P
: return REACH_PRIVATE
;
972 default: return REACH_DEFAULT
;
973 case NET_TEREDO
: return REACH_TEREDO
;
974 case NET_IPV6
: return REACH_IPV6_WEAK
;
975 case NET_IPV4
: return REACH_IPV4
;
981 default: return REACH_DEFAULT
;
982 case NET_TEREDO
: return REACH_TEREDO
;
983 case NET_IPV6
: return REACH_IPV6_WEAK
;
984 case NET_IPV4
: return REACH_IPV4
;
985 case NET_I2P
: return REACH_PRIVATE
; // assume connections from unroutable addresses are
986 case NET_TOR
: return REACH_PRIVATE
; // either from Tor/I2P, or don't care about our address
991 void CService::Init()
1001 CService::CService(const CNetAddr
& cip
, unsigned short portIn
) : CNetAddr(cip
), port(portIn
)
1005 CService::CService(const struct in_addr
& ipv4Addr
, unsigned short portIn
) : CNetAddr(ipv4Addr
), port(portIn
)
1010 CService::CService(const struct in6_addr
& ipv6Addr
, unsigned short portIn
) : CNetAddr(ipv6Addr
), port(portIn
)
1015 CService::CService(const struct sockaddr_in
& addr
) : CNetAddr(addr
.sin_addr
), port(ntohs(addr
.sin_port
))
1017 assert(addr
.sin_family
== AF_INET
);
1021 CService::CService(const struct sockaddr_in6
&addr
) : CNetAddr(addr
.sin6_addr
), port(ntohs(addr
.sin6_port
))
1023 assert(addr
.sin6_family
== AF_INET6
);
1027 bool CService::SetSockAddr(const struct sockaddr
*paddr
)
1029 switch (paddr
->sa_family
) {
1031 *this = CService(*(const struct sockaddr_in
*)paddr
);
1035 *this = CService(*(const struct sockaddr_in6
*)paddr
);
1043 CService::CService(const char *pszIpPort
, bool fAllowLookup
)
1047 if (Lookup(pszIpPort
, ip
, 0, fAllowLookup
))
1051 CService::CService(const char *pszIpPort
, int portDefault
, bool fAllowLookup
)
1055 if (Lookup(pszIpPort
, ip
, portDefault
, fAllowLookup
))
1059 CService::CService(const std::string
&strIpPort
, bool fAllowLookup
)
1063 if (Lookup(strIpPort
.c_str(), ip
, 0, fAllowLookup
))
1067 CService::CService(const std::string
&strIpPort
, int portDefault
, bool fAllowLookup
)
1071 if (Lookup(strIpPort
.c_str(), ip
, portDefault
, fAllowLookup
))
1075 unsigned short CService::GetPort() const
1080 bool operator==(const CService
& a
, const CService
& b
)
1082 return (CNetAddr
)a
== (CNetAddr
)b
&& a
.port
== b
.port
;
1085 bool operator!=(const CService
& a
, const CService
& b
)
1087 return (CNetAddr
)a
!= (CNetAddr
)b
|| a
.port
!= b
.port
;
1090 bool operator<(const CService
& a
, const CService
& b
)
1092 return (CNetAddr
)a
< (CNetAddr
)b
|| ((CNetAddr
)a
== (CNetAddr
)b
&& a
.port
< b
.port
);
1095 bool CService::GetSockAddr(struct sockaddr
* paddr
, socklen_t
*addrlen
) const
1098 if (*addrlen
< (socklen_t
)sizeof(struct sockaddr_in
))
1100 *addrlen
= sizeof(struct sockaddr_in
);
1101 struct sockaddr_in
*paddrin
= (struct sockaddr_in
*)paddr
;
1102 memset(paddrin
, 0, *addrlen
);
1103 if (!GetInAddr(&paddrin
->sin_addr
))
1105 paddrin
->sin_family
= AF_INET
;
1106 paddrin
->sin_port
= htons(port
);
1111 if (*addrlen
< (socklen_t
)sizeof(struct sockaddr_in6
))
1113 *addrlen
= sizeof(struct sockaddr_in6
);
1114 struct sockaddr_in6
*paddrin6
= (struct sockaddr_in6
*)paddr
;
1115 memset(paddrin6
, 0, *addrlen
);
1116 if (!GetIn6Addr(&paddrin6
->sin6_addr
))
1118 paddrin6
->sin6_family
= AF_INET6
;
1119 paddrin6
->sin6_port
= htons(port
);
1126 std::vector
<unsigned char> CService::GetKey() const
1128 std::vector
<unsigned char> vKey
;
1130 memcpy(&vKey
[0], ip
, 16);
1131 vKey
[16] = port
/ 0x100;
1132 vKey
[17] = port
& 0x0FF;
1136 std::string
CService::ToStringPort() const
1138 return strprintf("%i", port
);
1141 std::string
CService::ToStringIPPort() const
1143 if (IsIPv4() || IsTor() || IsI2P()) {
1144 return ToStringIP() + ":" + ToStringPort();
1146 return "[" + ToStringIP() + "]:" + ToStringPort();
1150 std::string
CService::ToString() const
1152 return ToStringIPPort();
1155 void CService::print() const
1157 printf("CService(%s)\n", ToString().c_str());
1160 void CService::SetPort(unsigned short portIn
)