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