Fabcoin Core  0.16.2
P2P Digital Currency
netbase.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #ifdef HAVE_CONFIG_H
8 #endif
9 
10 #include <netbase.h>
11 
12 #include <hash.h>
13 #include <sync.h>
14 #include <uint256.h>
15 #include <random.h>
16 #include <util.h>
17 #include <utilstrencodings.h>
18 
19 #include <atomic>
20 
21 #ifndef WIN32
22 #include <fcntl.h>
23 #endif
24 
25 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
26 #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
27 
28 #if !defined(HAVE_MSG_NOSIGNAL)
29 #define MSG_NOSIGNAL 0
30 #endif
31 
32 // Settings
33 static proxyType proxyInfo[NET_MAX];
34 static proxyType nameProxy;
35 static CCriticalSection cs_proxyInfos;
36 int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
37 bool fNameLookup = DEFAULT_NAME_LOOKUP;
38 
39 // Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
40 static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
41 static std::atomic<bool> interruptSocks5Recv(false);
42 
43 enum Network ParseNetwork(std::string net) {
44  boost::to_lower(net);
45  if (net == "ipv4") return NET_IPV4;
46  if (net == "ipv6") return NET_IPV6;
47  if (net == "tor" || net == "onion") return NET_TOR;
48  return NET_UNROUTABLE;
49 }
50 
51 std::string GetNetworkName(enum Network net) {
52  switch(net)
53  {
54  case NET_IPV4: return "ipv4";
55  case NET_IPV6: return "ipv6";
56  case NET_TOR: return "onion";
57  default: return "";
58  }
59 }
60 
61 bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
62 {
63  vIP.clear();
64 
65  {
66  CNetAddr addr;
67  if (addr.SetSpecial(std::string(pszName))) {
68  vIP.push_back(addr);
69  return true;
70  }
71  }
72 
73  struct addrinfo aiHint;
74  memset(&aiHint, 0, sizeof(struct addrinfo));
75 
76  aiHint.ai_socktype = SOCK_STREAM;
77  aiHint.ai_protocol = IPPROTO_TCP;
78  aiHint.ai_family = AF_UNSPEC;
79 #ifdef WIN32
80  aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
81 #else
82  aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
83 #endif
84  struct addrinfo *aiRes = nullptr;
85  int nErr = getaddrinfo(pszName, nullptr, &aiHint, &aiRes);
86  if (nErr)
87  return false;
88 
89  struct addrinfo *aiTrav = aiRes;
90  while (aiTrav != nullptr && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
91  {
92  CNetAddr resolved;
93  if (aiTrav->ai_family == AF_INET)
94  {
95  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
96  resolved = CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr);
97  }
98 
99  if (aiTrav->ai_family == AF_INET6)
100  {
101  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
102  struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
103  resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id);
104  }
105  /* Never allow resolving to an internal address. Consider any such result invalid */
106  if (!resolved.IsInternal()) {
107  vIP.push_back(resolved);
108  }
109 
110  aiTrav = aiTrav->ai_next;
111  }
112 
113  freeaddrinfo(aiRes);
114 
115  return (vIP.size() > 0);
116 }
117 
118 bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
119 {
120  std::string strHost(pszName);
121  if (strHost.empty())
122  return false;
123  if (boost::algorithm::starts_with(strHost, "[") && boost::algorithm::ends_with(strHost, "]"))
124  {
125  strHost = strHost.substr(1, strHost.size() - 2);
126  }
127 
128  return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
129 }
130 
131 bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup)
132 {
133  std::vector<CNetAddr> vIP;
134  LookupHost(pszName, vIP, 1, fAllowLookup);
135  if(vIP.empty())
136  return false;
137  addr = vIP.front();
138  return true;
139 }
140 
141 bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
142 {
143  if (pszName[0] == 0)
144  return false;
145  int port = portDefault;
146  std::string hostname = "";
147  SplitHostPort(std::string(pszName), port, hostname);
148 
149  std::vector<CNetAddr> vIP;
150  bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
151  if (!fRet)
152  return false;
153  vAddr.resize(vIP.size());
154  for (unsigned int i = 0; i < vIP.size(); i++)
155  vAddr[i] = CService(vIP[i], port);
156  return true;
157 }
158 
159 bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
160 {
161  std::vector<CService> vService;
162  bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
163  if (!fRet)
164  return false;
165  addr = vService[0];
166  return true;
167 }
168 
169 CService LookupNumeric(const char *pszName, int portDefault)
170 {
171  CService addr;
172  // "1.2:345" will fail to resolve the ip, but will still set the port.
173  // If the ip fails to resolve, re-init the result.
174  if(!Lookup(pszName, addr, portDefault, false))
175  addr = CService();
176  return addr;
177 }
178 
179 struct timeval MillisToTimeval(int64_t nTimeout)
180 {
181  struct timeval timeout;
182  timeout.tv_sec = nTimeout / 1000;
183  timeout.tv_usec = (nTimeout % 1000) * 1000;
184  return timeout;
185 }
186 
188 enum SOCKSVersion: uint8_t {
189  SOCKS4 = 0x04,
190  SOCKS5 = 0x05
191 };
192 
194 enum SOCKS5Method: uint8_t {
195  NOAUTH = 0x00,
196  GSSAPI = 0x01,
197  USER_PASS = 0x02,
198  NO_ACCEPTABLE = 0xff,
199 };
200 
202 enum SOCKS5Command: uint8_t {
203  CONNECT = 0x01,
204  BIND = 0x02,
206 };
207 
209 enum SOCKS5Reply: uint8_t {
210  SUCCEEDED = 0x00,
211  GENFAILURE = 0x01,
212  NOTALLOWED = 0x02,
213  NETUNREACHABLE = 0x03,
215  CONNREFUSED = 0x05,
216  TTLEXPIRED = 0x06,
217  CMDUNSUPPORTED = 0x07,
219 };
220 
222 enum SOCKS5Atyp: uint8_t {
223  IPV4 = 0x01,
224  DOMAINNAME = 0x03,
225  IPV6 = 0x04,
226 };
227 
229 enum class IntrRecvError {
230  OK,
231  Timeout,
232  Disconnected,
233  NetworkError,
235 };
236 
248 static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const SOCKET& hSocket)
249 {
250  int64_t curTime = GetTimeMillis();
251  int64_t endTime = curTime + timeout;
252  // Maximum time to wait in one select call. It will take up until this time (in millis)
253  // to break off in case of an interruption.
254  const int64_t maxWait = 1000;
255  while (len > 0 && curTime < endTime) {
256  ssize_t ret = recv(hSocket, (char*)data, len, 0); // Optimistically try the recv first
257  if (ret > 0) {
258  len -= ret;
259  data += ret;
260  } else if (ret == 0) { // Unexpected disconnection
262  } else { // Other error or blocking
263  int nErr = WSAGetLastError();
264  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
265  if (!IsSelectableSocket(hSocket)) {
267  }
268  struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait));
269  fd_set fdset;
270  FD_ZERO(&fdset);
271  FD_SET(hSocket, &fdset);
272  int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval);
273  if (nRet == SOCKET_ERROR) {
275  }
276  } else {
278  }
279  }
280  if (interruptSocks5Recv)
282  curTime = GetTimeMillis();
283  }
284  return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
285 }
286 
289 {
290  std::string username;
291  std::string password;
292 };
293 
295 std::string Socks5ErrorString(uint8_t err)
296 {
297  switch(err) {
299  return "general failure";
301  return "connection not allowed";
303  return "network unreachable";
305  return "host unreachable";
307  return "connection refused";
309  return "TTL expired";
311  return "protocol error";
313  return "address type not supported";
314  default:
315  return "unknown";
316  }
317 }
318 
320 static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket)
321 {
322  IntrRecvError recvr;
323  LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
324  if (strDest.size() > 255) {
325  CloseSocket(hSocket);
326  return error("Hostname too long");
327  }
328  // Accepted authentication methods
329  std::vector<uint8_t> vSocks5Init;
330  vSocks5Init.push_back(SOCKSVersion::SOCKS5);
331  if (auth) {
332  vSocks5Init.push_back(0x02); // Number of methods
333  vSocks5Init.push_back(SOCKS5Method::NOAUTH);
334  vSocks5Init.push_back(SOCKS5Method::USER_PASS);
335  } else {
336  vSocks5Init.push_back(0x01); // Number of methods
337  vSocks5Init.push_back(SOCKS5Method::NOAUTH);
338  }
339  ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
340  if (ret != (ssize_t)vSocks5Init.size()) {
341  CloseSocket(hSocket);
342  return error("Error sending to proxy");
343  }
344  uint8_t pchRet1[2];
345  if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
346  CloseSocket(hSocket);
347  LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
348  return false;
349  }
350  if (pchRet1[0] != SOCKSVersion::SOCKS5) {
351  CloseSocket(hSocket);
352  return error("Proxy failed to initialize");
353  }
354  if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
355  // Perform username/password authentication (as described in RFC1929)
356  std::vector<uint8_t> vAuth;
357  vAuth.push_back(0x01); // Current (and only) version of user/pass subnegotiation
358  if (auth->username.size() > 255 || auth->password.size() > 255)
359  return error("Proxy username or password too long");
360  vAuth.push_back(auth->username.size());
361  vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
362  vAuth.push_back(auth->password.size());
363  vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
364  ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL);
365  if (ret != (ssize_t)vAuth.size()) {
366  CloseSocket(hSocket);
367  return error("Error sending authentication to proxy");
368  }
369  LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
370  uint8_t pchRetA[2];
371  if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
372  CloseSocket(hSocket);
373  return error("Error reading proxy authentication response");
374  }
375  if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
376  CloseSocket(hSocket);
377  return error("Proxy authentication unsuccessful");
378  }
379  } else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
380  // Perform no authentication
381  } else {
382  CloseSocket(hSocket);
383  return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
384  }
385  std::vector<uint8_t> vSocks5;
386  vSocks5.push_back(SOCKSVersion::SOCKS5); // VER protocol version
387  vSocks5.push_back(SOCKS5Command::CONNECT); // CMD CONNECT
388  vSocks5.push_back(0x00); // RSV Reserved must be 0
389  vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); // ATYP DOMAINNAME
390  vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function
391  vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
392  vSocks5.push_back((port >> 8) & 0xFF);
393  vSocks5.push_back((port >> 0) & 0xFF);
394  ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL);
395  if (ret != (ssize_t)vSocks5.size()) {
396  CloseSocket(hSocket);
397  return error("Error sending to proxy");
398  }
399  uint8_t pchRet2[4];
400  if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
401  CloseSocket(hSocket);
402  if (recvr == IntrRecvError::Timeout) {
403  /* If a timeout happens here, this effectively means we timed out while connecting
404  * to the remote node. This is very common for Tor, so do not print an
405  * error message. */
406  return false;
407  } else {
408  return error("Error while reading proxy response");
409  }
410  }
411  if (pchRet2[0] != SOCKSVersion::SOCKS5) {
412  CloseSocket(hSocket);
413  return error("Proxy failed to accept request");
414  }
415  if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
416  // Failures to connect to a peer that are not proxy errors
417  CloseSocket(hSocket);
418  LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
419  return false;
420  }
421  if (pchRet2[2] != 0x00) { // Reserved field must be 0
422  CloseSocket(hSocket);
423  return error("Error: malformed proxy response");
424  }
425  uint8_t pchRet3[256];
426  switch (pchRet2[3])
427  {
428  case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
429  case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
431  {
432  recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
433  if (recvr != IntrRecvError::OK) {
434  CloseSocket(hSocket);
435  return error("Error reading from proxy");
436  }
437  int nRecv = pchRet3[0];
438  recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
439  break;
440  }
441  default: CloseSocket(hSocket); return error("Error: malformed proxy response");
442  }
443  if (recvr != IntrRecvError::OK) {
444  CloseSocket(hSocket);
445  return error("Error reading from proxy");
446  }
447  if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
448  CloseSocket(hSocket);
449  return error("Error reading from proxy");
450  }
451  LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
452  return true;
453 }
454 
455 bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout)
456 {
457  hSocketRet = INVALID_SOCKET;
458 
459  struct sockaddr_storage sockaddr;
460  socklen_t len = sizeof(sockaddr);
461  if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
462  LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
463  return false;
464  }
465 
466  SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
467  if (hSocket == INVALID_SOCKET)
468  return false;
469 
470 #ifdef SO_NOSIGPIPE
471  int set = 1;
472  // Different way of disabling SIGPIPE on BSD
473  setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
474 #endif
475 
476  //Disable Nagle's algorithm
477  SetSocketNoDelay(hSocket);
478 
479  // Set to non-blocking
480  if (!SetSocketNonBlocking(hSocket, true)) {
481  CloseSocket(hSocket);
482  return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
483  }
484 
485  if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
486  {
487  if (!IsSelectableSocket(hSocket)) {
488  LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
489  CloseSocket(hSocket);
490  return false;
491  }
492  int nErr = WSAGetLastError();
493  // WSAEINVAL is here because some legacy version of winsock uses it
494  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
495  {
496  struct timeval timeout = MillisToTimeval(nTimeout);
497  fd_set fdset;
498  FD_ZERO(&fdset);
499  FD_SET(hSocket, &fdset);
500  int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout);
501  if (nRet == 0)
502  {
503  LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
504  CloseSocket(hSocket);
505  return false;
506  }
507  if (nRet == SOCKET_ERROR)
508  {
509  LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
510  CloseSocket(hSocket);
511  return false;
512  }
513  socklen_t nRetSize = sizeof(nRet);
514 #ifdef WIN32
515  if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
516 #else
517  if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
518 #endif
519  {
520  LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
521  CloseSocket(hSocket);
522  return false;
523  }
524  if (nRet != 0)
525  {
526  //LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet));
527  CloseSocket(hSocket);
528  return false;
529  }
530  }
531 #ifdef WIN32
532  else if (WSAGetLastError() != WSAEISCONN)
533 #else
534  else
535 #endif
536  {
537  //LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
538  CloseSocket(hSocket);
539  return false;
540  }
541  }
542 
543  hSocketRet = hSocket;
544  return true;
545 }
546 
547 bool SetProxy(enum Network net, const proxyType &addrProxy) {
548  assert(net >= 0 && net < NET_MAX);
549  if (!addrProxy.IsValid())
550  return false;
551  LOCK(cs_proxyInfos);
552  proxyInfo[net] = addrProxy;
553  return true;
554 }
555 
556 bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
557  assert(net >= 0 && net < NET_MAX);
558  LOCK(cs_proxyInfos);
559  if (!proxyInfo[net].IsValid())
560  return false;
561  proxyInfoOut = proxyInfo[net];
562  return true;
563 }
564 
565 bool SetNameProxy(const proxyType &addrProxy) {
566  if (!addrProxy.IsValid())
567  return false;
568  LOCK(cs_proxyInfos);
569  nameProxy = addrProxy;
570  return true;
571 }
572 
573 bool GetNameProxy(proxyType &nameProxyOut) {
574  LOCK(cs_proxyInfos);
575  if(!nameProxy.IsValid())
576  return false;
577  nameProxyOut = nameProxy;
578  return true;
579 }
580 
582  LOCK(cs_proxyInfos);
583  return nameProxy.IsValid();
584 }
585 
586 bool IsProxy(const CNetAddr &addr) {
587  LOCK(cs_proxyInfos);
588  for (int i = 0; i < NET_MAX; i++) {
589  if (addr == (CNetAddr)proxyInfo[i].proxy)
590  return true;
591  }
592  return false;
593 }
594 
595 static bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
596 {
597  SOCKET hSocket = INVALID_SOCKET;
598  // first connect to proxy server
599  if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) {
600  if (outProxyConnectionFailed)
601  *outProxyConnectionFailed = true;
602  return false;
603  }
604  // do socks negotiation
605  if (proxy.randomize_credentials) {
606  ProxyCredentials random_auth;
607  static std::atomic_int counter(0);
608  random_auth.username = random_auth.password = strprintf("%i", counter++);
609  if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket))
610  return false;
611  } else {
612  if (!Socks5(strDest, (unsigned short)port, 0, hSocket))
613  return false;
614  }
615 
616  hSocketRet = hSocket;
617  return true;
618 }
619 
620 bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
621 {
622  proxyType proxy;
623  if (outProxyConnectionFailed)
624  *outProxyConnectionFailed = false;
625 
626  if (GetProxy(addrDest.GetNetwork(), proxy))
627  return ConnectThroughProxy(proxy, addrDest.ToStringIP(), addrDest.GetPort(), hSocketRet, nTimeout, outProxyConnectionFailed);
628  else // no proxy needed (none set for target network)
629  return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
630 }
631 
632 bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed)
633 {
634  std::string strDest;
635  int port = portDefault;
636 
637  if (outProxyConnectionFailed)
638  *outProxyConnectionFailed = false;
639 
640  SplitHostPort(std::string(pszDest), port, strDest);
641 
642  proxyType proxy;
643  GetNameProxy(proxy);
644 
645  std::vector<CService> addrResolved;
646  if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy(), 256)) {
647  if (addrResolved.size() > 0) {
648  addr = addrResolved[GetRand(addrResolved.size())];
649  return ConnectSocket(addr, hSocketRet, nTimeout);
650  }
651  }
652 
653  addr = CService();
654 
655  if (!HaveNameProxy())
656  return false;
657  return ConnectThroughProxy(proxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed);
658 }
659 
660 bool LookupSubNet(const char* pszName, CSubNet& ret)
661 {
662  std::string strSubnet(pszName);
663  size_t slash = strSubnet.find_last_of('/');
664  std::vector<CNetAddr> vIP;
665 
666  std::string strAddress = strSubnet.substr(0, slash);
667  if (LookupHost(strAddress.c_str(), vIP, 1, false))
668  {
669  CNetAddr network = vIP[0];
670  if (slash != strSubnet.npos)
671  {
672  std::string strNetmask = strSubnet.substr(slash + 1);
673  int32_t n;
674  // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
675  if (ParseInt32(strNetmask, &n)) { // If valid number, assume /24 syntax
676  ret = CSubNet(network, n);
677  return ret.IsValid();
678  }
679  else // If not a valid number, try full netmask syntax
680  {
681  // Never allow lookup for netmask
682  if (LookupHost(strNetmask.c_str(), vIP, 1, false)) {
683  ret = CSubNet(network, vIP[0]);
684  return ret.IsValid();
685  }
686  }
687  }
688  else
689  {
690  ret = CSubNet(network);
691  return ret.IsValid();
692  }
693  }
694  return false;
695 }
696 
697 #ifdef WIN32
698 std::string NetworkErrorString(int err)
699 {
700  char buf[256];
701  buf[0] = 0;
702  if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
703  nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
704  buf, sizeof(buf), nullptr))
705  {
706  return strprintf("%s (%d)", buf, err);
707  }
708  else
709  {
710  return strprintf("Unknown error (%d)", err);
711  }
712 }
713 #else
714 std::string NetworkErrorString(int err)
715 {
716  char buf[256];
717  buf[0] = 0;
718  /* Too bad there are two incompatible implementations of the
719  * thread-safe strerror. */
720  const char *s;
721 #ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */
722  s = strerror_r(err, buf, sizeof(buf));
723 #else /* POSIX variant always returns message in buffer */
724  s = buf;
725  if (strerror_r(err, buf, sizeof(buf)))
726  buf[0] = 0;
727 #endif
728  return strprintf("%s (%d)", s, err);
729 }
730 #endif
731 
732 bool CloseSocket(SOCKET& hSocket)
733 {
734  if (hSocket == INVALID_SOCKET)
735  return false;
736 #ifdef WIN32
737  int ret = closesocket(hSocket);
738 #else
739  int ret = close(hSocket);
740 #endif
741  hSocket = INVALID_SOCKET;
742  return ret != SOCKET_ERROR;
743 }
744 
745 bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking)
746 {
747  if (fNonBlocking) {
748 #ifdef WIN32
749  u_long nOne = 1;
750  if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
751 #else
752  int fFlags = fcntl(hSocket, F_GETFL, 0);
753  if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
754 #endif
755  return false;
756  }
757  } else {
758 #ifdef WIN32
759  u_long nZero = 0;
760  if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
761 #else
762  int fFlags = fcntl(hSocket, F_GETFL, 0);
763  if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
764 #endif
765  return false;
766  }
767  }
768 
769  return true;
770 }
771 
772 bool SetSocketNoDelay(const SOCKET& hSocket)
773 {
774  int set = 1;
775  int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int));
776  return rc == 0;
777 }
778 
779 void InterruptSocks5(bool interrupt)
780 {
781  interruptSocks5Recv = interrupt;
782 }
#define WSAEINPROGRESS
Definition: compat.h:59
Network unreachable.
Definition: netbase.cpp:215
bool error(const char *fmt, const Args &...args)
Definition: util.h:178
SOCKS5Reply
Values defined for REP in RFC1928.
Definition: netbase.cpp:209
unsigned short GetPort() const
Definition: netaddress.cpp:522
GSSAPI.
Definition: netbase.cpp:197
bool IsInternal() const
Definition: netaddress.cpp:241
No authentication required.
Definition: netbase.cpp:196
#define strprintf
Definition: tinyformat.h:1054
std::string ToStringIP() const
Definition: netaddress.cpp:263
Connection not allowed by ruleset.
Definition: netbase.cpp:213
CService LookupNumeric(const char *pszName, int portDefault)
Definition: netbase.cpp:169
bool GetNameProxy(proxyType &nameProxyOut)
Definition: netbase.cpp:573
assert(len-trim+(2 *lenIndices)<=WIDTH)
#define INVALID_SOCKET
Definition: compat.h:62
ExecStats::duration min
Definition: ExecStats.cpp:35
bool SetNameProxy(const proxyType &addrProxy)
Definition: netbase.cpp:565
#define WSAGetLastError()
Definition: compat.h:53
bool ConnectSocketByName(CService &addr, SOCKET &hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed)
Definition: netbase.cpp:632
SOCKS5Command
Values defined for CMD in RFC1928.
Definition: netbase.cpp:202
bool IsValid() const
Definition: netbase.h:34
std::string Socks5ErrorString(uint8_t err)
Convert SOCKS5 reply to a an error message.
Definition: netbase.cpp:295
bool HaveNameProxy()
Definition: netbase.cpp:581
#define SOCKET_ERROR
Definition: compat.h:63
enum Network ParseNetwork(std::string net)
Definition: netbase.cpp:43
#define LogPrintf(...)
Definition: util.h:153
bool randomize_credentials
Definition: netbase.h:37
bool ParseInt32(const std::string &str, int32_t *out)
Convert string to signed 32-bit integer with strict parse error feedback.
Username/password.
Definition: netbase.cpp:198
#define LOCK(cs)
Definition: sync.h:175
bool ConnectSocket(const CService &addrDest, SOCKET &hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
Definition: netbase.cpp:620
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:140
Credentials for proxy authentication.
Definition: netbase.cpp:288
IntrRecvError
Status codes that can be returned by InterruptibleRecv.
Definition: netbase.cpp:229
bool IsProxy(const CNetAddr &addr)
Definition: netbase.cpp:586
SOCKSVersion
SOCKS version.
Definition: netbase.cpp:188
Succeeded.
Definition: netbase.cpp:211
std::string ToString() const
Definition: netaddress.cpp:596
Network
Definition: netaddress.h:19
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
Definition: netbase.cpp:732
int nConnectTimeout
Definition: netbase.cpp:36
#define WSAEWOULDBLOCK
Definition: compat.h:56
SOCKS5Method
Values defined for METHOD in RFC1928.
Definition: netbase.cpp:194
bool LookupSubNet(const char *pszName, CSubNet &ret)
Definition: netbase.cpp:660
unsigned int SOCKET
Definition: compat.h:51
bool SetProxy(enum Network net, const proxyType &addrProxy)
Definition: netbase.cpp:547
bool SetSocketNonBlocking(const SOCKET &hSocket, bool fNonBlocking)
Disable or enable blocking-mode for a socket.
Definition: netbase.cpp:745
struct timeval MillisToTimeval(int64_t nTimeout)
Convert milliseconds to a struct timeval for e.g.
Definition: netbase.cpp:179
#define LogPrint(category,...)
Definition: util.h:164
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:31
Network unreachable.
Definition: netbase.cpp:214
CService proxy
Definition: netbase.h:36
bool IsValid() const
Definition: netaddress.cpp:721
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
Connection refused.
Definition: netbase.cpp:216
#define WSAEINVAL
Definition: compat.h:54
bool SetSocketNoDelay(const SOCKET &hSocket)
Set the TCP_NODELAY flag on a socket.
Definition: netbase.cpp:772
int64_t GetTimeMillis()
Definition: utiltime.cpp:39
#define MSG_NOSIGNAL
Definition: netbase.cpp:29
bool Lookup(const char *pszName, std::vector< CService > &vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
Definition: netbase.cpp:141
bool SetSpecial(const std::string &strName)
Definition: netaddress.cpp:60
void InterruptSocks5(bool interrupt)
Definition: netbase.cpp:779
std::string password
Definition: netbase.cpp:291
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:556
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
Definition: netbase.cpp:714
Command not supported.
Definition: netbase.cpp:218
TTL expired.
Definition: netbase.cpp:217
General failure.
Definition: netbase.cpp:212
std::string GetNetworkName(enum Network net)
Definition: netbase.cpp:51
bool LookupHost(const char *pszName, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:118
std::string username
Definition: netbase.cpp:290
SOCKS5Atyp
Values defined for ATYPE in RFC1928.
Definition: netbase.cpp:222
uint8_t const * data
Definition: sha3.h:19
bool fNameLookup
Definition: netbase.cpp:37
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Definition: netaddress.cpp:542
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
Definition: sync.h:91
uint64_t GetRand(uint64_t nMax)
Definition: random.cpp:352
enum Network GetNetwork() const
Definition: netaddress.cpp:246