]> Git Repo - VerusCoin.git/blame - src/netbase.cpp
Merge pull request #3601
[VerusCoin.git] / src / netbase.cpp
CommitLineData
67a42f92 1// Copyright (c) 2009-2010 Satoshi Nakamoto
db0e8ccd 2// Copyright (c) 2009-2013 The Bitcoin developers
67a42f92 3// Distributed under the MIT/X11 software license, see the accompanying
3a25a2b9 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
67a42f92
PW
5
6#include "netbase.h"
51ed9ec9 7
0fb9073e 8#include "hash.h"
51ed9ec9
BD
9#include "sync.h"
10#include "uint256.h"
11#include "util.h"
12
67a42f92 13#ifndef WIN32
98148a71 14#include <fcntl.h>
67a42f92
PW
15#endif
16
ea933b03 17#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
6032e4f4 18#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
67a42f92 19
51ed9ec9 20#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
35b8af92
CF
21#define MSG_NOSIGNAL 0
22#endif
23
67a42f92
PW
24using namespace std;
25
26// Settings
587f929c
PW
27static proxyType proxyInfo[NET_MAX];
28static proxyType nameproxyInfo;
81bbef26 29static CCriticalSection cs_proxyInfos;
67a42f92 30int nConnectTimeout = 5000;
587f929c 31bool fNameLookup = false;
67a42f92
PW
32
33static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
34
090e5b40 35enum Network ParseNetwork(std::string net) {
ea933b03 36 boost::to_lower(net);
090e5b40
PW
37 if (net == "ipv4") return NET_IPV4;
38 if (net == "ipv6") return NET_IPV6;
39 if (net == "tor") return NET_TOR;
090e5b40
PW
40 return NET_UNROUTABLE;
41}
42
1e8aeae1
PW
43void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
44 size_t colon = in.find_last_of(':');
45 // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
46 bool fHaveColon = colon != in.npos;
47 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
48 bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
49 if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
50 char *endp = NULL;
51 int n = strtol(in.c_str() + colon + 1, &endp, 10);
52 if (endp && *endp == 0 && n >= 0) {
53 in = in.substr(0, colon);
54 if (n > 0 && n < 0x10000)
55 portOut = n;
56 }
57 }
58 if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
59 hostOut = in.substr(1, in.size()-2);
60 else
61 hostOut = in;
62}
63
3a78f82a 64bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
67a42f92
PW
65{
66 vIP.clear();
70f7f003
PW
67
68 {
69 CNetAddr addr;
70 if (addr.SetSpecial(std::string(pszName))) {
71 vIP.push_back(addr);
72 return true;
73 }
74 }
75
a1de57a0
GA
76 struct addrinfo aiHint;
77 memset(&aiHint, 0, sizeof(struct addrinfo));
78
67a42f92
PW
79 aiHint.ai_socktype = SOCK_STREAM;
80 aiHint.ai_protocol = IPPROTO_TCP;
fe9e88cb 81#ifdef USE_IPV6
67a42f92 82 aiHint.ai_family = AF_UNSPEC;
fe9e88cb 83#else
67a42f92 84 aiHint.ai_family = AF_INET;
fe9e88cb
WL
85#endif
86#ifdef WIN32
4c6b210a 87 aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
67a42f92 88#else
4c6b210a 89 aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
67a42f92
PW
90#endif
91 struct addrinfo *aiRes = NULL;
92 int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
93 if (nErr)
94 return false;
95
96 struct addrinfo *aiTrav = aiRes;
97 while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
98 {
99 if (aiTrav->ai_family == AF_INET)
100 {
101 assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
102 vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr));
103 }
104
105#ifdef USE_IPV6
106 if (aiTrav->ai_family == AF_INET6)
107 {
108 assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
109 vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr));
110 }
111#endif
112
113 aiTrav = aiTrav->ai_next;
114 }
115
116 freeaddrinfo(aiRes);
117
118 return (vIP.size() > 0);
119}
120
3a78f82a 121bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
67a42f92 122{
fe9e88cb
WL
123 std::string strHost(pszName);
124 if (strHost.empty())
67a42f92 125 return false;
fe9e88cb 126 if (boost::algorithm::starts_with(strHost, "[") && boost::algorithm::ends_with(strHost, "]"))
67a42f92 127 {
fe9e88cb 128 strHost = strHost.substr(1, strHost.size() - 2);
67a42f92
PW
129 }
130
6032e4f4 131 return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
67a42f92
PW
132}
133
3a78f82a 134bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions)
67a42f92
PW
135{
136 return LookupHost(pszName, vIP, nMaxSolutions, false);
137}
138
3a78f82a 139bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
67a42f92
PW
140{
141 if (pszName[0] == 0)
142 return false;
143 int port = portDefault;
1e8aeae1
PW
144 std::string hostname = "";
145 SplitHostPort(std::string(pszName), port, hostname);
67a42f92
PW
146
147 std::vector<CNetAddr> vIP;
1e8aeae1 148 bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
b24e6e4d
MC
149 if (!fRet)
150 return false;
151 vAddr.resize(vIP.size());
c376ac35 152 for (unsigned int i = 0; i < vIP.size(); i++)
b24e6e4d
MC
153 vAddr[i] = CService(vIP[i], port);
154 return true;
155}
156
157bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
158{
159 std::vector<CService> vService;
160 bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
67a42f92
PW
161 if (!fRet)
162 return false;
b24e6e4d 163 addr = vService[0];
67a42f92
PW
164 return true;
165}
166
167bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
168{
169 return Lookup(pszName, addr, portDefault, false);
170}
171
60a87bce
PW
172bool static Socks4(const CService &addrDest, SOCKET& hSocket)
173{
7d9d134b 174 LogPrintf("SOCKS4 connecting %s\n", addrDest.ToString());
60a87bce
PW
175 if (!addrDest.IsIPv4())
176 {
177 closesocket(hSocket);
178 return error("Proxy destination is not IPv4");
179 }
180 char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
181 struct sockaddr_in addr;
8f10a288
PW
182 socklen_t len = sizeof(addr);
183 if (!addrDest.GetSockAddr((struct sockaddr*)&addr, &len) || addr.sin_family != AF_INET)
184 {
185 closesocket(hSocket);
186 return error("Cannot get proxy destination address");
187 }
60a87bce
PW
188 memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
189 memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
190 char* pszSocks4 = pszSocks4IP;
191 int nSize = sizeof(pszSocks4IP);
192
193 int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
194 if (ret != nSize)
195 {
196 closesocket(hSocket);
197 return error("Error sending to proxy");
198 }
199 char pchRet[8];
200 if (recv(hSocket, pchRet, 8, 0) != 8)
201 {
202 closesocket(hSocket);
203 return error("Error reading proxy response");
204 }
205 if (pchRet[1] != 0x5a)
206 {
207 closesocket(hSocket);
208 if (pchRet[1] != 0x5b)
881a85a2 209 LogPrintf("ERROR: Proxy returned error %d\n", pchRet[1]);
60a87bce
PW
210 return false;
211 }
7d9d134b 212 LogPrintf("SOCKS4 connected %s\n", addrDest.ToString());
60a87bce
PW
213 return true;
214}
215
a012e2db 216bool static Socks5(string strDest, int port, SOCKET& hSocket)
60a87bce 217{
7d9d134b 218 LogPrintf("SOCKS5 connecting %s\n", strDest);
a012e2db
PW
219 if (strDest.size() > 255)
220 {
221 closesocket(hSocket);
222 return error("Hostname too long");
223 }
60a87bce 224 char pszSocks5Init[] = "\5\1\0";
b19811d5 225 ssize_t nSize = sizeof(pszSocks5Init) - 1;
60a87bce 226
fe9e88cb 227 ssize_t ret = send(hSocket, pszSocks5Init, nSize, MSG_NOSIGNAL);
60a87bce
PW
228 if (ret != nSize)
229 {
230 closesocket(hSocket);
231 return error("Error sending to proxy");
232 }
233 char pchRet1[2];
234 if (recv(hSocket, pchRet1, 2, 0) != 2)
235 {
236 closesocket(hSocket);
237 return error("Error reading proxy response");
238 }
239 if (pchRet1[0] != 0x05 || pchRet1[1] != 0x00)
240 {
241 closesocket(hSocket);
242 return error("Proxy failed to initialize");
243 }
933f2715
PW
244 string strSocks5("\5\1");
245 strSocks5 += '\000'; strSocks5 += '\003';
933f2715 246 strSocks5 += static_cast<char>(std::min((int)strDest.size(), 255));
ea0796bd 247 strSocks5 += strDest;
a012e2db
PW
248 strSocks5 += static_cast<char>((port >> 8) & 0xFF);
249 strSocks5 += static_cast<char>((port >> 0) & 0xFF);
933f2715 250 ret = send(hSocket, strSocks5.c_str(), strSocks5.size(), MSG_NOSIGNAL);
f621326c 251 if (ret != (ssize_t)strSocks5.size())
60a87bce
PW
252 {
253 closesocket(hSocket);
254 return error("Error sending to proxy");
255 }
256 char pchRet2[4];
257 if (recv(hSocket, pchRet2, 4, 0) != 4)
258 {
259 closesocket(hSocket);
260 return error("Error reading proxy response");
261 }
262 if (pchRet2[0] != 0x05)
263 {
264 closesocket(hSocket);
265 return error("Proxy failed to accept request");
266 }
267 if (pchRet2[1] != 0x00)
268 {
269 closesocket(hSocket);
270 switch (pchRet2[1])
271 {
272 case 0x01: return error("Proxy error: general failure");
273 case 0x02: return error("Proxy error: connection not allowed");
274 case 0x03: return error("Proxy error: network unreachable");
275 case 0x04: return error("Proxy error: host unreachable");
276 case 0x05: return error("Proxy error: connection refused");
277 case 0x06: return error("Proxy error: TTL expired");
278 case 0x07: return error("Proxy error: protocol error");
279 case 0x08: return error("Proxy error: address type not supported");
280 default: return error("Proxy error: unknown");
281 }
282 }
283 if (pchRet2[2] != 0x00)
284 {
285 closesocket(hSocket);
286 return error("Error: malformed proxy response");
287 }
288 char pchRet3[256];
289 switch (pchRet2[3])
290 {
291 case 0x01: ret = recv(hSocket, pchRet3, 4, 0) != 4; break;
292 case 0x04: ret = recv(hSocket, pchRet3, 16, 0) != 16; break;
293 case 0x03:
294 {
295 ret = recv(hSocket, pchRet3, 1, 0) != 1;
296 if (ret)
297 return error("Error reading from proxy");
298 int nRecv = pchRet3[0];
299 ret = recv(hSocket, pchRet3, nRecv, 0) != nRecv;
300 break;
301 }
302 default: closesocket(hSocket); return error("Error: malformed proxy response");
303 }
304 if (ret)
305 {
306 closesocket(hSocket);
307 return error("Error reading from proxy");
308 }
309 if (recv(hSocket, pchRet3, 2, 0) != 2)
310 {
311 closesocket(hSocket);
312 return error("Error reading from proxy");
313 }
7d9d134b 314 LogPrintf("SOCKS5 connected %s\n", strDest);
60a87bce
PW
315 return true;
316}
317
a012e2db 318bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout)
67a42f92
PW
319{
320 hSocketRet = INVALID_SOCKET;
321
23aa78c4 322#ifdef USE_IPV6
8f10a288
PW
323 struct sockaddr_storage sockaddr;
324#else
325 struct sockaddr sockaddr;
23aa78c4 326#endif
8f10a288
PW
327 socklen_t len = sizeof(sockaddr);
328 if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
7d9d134b 329 LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
23aa78c4
PW
330 return false;
331 }
332
8f10a288 333 SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
67a42f92
PW
334 if (hSocket == INVALID_SOCKET)
335 return false;
336#ifdef SO_NOSIGPIPE
337 int set = 1;
338 setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
339#endif
340
67a42f92
PW
341#ifdef WIN32
342 u_long fNonblock = 1;
343 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
344#else
345 int fFlags = fcntl(hSocket, F_GETFL, 0);
346 if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
347#endif
348 {
349 closesocket(hSocket);
350 return false;
351 }
352
8f10a288 353 if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
67a42f92
PW
354 {
355 // WSAEINVAL is here because some legacy version of winsock uses it
356 if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
357 {
358 struct timeval timeout;
359 timeout.tv_sec = nTimeout / 1000;
360 timeout.tv_usec = (nTimeout % 1000) * 1000;
361
362 fd_set fdset;
363 FD_ZERO(&fdset);
364 FD_SET(hSocket, &fdset);
365 int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
366 if (nRet == 0)
367 {
7d9d134b 368 LogPrint("net", "connection to %s timeout\n", addrConnect.ToString());
67a42f92
PW
369 closesocket(hSocket);
370 return false;
371 }
372 if (nRet == SOCKET_ERROR)
373 {
7d9d134b 374 LogPrintf("select() for %s failed: %i\n", addrConnect.ToString(), WSAGetLastError());
67a42f92
PW
375 closesocket(hSocket);
376 return false;
377 }
378 socklen_t nRetSize = sizeof(nRet);
379#ifdef WIN32
380 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
381#else
382 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
383#endif
384 {
7d9d134b 385 LogPrintf("getsockopt() for %s failed: %i\n", addrConnect.ToString(), WSAGetLastError());
67a42f92
PW
386 closesocket(hSocket);
387 return false;
388 }
389 if (nRet != 0)
390 {
7d9d134b 391 LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), strerror(nRet));
67a42f92
PW
392 closesocket(hSocket);
393 return false;
394 }
395 }
396#ifdef WIN32
397 else if (WSAGetLastError() != WSAEISCONN)
398#else
399 else
400#endif
401 {
7d9d134b 402 LogPrintf("connect() to %s failed: %i\n", addrConnect.ToString(), WSAGetLastError());
67a42f92
PW
403 closesocket(hSocket);
404 return false;
405 }
406 }
407
408 // this isn't even strictly necessary
409 // CNode::ConnectNode immediately turns the socket back to non-blocking
410 // but we'll turn it back to blocking just in case
411#ifdef WIN32
412 fNonblock = 0;
413 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
414#else
415 fFlags = fcntl(hSocket, F_GETFL, 0);
fe9e88cb 416 if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR)
67a42f92
PW
417#endif
418 {
419 closesocket(hSocket);
420 return false;
421 }
422
a012e2db
PW
423 hSocketRet = hSocket;
424 return true;
425}
426
587f929c
PW
427bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion) {
428 assert(net >= 0 && net < NET_MAX);
429 if (nSocksVersion != 0 && nSocksVersion != 4 && nSocksVersion != 5)
430 return false;
431 if (nSocksVersion != 0 && !addrProxy.IsValid())
432 return false;
81bbef26 433 LOCK(cs_proxyInfos);
587f929c
PW
434 proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion);
435 return true;
436}
437
81bbef26 438bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
587f929c 439 assert(net >= 0 && net < NET_MAX);
81bbef26 440 LOCK(cs_proxyInfos);
587f929c
PW
441 if (!proxyInfo[net].second)
442 return false;
81bbef26 443 proxyInfoOut = proxyInfo[net];
587f929c
PW
444 return true;
445}
446
447bool SetNameProxy(CService addrProxy, int nSocksVersion) {
448 if (nSocksVersion != 0 && nSocksVersion != 5)
449 return false;
450 if (nSocksVersion != 0 && !addrProxy.IsValid())
451 return false;
81bbef26 452 LOCK(cs_proxyInfos);
587f929c
PW
453 nameproxyInfo = std::make_pair(addrProxy, nSocksVersion);
454 return true;
455}
456
81bbef26
PK
457bool GetNameProxy(proxyType &nameproxyInfoOut) {
458 LOCK(cs_proxyInfos);
459 if (!nameproxyInfo.second)
460 return false;
461 nameproxyInfoOut = nameproxyInfo;
462 return true;
463}
464
465bool HaveNameProxy() {
466 LOCK(cs_proxyInfos);
587f929c
PW
467 return nameproxyInfo.second != 0;
468}
469
470bool IsProxy(const CNetAddr &addr) {
81bbef26
PK
471 LOCK(cs_proxyInfos);
472 for (int i = 0; i < NET_MAX; i++) {
587f929c
PW
473 if (proxyInfo[i].second && (addr == (CNetAddr)proxyInfo[i].first))
474 return true;
475 }
476 return false;
477}
478
a012e2db
PW
479bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
480{
81bbef26 481 proxyType proxy;
587f929c
PW
482
483 // no proxy needed
81bbef26 484 if (!GetProxy(addrDest.GetNetwork(), proxy))
587f929c
PW
485 return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
486
a012e2db 487 SOCKET hSocket = INVALID_SOCKET;
a012e2db 488
587f929c
PW
489 // first connect to proxy server
490 if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout))
491 return false;
ea0796bd 492
587f929c
PW
493 // do socks negotiation
494 switch (proxy.second) {
495 case 4:
496 if (!Socks4(addrDest, hSocket))
497 return false;
498 break;
499 case 5:
500 if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
501 return false;
502 break;
503 default:
a012e2db 504 return false;
67a42f92
PW
505 }
506
507 hSocketRet = hSocket;
508 return true;
509}
510
9bab521d
PW
511bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout)
512{
1e8aeae1 513 string strDest;
9bab521d 514 int port = portDefault;
1e8aeae1 515 SplitHostPort(string(pszDest), port, strDest);
9bab521d
PW
516
517 SOCKET hSocket = INVALID_SOCKET;
81bbef26
PK
518
519 proxyType nameproxy;
520 GetNameProxy(nameproxy);
521
522 CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxy.second), port);
9bab521d
PW
523 if (addrResolved.IsValid()) {
524 addr = addrResolved;
525 return ConnectSocket(addr, hSocketRet, nTimeout);
526 }
527 addr = CService("0.0.0.0:0");
81bbef26 528 if (!nameproxy.second)
9bab521d 529 return false;
81bbef26 530 if (!ConnectSocketDirectly(nameproxy.first, hSocket, nTimeout))
9bab521d
PW
531 return false;
532
81bbef26 533 switch(nameproxy.second) {
587f929c
PW
534 default:
535 case 4: return false;
536 case 5:
537 if (!Socks5(strDest, port, hSocket))
538 return false;
539 break;
540 }
9bab521d
PW
541
542 hSocketRet = hSocket;
543 return true;
544}
545
67a42f92
PW
546void CNetAddr::Init()
547{
0f8a6477 548 memset(ip, 0, sizeof(ip));
67a42f92
PW
549}
550
551void CNetAddr::SetIP(const CNetAddr& ipIn)
552{
553 memcpy(ip, ipIn.ip, sizeof(ip));
554}
555
70f7f003 556static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
70f7f003
PW
557
558bool CNetAddr::SetSpecial(const std::string &strName)
559{
560 if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
561 std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str());
562 if (vchAddr.size() != 16-sizeof(pchOnionCat))
563 return false;
564 memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
565 for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++)
566 ip[i + sizeof(pchOnionCat)] = vchAddr[i];
567 return true;
568 }
70f7f003
PW
569 return false;
570}
571
67a42f92
PW
572CNetAddr::CNetAddr()
573{
574 Init();
575}
576
577CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
578{
579 memcpy(ip, pchIPv4, 12);
580 memcpy(ip+12, &ipv4Addr, 4);
581}
582
583#ifdef USE_IPV6
584CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
585{
586 memcpy(ip, &ipv6Addr, 16);
587}
588#endif
589
590CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup)
591{
592 Init();
593 std::vector<CNetAddr> vIP;
594 if (LookupHost(pszIp, vIP, 1, fAllowLookup))
595 *this = vIP[0];
596}
597
598CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup)
599{
600 Init();
601 std::vector<CNetAddr> vIP;
602 if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup))
603 *this = vIP[0];
604}
605
463a1cab 606unsigned int CNetAddr::GetByte(int n) const
67a42f92
PW
607{
608 return ip[15-n];
609}
610
611bool CNetAddr::IsIPv4() const
612{
613 return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
614}
615
23aa78c4
PW
616bool CNetAddr::IsIPv6() const
617{
4e882b79 618 return (!IsIPv4() && !IsTor());
23aa78c4
PW
619}
620
67a42f92
PW
621bool CNetAddr::IsRFC1918() const
622{
623 return IsIPv4() && (
ea0796bd
JG
624 GetByte(3) == 10 ||
625 (GetByte(3) == 192 && GetByte(2) == 168) ||
67a42f92
PW
626 (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
627}
628
629bool CNetAddr::IsRFC3927() const
630{
631 return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
632}
633
634bool CNetAddr::IsRFC3849() const
635{
636 return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
637}
638
639bool CNetAddr::IsRFC3964() const
640{
641 return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
642}
643
644bool CNetAddr::IsRFC6052() const
645{
646 static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0};
647 return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0);
648}
649
650bool CNetAddr::IsRFC4380() const
651{
652 return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
653}
654
655bool CNetAddr::IsRFC4862() const
656{
657 static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0};
658 return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
659}
660
661bool CNetAddr::IsRFC4193() const
662{
663 return ((GetByte(15) & 0xFE) == 0xFC);
664}
665
666bool CNetAddr::IsRFC6145() const
667{
668 static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0};
669 return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0);
670}
671
672bool CNetAddr::IsRFC4843() const
673{
d3896211 674 return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
67a42f92
PW
675}
676
70f7f003 677bool CNetAddr::IsTor() const
d3214856 678{
d3214856
PW
679 return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
680}
681
67a42f92
PW
682bool CNetAddr::IsLocal() const
683{
684 // IPv4 loopback
685 if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
686 return true;
687
688 // IPv6 loopback (::1/128)
689 static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
690 if (memcmp(ip, pchLocal, 16) == 0)
691 return true;
692
693 return false;
694}
695
696bool CNetAddr::IsMulticast() const
697{
698 return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
699 || (GetByte(15) == 0xFF);
700}
701
702bool CNetAddr::IsValid() const
703{
814efd6f 704 // Cleanup 3-byte shifted addresses caused by garbage in size field
67a42f92
PW
705 // of addr messages from versions before 0.2.9 checksum.
706 // Two consecutive addr messages look like this:
707 // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
708 // so if the first length field is garbled, it reads the second batch
709 // of addr misaligned by 3 bytes.
710 if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
711 return false;
712
713 // unspecified IPv6 address (::/128)
714 unsigned char ipNone[16] = {};
715 if (memcmp(ip, ipNone, 16) == 0)
716 return false;
717
718 // documentation IPv6 address
719 if (IsRFC3849())
720 return false;
721
722 if (IsIPv4())
723 {
724 // INADDR_NONE
725 uint32_t ipNone = INADDR_NONE;
726 if (memcmp(ip+12, &ipNone, 4) == 0)
727 return false;
728
729 // 0
730 ipNone = 0;
731 if (memcmp(ip+12, &ipNone, 4) == 0)
732 return false;
733 }
734
735 return true;
736}
737
738bool CNetAddr::IsRoutable() const
739{
4e882b79 740 return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal());
67a42f92
PW
741}
742
090e5b40
PW
743enum Network CNetAddr::GetNetwork() const
744{
745 if (!IsRoutable())
746 return NET_UNROUTABLE;
747
748 if (IsIPv4())
749 return NET_IPV4;
750
70f7f003 751 if (IsTor())
090e5b40
PW
752 return NET_TOR;
753
090e5b40
PW
754 return NET_IPV6;
755}
756
67a42f92
PW
757std::string CNetAddr::ToStringIP() const
758{
70f7f003
PW
759 if (IsTor())
760 return EncodeBase32(&ip[6], 10) + ".onion";
ca814646
PW
761 CService serv(*this, 0);
762#ifdef USE_IPV6
763 struct sockaddr_storage sockaddr;
764#else
765 struct sockaddr sockaddr;
766#endif
767 socklen_t socklen = sizeof(sockaddr);
768 if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) {
769 char name[1025] = "";
770 if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST))
771 return std::string(name);
772 }
70f7f003 773 if (IsIPv4())
67a42f92
PW
774 return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
775 else
776 return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
777 GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12),
778 GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8),
779 GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4),
780 GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0));
781}
782
783std::string CNetAddr::ToString() const
784{
785 return ToStringIP();
786}
787
788bool operator==(const CNetAddr& a, const CNetAddr& b)
789{
790 return (memcmp(a.ip, b.ip, 16) == 0);
791}
792
793bool operator!=(const CNetAddr& a, const CNetAddr& b)
794{
795 return (memcmp(a.ip, b.ip, 16) != 0);
796}
797
798bool operator<(const CNetAddr& a, const CNetAddr& b)
799{
800 return (memcmp(a.ip, b.ip, 16) < 0);
801}
802
803bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
804{
805 if (!IsIPv4())
806 return false;
807 memcpy(pipv4Addr, ip+12, 4);
808 return true;
809}
810
811#ifdef USE_IPV6
812bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
813{
814 memcpy(pipv6Addr, ip, 16);
815 return true;
816}
817#endif
818
819// get canonical identifier of an address' group
820// no two connections will be attempted to addresses with the same group
821std::vector<unsigned char> CNetAddr::GetGroup() const
822{
823 std::vector<unsigned char> vchRet;
c5b3ffd8 824 int nClass = NET_IPV6;
67a42f92
PW
825 int nStartByte = 0;
826 int nBits = 16;
827
5fee401f
PW
828 // all local addresses belong to the same group
829 if (IsLocal())
830 {
c5b3ffd8 831 nClass = 255;
5fee401f
PW
832 nBits = 0;
833 }
834
835 // all unroutable addresses belong to the same group
67a42f92
PW
836 if (!IsRoutable())
837 {
c5b3ffd8 838 nClass = NET_UNROUTABLE;
5fee401f 839 nBits = 0;
67a42f92
PW
840 }
841 // for IPv4 addresses, '1' + the 16 higher-order bits of the IP
842 // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
843 else if (IsIPv4() || IsRFC6145() || IsRFC6052())
844 {
c5b3ffd8 845 nClass = NET_IPV4;
67a42f92
PW
846 nStartByte = 12;
847 }
814efd6f 848 // for 6to4 tunnelled addresses, use the encapsulated IPv4 address
67a42f92
PW
849 else if (IsRFC3964())
850 {
c5b3ffd8 851 nClass = NET_IPV4;
67a42f92
PW
852 nStartByte = 2;
853 }
814efd6f 854 // for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address
67a42f92
PW
855 else if (IsRFC4380())
856 {
c5b3ffd8 857 vchRet.push_back(NET_IPV4);
67a42f92
PW
858 vchRet.push_back(GetByte(3) ^ 0xFF);
859 vchRet.push_back(GetByte(2) ^ 0xFF);
860 return vchRet;
861 }
70f7f003
PW
862 else if (IsTor())
863 {
864 nClass = NET_TOR;
865 nStartByte = 6;
866 nBits = 4;
867 }
67a42f92 868 // for he.net, use /36 groups
a5e685bc 869 else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
67a42f92
PW
870 nBits = 36;
871 // for the rest of the IPv6 network, use /32 groups
872 else
873 nBits = 32;
874
875 vchRet.push_back(nClass);
876 while (nBits >= 8)
877 {
878 vchRet.push_back(GetByte(15 - nStartByte));
879 nStartByte++;
880 nBits -= 8;
881 }
882 if (nBits > 0)
883 vchRet.push_back(GetByte(15 - nStartByte) | ((1 << nBits) - 1));
884
885 return vchRet;
886}
887
51ed9ec9 888uint64_t CNetAddr::GetHash() const
67a42f92
PW
889{
890 uint256 hash = Hash(&ip[0], &ip[16]);
51ed9ec9 891 uint64_t nRet;
67a42f92
PW
892 memcpy(&nRet, &hash, sizeof(nRet));
893 return nRet;
894}
895
896void CNetAddr::print() const
897{
7d9d134b 898 LogPrintf("CNetAddr(%s)\n", ToString());
67a42f92
PW
899}
900
d077dd2a
PW
901// private extensions to enum Network, only returned by GetExtNetwork,
902// and only used in GetReachabilityFrom
903static const int NET_UNKNOWN = NET_MAX + 0;
904static const int NET_TEREDO = NET_MAX + 1;
905int static GetExtNetwork(const CNetAddr *addr)
906{
907 if (addr == NULL)
908 return NET_UNKNOWN;
909 if (addr->IsRFC4380())
910 return NET_TEREDO;
911 return addr->GetNetwork();
912}
913
914/** Calculates a metric for how reachable (*this) is from a given partner */
39857190
PW
915int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
916{
d077dd2a
PW
917 enum Reachability {
918 REACH_UNREACHABLE,
919 REACH_DEFAULT,
920 REACH_TEREDO,
921 REACH_IPV6_WEAK,
922 REACH_IPV4,
923 REACH_IPV6_STRONG,
924 REACH_PRIVATE
925 };
926
927 if (!IsRoutable())
928 return REACH_UNREACHABLE;
929
930 int ourNet = GetExtNetwork(this);
931 int theirNet = GetExtNetwork(paddrPartner);
932 bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
933
934 switch(theirNet) {
935 case NET_IPV4:
936 switch(ourNet) {
937 default: return REACH_DEFAULT;
938 case NET_IPV4: return REACH_IPV4;
939 }
940 case NET_IPV6:
941 switch(ourNet) {
942 default: return REACH_DEFAULT;
943 case NET_TEREDO: return REACH_TEREDO;
944 case NET_IPV4: return REACH_IPV4;
814efd6f 945 case NET_IPV6: return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunnelled
d077dd2a
PW
946 }
947 case NET_TOR:
948 switch(ourNet) {
949 default: return REACH_DEFAULT;
950 case NET_IPV4: return REACH_IPV4; // Tor users can connect to IPv4 as well
951 case NET_TOR: return REACH_PRIVATE;
952 }
d077dd2a
PW
953 case NET_TEREDO:
954 switch(ourNet) {
955 default: return REACH_DEFAULT;
956 case NET_TEREDO: return REACH_TEREDO;
957 case NET_IPV6: return REACH_IPV6_WEAK;
958 case NET_IPV4: return REACH_IPV4;
959 }
960 case NET_UNKNOWN:
961 case NET_UNROUTABLE:
962 default:
963 switch(ourNet) {
964 default: return REACH_DEFAULT;
965 case NET_TEREDO: return REACH_TEREDO;
966 case NET_IPV6: return REACH_IPV6_WEAK;
967 case NET_IPV4: return REACH_IPV4;
4e882b79 968 case NET_TOR: return REACH_PRIVATE; // either from Tor, or don't care about our address
d077dd2a
PW
969 }
970 }
39857190
PW
971}
972
67a42f92
PW
973void CService::Init()
974{
975 port = 0;
976}
977
978CService::CService()
979{
980 Init();
981}
982
983CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn)
984{
985}
986
987CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn)
988{
989}
990
991#ifdef USE_IPV6
992CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn)
993{
994}
995#endif
996
997CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port))
998{
999 assert(addr.sin_family == AF_INET);
1000}
1001
1002#ifdef USE_IPV6
1003CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr), port(ntohs(addr.sin6_port))
1004{
1005 assert(addr.sin6_family == AF_INET6);
1006}
1007#endif
1008
8f10a288
PW
1009bool CService::SetSockAddr(const struct sockaddr *paddr)
1010{
1011 switch (paddr->sa_family) {
1012 case AF_INET:
1013 *this = CService(*(const struct sockaddr_in*)paddr);
1014 return true;
1015#ifdef USE_IPV6
1016 case AF_INET6:
1017 *this = CService(*(const struct sockaddr_in6*)paddr);
1018 return true;
1019#endif
1020 default:
1021 return false;
1022 }
1023}
1024
67a42f92
PW
1025CService::CService(const char *pszIpPort, bool fAllowLookup)
1026{
1027 Init();
1028 CService ip;
1029 if (Lookup(pszIpPort, ip, 0, fAllowLookup))
1030 *this = ip;
1031}
1032
c981d768 1033CService::CService(const char *pszIpPort, int portDefault, bool fAllowLookup)
67a42f92 1034{
c981d768
PW
1035 Init();
1036 CService ip;
1037 if (Lookup(pszIpPort, ip, portDefault, fAllowLookup))
1038 *this = ip;
67a42f92
PW
1039}
1040
1041CService::CService(const std::string &strIpPort, bool fAllowLookup)
1042{
1043 Init();
1044 CService ip;
1045 if (Lookup(strIpPort.c_str(), ip, 0, fAllowLookup))
1046 *this = ip;
1047}
1048
c981d768 1049CService::CService(const std::string &strIpPort, int portDefault, bool fAllowLookup)
67a42f92 1050{
c981d768
PW
1051 Init();
1052 CService ip;
1053 if (Lookup(strIpPort.c_str(), ip, portDefault, fAllowLookup))
1054 *this = ip;
67a42f92
PW
1055}
1056
1057unsigned short CService::GetPort() const
1058{
1059 return port;
1060}
1061
1062bool operator==(const CService& a, const CService& b)
1063{
1064 return (CNetAddr)a == (CNetAddr)b && a.port == b.port;
1065}
1066
1067bool operator!=(const CService& a, const CService& b)
1068{
1069 return (CNetAddr)a != (CNetAddr)b || a.port != b.port;
1070}
1071
1072bool operator<(const CService& a, const CService& b)
1073{
1074 return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port);
1075}
1076
8f10a288 1077bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
67a42f92 1078{
8f10a288 1079 if (IsIPv4()) {
b69dd08a 1080 if (*addrlen < (socklen_t)sizeof(struct sockaddr_in))
8f10a288
PW
1081 return false;
1082 *addrlen = sizeof(struct sockaddr_in);
1083 struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr;
1084 memset(paddrin, 0, *addrlen);
1085 if (!GetInAddr(&paddrin->sin_addr))
1086 return false;
1087 paddrin->sin_family = AF_INET;
1088 paddrin->sin_port = htons(port);
1089 return true;
1090 }
67a42f92 1091#ifdef USE_IPV6
8f10a288 1092 if (IsIPv6()) {
b69dd08a 1093 if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
8f10a288
PW
1094 return false;
1095 *addrlen = sizeof(struct sockaddr_in6);
1096 struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr;
1097 memset(paddrin6, 0, *addrlen);
1098 if (!GetIn6Addr(&paddrin6->sin6_addr))
1099 return false;
1100 paddrin6->sin6_family = AF_INET6;
1101 paddrin6->sin6_port = htons(port);
1102 return true;
1103 }
67a42f92 1104#endif
8f10a288
PW
1105 return false;
1106}
67a42f92
PW
1107
1108std::vector<unsigned char> CService::GetKey() const
1109{
1110 std::vector<unsigned char> vKey;
1111 vKey.resize(18);
1112 memcpy(&vKey[0], ip, 16);
1113 vKey[16] = port / 0x100;
1114 vKey[17] = port & 0x0FF;
1115 return vKey;
1116}
1117
1118std::string CService::ToStringPort() const
1119{
463a1cab 1120 return strprintf("%u", port);
67a42f92
PW
1121}
1122
1123std::string CService::ToStringIPPort() const
1124{
4e882b79 1125 if (IsIPv4() || IsTor()) {
23aa78c4
PW
1126 return ToStringIP() + ":" + ToStringPort();
1127 } else {
1128 return "[" + ToStringIP() + "]:" + ToStringPort();
1129 }
67a42f92
PW
1130}
1131
1132std::string CService::ToString() const
1133{
1134 return ToStringIPPort();
1135}
1136
1137void CService::print() const
1138{
7d9d134b 1139 LogPrintf("CService(%s)\n", ToString());
67a42f92
PW
1140}
1141
1142void CService::SetPort(unsigned short portIn)
1143{
1144 port = portIn;
1145}
This page took 0.254847 seconds and 4 git commands to generate.