Bitcoin Core  0.20.99
P2P Digital Currency
netbase.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 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 #include <netbase.h>
7 
8 #include <sync.h>
9 #include <tinyformat.h>
10 #include <util/strencodings.h>
11 #include <util/string.h>
12 #include <util/system.h>
13 
14 #include <atomic>
15 #include <cstdint>
16 
17 #ifndef WIN32
18 #include <fcntl.h>
19 #else
20 #include <codecvt>
21 #endif
22 
23 #ifdef USE_POLL
24 #include <poll.h>
25 #endif
26 
27 #if !defined(MSG_NOSIGNAL)
28 #define MSG_NOSIGNAL 0
29 #endif
30 
31 // Settings
33 static proxyType proxyInfo[NET_MAX] GUARDED_BY(g_proxyinfo_mutex);
34 static proxyType nameProxy GUARDED_BY(g_proxyinfo_mutex);
37 
38 // Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
39 static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
40 static std::atomic<bool> interruptSocks5Recv(false);
41 
42 enum Network ParseNetwork(const std::string& net_in) {
43  std::string net = ToLower(net_in);
44  if (net == "ipv4") return NET_IPV4;
45  if (net == "ipv6") return NET_IPV6;
46  if (net == "onion") return NET_ONION;
47  if (net == "tor") {
48  LogPrintf("Warning: net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.\n");
49  return NET_ONION;
50  }
51  return NET_UNROUTABLE;
52 }
53 
54 std::string GetNetworkName(enum Network net) {
55  switch(net)
56  {
57  case NET_IPV4: return "ipv4";
58  case NET_IPV6: return "ipv6";
59  case NET_ONION: return "onion";
60  default: return "";
61  }
62 }
63 
64 bool static LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
65 {
66  vIP.clear();
67 
68  if (!ValidAsCString(name)) {
69  return false;
70  }
71 
72  {
73  CNetAddr addr;
74  // From our perspective, onion addresses are not hostnames but rather
75  // direct encodings of CNetAddr much like IPv4 dotted-decimal notation
76  // or IPv6 colon-separated hextet notation. Since we can't use
77  // getaddrinfo to decode them and it wouldn't make sense to resolve
78  // them, we return a network address representing it instead. See
79  // CNetAddr::SetSpecial(const std::string&) for more details.
80  if (addr.SetSpecial(name)) {
81  vIP.push_back(addr);
82  return true;
83  }
84  }
85 
86  struct addrinfo aiHint;
87  memset(&aiHint, 0, sizeof(struct addrinfo));
88 
89  // We want a TCP port, which is a streaming socket type
90  aiHint.ai_socktype = SOCK_STREAM;
91  aiHint.ai_protocol = IPPROTO_TCP;
92  // We don't care which address family (IPv4 or IPv6) is returned
93  aiHint.ai_family = AF_UNSPEC;
94  // If we allow lookups of hostnames, use the AI_ADDRCONFIG flag to only
95  // return addresses whose family we have an address configured for.
96  //
97  // If we don't allow lookups, then use the AI_NUMERICHOST flag for
98  // getaddrinfo to only decode numerical network addresses and suppress
99  // hostname lookups.
100  aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
101  struct addrinfo *aiRes = nullptr;
102  int nErr = getaddrinfo(name.c_str(), nullptr, &aiHint, &aiRes);
103  if (nErr)
104  return false;
105 
106  // Traverse the linked list starting with aiTrav, add all non-internal
107  // IPv4,v6 addresses to vIP while respecting nMaxSolutions.
108  struct addrinfo *aiTrav = aiRes;
109  while (aiTrav != nullptr && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
110  {
111  CNetAddr resolved;
112  if (aiTrav->ai_family == AF_INET)
113  {
114  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
115  resolved = CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr);
116  }
117 
118  if (aiTrav->ai_family == AF_INET6)
119  {
120  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
121  struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
122  resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id);
123  }
124  /* Never allow resolving to an internal address. Consider any such result invalid */
125  if (!resolved.IsInternal()) {
126  vIP.push_back(resolved);
127  }
128 
129  aiTrav = aiTrav->ai_next;
130  }
131 
132  freeaddrinfo(aiRes);
133 
134  return (vIP.size() > 0);
135 }
136 
152 bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
153 {
154  if (!ValidAsCString(name)) {
155  return false;
156  }
157  std::string strHost = name;
158  if (strHost.empty())
159  return false;
160  if (strHost.front() == '[' && strHost.back() == ']') {
161  strHost = strHost.substr(1, strHost.size() - 2);
162  }
163 
164  return LookupIntern(strHost, vIP, nMaxSolutions, fAllowLookup);
165 }
166 
173 bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup)
174 {
175  if (!ValidAsCString(name)) {
176  return false;
177  }
178  std::vector<CNetAddr> vIP;
179  LookupHost(name, vIP, 1, fAllowLookup);
180  if(vIP.empty())
181  return false;
182  addr = vIP.front();
183  return true;
184 }
185 
206 bool Lookup(const std::string& name, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
207 {
208  if (name.empty() || !ValidAsCString(name)) {
209  return false;
210  }
211  int port = portDefault;
212  std::string hostname;
213  SplitHostPort(name, port, hostname);
214 
215  std::vector<CNetAddr> vIP;
216  bool fRet = LookupIntern(hostname, vIP, nMaxSolutions, fAllowLookup);
217  if (!fRet)
218  return false;
219  vAddr.resize(vIP.size());
220  for (unsigned int i = 0; i < vIP.size(); i++)
221  vAddr[i] = CService(vIP[i], port);
222  return true;
223 }
224 
231 bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllowLookup)
232 {
233  if (!ValidAsCString(name)) {
234  return false;
235  }
236  std::vector<CService> vService;
237  bool fRet = Lookup(name, vService, portDefault, fAllowLookup, 1);
238  if (!fRet)
239  return false;
240  addr = vService[0];
241  return true;
242 }
243 
254 CService LookupNumeric(const std::string& name, int portDefault)
255 {
256  if (!ValidAsCString(name)) {
257  return {};
258  }
259  CService addr;
260  // "1.2:345" will fail to resolve the ip, but will still set the port.
261  // If the ip fails to resolve, re-init the result.
262  if(!Lookup(name, addr, portDefault, false))
263  addr = CService();
264  return addr;
265 }
266 
267 struct timeval MillisToTimeval(int64_t nTimeout)
268 {
269  struct timeval timeout;
270  timeout.tv_sec = nTimeout / 1000;
271  timeout.tv_usec = (nTimeout % 1000) * 1000;
272  return timeout;
273 }
274 
276 enum SOCKSVersion: uint8_t {
277  SOCKS4 = 0x04,
278  SOCKS5 = 0x05
279 };
280 
282 enum SOCKS5Method: uint8_t {
283  NOAUTH = 0x00,
284  GSSAPI = 0x01,
285  USER_PASS = 0x02,
286  NO_ACCEPTABLE = 0xff,
287 };
288 
290 enum SOCKS5Command: uint8_t {
291  CONNECT = 0x01,
292  BIND = 0x02,
294 };
295 
297 enum SOCKS5Reply: uint8_t {
298  SUCCEEDED = 0x00,
299  GENFAILURE = 0x01,
300  NOTALLOWED = 0x02,
301  NETUNREACHABLE = 0x03,
303  CONNREFUSED = 0x05,
304  TTLEXPIRED = 0x06,
305  CMDUNSUPPORTED = 0x07,
307 };
308 
310 enum SOCKS5Atyp: uint8_t {
311  IPV4 = 0x01,
312  DOMAINNAME = 0x03,
313  IPV6 = 0x04,
314 };
315 
317 enum class IntrRecvError {
318  OK,
319  Timeout,
320  Disconnected,
321  NetworkError,
323 };
324 
343 static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const SOCKET& hSocket)
344 {
345  int64_t curTime = GetTimeMillis();
346  int64_t endTime = curTime + timeout;
347  // Maximum time to wait for I/O readiness. It will take up until this time
348  // (in millis) to break off in case of an interruption.
349  const int64_t maxWait = 1000;
350  while (len > 0 && curTime < endTime) {
351  ssize_t ret = recv(hSocket, (char*)data, len, 0); // Optimistically try the recv first
352  if (ret > 0) {
353  len -= ret;
354  data += ret;
355  } else if (ret == 0) { // Unexpected disconnection
357  } else { // Other error or blocking
358  int nErr = WSAGetLastError();
359  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
360  if (!IsSelectableSocket(hSocket)) {
362  }
363  // Only wait at most maxWait milliseconds at a time, unless
364  // we're approaching the end of the specified total timeout
365  int timeout_ms = std::min(endTime - curTime, maxWait);
366 #ifdef USE_POLL
367  struct pollfd pollfd = {};
368  pollfd.fd = hSocket;
369  pollfd.events = POLLIN;
370  int nRet = poll(&pollfd, 1, timeout_ms);
371 #else
372  struct timeval tval = MillisToTimeval(timeout_ms);
373  fd_set fdset;
374  FD_ZERO(&fdset);
375  FD_SET(hSocket, &fdset);
376  int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval);
377 #endif
378  if (nRet == SOCKET_ERROR) {
380  }
381  } else {
383  }
384  }
387  curTime = GetTimeMillis();
388  }
389  return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
390 }
391 
394 {
395  std::string username;
396  std::string password;
397 };
398 
400 static std::string Socks5ErrorString(uint8_t err)
401 {
402  switch(err) {
404  return "general failure";
406  return "connection not allowed";
408  return "network unreachable";
410  return "host unreachable";
412  return "connection refused";
414  return "TTL expired";
416  return "protocol error";
418  return "address type not supported";
419  default:
420  return "unknown";
421  }
422 }
423 
442 static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, const SOCKET& hSocket)
443 {
444  IntrRecvError recvr;
445  LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
446  if (strDest.size() > 255) {
447  return error("Hostname too long");
448  }
449  // Construct the version identifier/method selection message
450  std::vector<uint8_t> vSocks5Init;
451  vSocks5Init.push_back(SOCKSVersion::SOCKS5); // We want the SOCK5 protocol
452  if (auth) {
453  vSocks5Init.push_back(0x02); // 2 method identifiers follow...
454  vSocks5Init.push_back(SOCKS5Method::NOAUTH);
455  vSocks5Init.push_back(SOCKS5Method::USER_PASS);
456  } else {
457  vSocks5Init.push_back(0x01); // 1 method identifier follows...
458  vSocks5Init.push_back(SOCKS5Method::NOAUTH);
459  }
460  ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
461  if (ret != (ssize_t)vSocks5Init.size()) {
462  return error("Error sending to proxy");
463  }
464  uint8_t pchRet1[2];
465  if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
466  LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
467  return false;
468  }
469  if (pchRet1[0] != SOCKSVersion::SOCKS5) {
470  return error("Proxy failed to initialize");
471  }
472  if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
473  // Perform username/password authentication (as described in RFC1929)
474  std::vector<uint8_t> vAuth;
475  vAuth.push_back(0x01); // Current (and only) version of user/pass subnegotiation
476  if (auth->username.size() > 255 || auth->password.size() > 255)
477  return error("Proxy username or password too long");
478  vAuth.push_back(auth->username.size());
479  vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
480  vAuth.push_back(auth->password.size());
481  vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
482  ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL);
483  if (ret != (ssize_t)vAuth.size()) {
484  return error("Error sending authentication to proxy");
485  }
486  LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
487  uint8_t pchRetA[2];
488  if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
489  return error("Error reading proxy authentication response");
490  }
491  if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
492  return error("Proxy authentication unsuccessful");
493  }
494  } else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
495  // Perform no authentication
496  } else {
497  return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
498  }
499  std::vector<uint8_t> vSocks5;
500  vSocks5.push_back(SOCKSVersion::SOCKS5); // VER protocol version
501  vSocks5.push_back(SOCKS5Command::CONNECT); // CMD CONNECT
502  vSocks5.push_back(0x00); // RSV Reserved must be 0
503  vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); // ATYP DOMAINNAME
504  vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function
505  vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
506  vSocks5.push_back((port >> 8) & 0xFF);
507  vSocks5.push_back((port >> 0) & 0xFF);
508  ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL);
509  if (ret != (ssize_t)vSocks5.size()) {
510  return error("Error sending to proxy");
511  }
512  uint8_t pchRet2[4];
513  if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
514  if (recvr == IntrRecvError::Timeout) {
515  /* If a timeout happens here, this effectively means we timed out while connecting
516  * to the remote node. This is very common for Tor, so do not print an
517  * error message. */
518  return false;
519  } else {
520  return error("Error while reading proxy response");
521  }
522  }
523  if (pchRet2[0] != SOCKSVersion::SOCKS5) {
524  return error("Proxy failed to accept request");
525  }
526  if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
527  // Failures to connect to a peer that are not proxy errors
528  LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
529  return false;
530  }
531  if (pchRet2[2] != 0x00) { // Reserved field must be 0
532  return error("Error: malformed proxy response");
533  }
534  uint8_t pchRet3[256];
535  switch (pchRet2[3])
536  {
537  case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
538  case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
540  {
541  recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
542  if (recvr != IntrRecvError::OK) {
543  return error("Error reading from proxy");
544  }
545  int nRecv = pchRet3[0];
546  recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
547  break;
548  }
549  default: return error("Error: malformed proxy response");
550  }
551  if (recvr != IntrRecvError::OK) {
552  return error("Error reading from proxy");
553  }
554  if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
555  return error("Error reading from proxy");
556  }
557  LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
558  return true;
559 }
560 
568 SOCKET CreateSocket(const CService &addrConnect)
569 {
570  // Create a sockaddr from the specified service.
571  struct sockaddr_storage sockaddr;
572  socklen_t len = sizeof(sockaddr);
573  if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
574  LogPrintf("Cannot create socket for %s: unsupported network\n", addrConnect.ToString());
575  return INVALID_SOCKET;
576  }
577 
578  // Create a TCP socket in the address family of the specified service.
579  SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
580  if (hSocket == INVALID_SOCKET)
581  return INVALID_SOCKET;
582 
583  // Ensure that waiting for I/O on this socket won't result in undefined
584  // behavior.
585  if (!IsSelectableSocket(hSocket)) {
586  CloseSocket(hSocket);
587  LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
588  return INVALID_SOCKET;
589  }
590 
591 #ifdef SO_NOSIGPIPE
592  int set = 1;
593  // Set the no-sigpipe option on the socket for BSD systems, other UNIXes
594  // should use the MSG_NOSIGNAL flag for every send.
595  setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
596 #endif
597 
598  // Set the no-delay option (disable Nagle's algorithm) on the TCP socket.
599  SetSocketNoDelay(hSocket);
600 
601  // Set the non-blocking option on the socket.
602  if (!SetSocketNonBlocking(hSocket, true)) {
603  CloseSocket(hSocket);
604  LogPrintf("CreateSocket: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
605  }
606  return hSocket;
607 }
608 
609 template<typename... Args>
610 static void LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args) {
611  std::string error_message = tfm::format(fmt, args...);
612  if (manual_connection) {
613  LogPrintf("%s\n", error_message);
614  } else {
615  LogPrint(BCLog::NET, "%s\n", error_message);
616  }
617 }
618 
631 bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout, bool manual_connection)
632 {
633  // Create a sockaddr from the specified service.
634  struct sockaddr_storage sockaddr;
635  socklen_t len = sizeof(sockaddr);
636  if (hSocket == INVALID_SOCKET) {
637  LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString());
638  return false;
639  }
640  if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
641  LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
642  return false;
643  }
644 
645  // Connect to the addrConnect service on the hSocket socket.
646  if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
647  {
648  int nErr = WSAGetLastError();
649  // WSAEINVAL is here because some legacy version of winsock uses it
650  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
651  {
652  // Connection didn't actually fail, but is being established
653  // asynchronously. Thus, use async I/O api (select/poll)
654  // synchronously to check for successful connection with a timeout.
655 #ifdef USE_POLL
656  struct pollfd pollfd = {};
657  pollfd.fd = hSocket;
658  pollfd.events = POLLIN | POLLOUT;
659  int nRet = poll(&pollfd, 1, nTimeout);
660 #else
661  struct timeval timeout = MillisToTimeval(nTimeout);
662  fd_set fdset;
663  FD_ZERO(&fdset);
664  FD_SET(hSocket, &fdset);
665  int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout);
666 #endif
667  // Upon successful completion, both select and poll return the total
668  // number of file descriptors that have been selected. A value of 0
669  // indicates that the call timed out and no file descriptors have
670  // been selected.
671  if (nRet == 0)
672  {
673  LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
674  return false;
675  }
676  if (nRet == SOCKET_ERROR)
677  {
678  LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
679  return false;
680  }
681 
682  // Even if the select/poll was successful, the connect might not
683  // have been successful. The reason for this failure is hidden away
684  // in the SO_ERROR for the socket in modern systems. We read it into
685  // nRet here.
686  socklen_t nRetSize = sizeof(nRet);
687  if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (sockopt_arg_type)&nRet, &nRetSize) == SOCKET_ERROR)
688  {
689  LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
690  return false;
691  }
692  if (nRet != 0)
693  {
694  LogConnectFailure(manual_connection, "connect() to %s failed after select(): %s", addrConnect.ToString(), NetworkErrorString(nRet));
695  return false;
696  }
697  }
698 #ifdef WIN32
699  else if (WSAGetLastError() != WSAEISCONN)
700 #else
701  else
702 #endif
703  {
704  LogConnectFailure(manual_connection, "connect() to %s failed: %s", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
705  return false;
706  }
707  }
708  return true;
709 }
710 
711 bool SetProxy(enum Network net, const proxyType &addrProxy) {
712  assert(net >= 0 && net < NET_MAX);
713  if (!addrProxy.IsValid())
714  return false;
715  LOCK(g_proxyinfo_mutex);
716  proxyInfo[net] = addrProxy;
717  return true;
718 }
719 
720 bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
721  assert(net >= 0 && net < NET_MAX);
722  LOCK(g_proxyinfo_mutex);
723  if (!proxyInfo[net].IsValid())
724  return false;
725  proxyInfoOut = proxyInfo[net];
726  return true;
727 }
728 
745 bool SetNameProxy(const proxyType &addrProxy) {
746  if (!addrProxy.IsValid())
747  return false;
748  LOCK(g_proxyinfo_mutex);
749  nameProxy = addrProxy;
750  return true;
751 }
752 
753 bool GetNameProxy(proxyType &nameProxyOut) {
754  LOCK(g_proxyinfo_mutex);
755  if(!nameProxy.IsValid())
756  return false;
757  nameProxyOut = nameProxy;
758  return true;
759 }
760 
762  LOCK(g_proxyinfo_mutex);
763  return nameProxy.IsValid();
764 }
765 
766 bool IsProxy(const CNetAddr &addr) {
767  LOCK(g_proxyinfo_mutex);
768  for (int i = 0; i < NET_MAX; i++) {
769  if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy))
770  return true;
771  }
772  return false;
773 }
774 
790 bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocket, int nTimeout, bool& outProxyConnectionFailed)
791 {
792  // first connect to proxy server
793  if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout, true)) {
794  outProxyConnectionFailed = true;
795  return false;
796  }
797  // do socks negotiation
798  if (proxy.randomize_credentials) {
799  ProxyCredentials random_auth;
800  static std::atomic_int counter(0);
801  random_auth.username = random_auth.password = strprintf("%i", counter++);
802  if (!Socks5(strDest, (uint16_t)port, &random_auth, hSocket)) {
803  return false;
804  }
805  } else {
806  if (!Socks5(strDest, (uint16_t)port, 0, hSocket)) {
807  return false;
808  }
809  }
810  return true;
811 }
812 
824 bool LookupSubNet(const std::string& strSubnet, CSubNet& ret)
825 {
826  if (!ValidAsCString(strSubnet)) {
827  return false;
828  }
829  size_t slash = strSubnet.find_last_of('/');
830  std::vector<CNetAddr> vIP;
831 
832  std::string strAddress = strSubnet.substr(0, slash);
833  // TODO: Use LookupHost(const std::string&, CNetAddr&, bool) instead to just get
834  // one CNetAddr.
835  if (LookupHost(strAddress, vIP, 1, false))
836  {
837  CNetAddr network = vIP[0];
838  if (slash != strSubnet.npos)
839  {
840  std::string strNetmask = strSubnet.substr(slash + 1);
841  int32_t n;
842  if (ParseInt32(strNetmask, &n)) {
843  // If valid number, assume CIDR variable-length subnet masking
844  ret = CSubNet(network, n);
845  return ret.IsValid();
846  }
847  else // If not a valid number, try full netmask syntax
848  {
849  // Never allow lookup for netmask
850  if (LookupHost(strNetmask, vIP, 1, false)) {
851  ret = CSubNet(network, vIP[0]);
852  return ret.IsValid();
853  }
854  }
855  }
856  else
857  {
858  ret = CSubNet(network);
859  return ret.IsValid();
860  }
861  }
862  return false;
863 }
864 
865 #ifdef WIN32
866 std::string NetworkErrorString(int err)
867 {
868  wchar_t buf[256];
869  buf[0] = 0;
870  if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
871  nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
872  buf, ARRAYSIZE(buf), nullptr))
873  {
874  return strprintf("%s (%d)", std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().to_bytes(buf), err);
875  }
876  else
877  {
878  return strprintf("Unknown error (%d)", err);
879  }
880 }
881 #else
882 std::string NetworkErrorString(int err)
883 {
884  char buf[256];
885  buf[0] = 0;
886  /* Too bad there are two incompatible implementations of the
887  * thread-safe strerror. */
888  const char *s;
889 #ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */
890  s = strerror_r(err, buf, sizeof(buf));
891 #else /* POSIX variant always returns message in buffer */
892  s = buf;
893  if (strerror_r(err, buf, sizeof(buf)))
894  buf[0] = 0;
895 #endif
896  return strprintf("%s (%d)", s, err);
897 }
898 #endif
899 
900 bool CloseSocket(SOCKET& hSocket)
901 {
902  if (hSocket == INVALID_SOCKET)
903  return false;
904 #ifdef WIN32
905  int ret = closesocket(hSocket);
906 #else
907  int ret = close(hSocket);
908 #endif
909  if (ret) {
910  LogPrintf("Socket close failed: %d. Error: %s\n", hSocket, NetworkErrorString(WSAGetLastError()));
911  }
912  hSocket = INVALID_SOCKET;
913  return ret != SOCKET_ERROR;
914 }
915 
916 bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking)
917 {
918  if (fNonBlocking) {
919 #ifdef WIN32
920  u_long nOne = 1;
921  if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
922 #else
923  int fFlags = fcntl(hSocket, F_GETFL, 0);
924  if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
925 #endif
926  return false;
927  }
928  } else {
929 #ifdef WIN32
930  u_long nZero = 0;
931  if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
932 #else
933  int fFlags = fcntl(hSocket, F_GETFL, 0);
934  if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
935 #endif
936  return false;
937  }
938  }
939 
940  return true;
941 }
942 
943 bool SetSocketNoDelay(const SOCKET& hSocket)
944 {
945  int set = 1;
946  int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int));
947  return rc == 0;
948 }
949 
950 void InterruptSocks5(bool interrupt)
951 {
952  interruptSocks5Recv = interrupt;
953 }
#define WSAEINPROGRESS
Definition: compat.h:56
Connection refused.
Definition: netbase.cpp:303
SOCKS5Reply
Values defined for REP in RFC1928.
Definition: netbase.cpp:297
bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET &hSocket, int nTimeout, bool manual_connection)
Try to connect to the specified service on the specified socket.
Definition: netbase.cpp:631
CService LookupNumeric(const std::string &name, int portDefault)
Resolve a service string with a numeric IP to its first corresponding service.
Definition: netbase.cpp:254
std::string ToLower(const std::string &str)
Returns the lowercase equivalent of the given string.
#define LogPrint(category,...)
Definition: logging.h:182
Username/password.
Definition: netbase.cpp:285
Dummy value to indicate the number of NET_* constants.
Definition: netaddress.h:49
static bool IsSelectableSocket(const SOCKET &s)
Definition: compat.h:98
static Mutex g_proxyinfo_mutex
Definition: netbase.cpp:32
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:57
GSSAPI.
Definition: netbase.cpp:284
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
static IntrRecvError InterruptibleRecv(uint8_t *data, size_t len, int timeout, const SOCKET &hSocket)
Try to read a specified number of bytes from a socket.
Definition: netbase.cpp:343
NODISCARD bool ValidAsCString(const std::string &str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
Definition: string.h:60
IPv4.
Definition: netaddress.h:34
static proxyType proxyInfo [NET_MAX] GUARDED_BY(g_proxyinfo_mutex)
Network unreachable.
Definition: netbase.cpp:301
static void LogConnectFailure(bool manual_connection, const char *fmt, const Args &... args)
Definition: netbase.cpp:610
void * sockopt_arg_type
Definition: compat.h:86
bool GetNameProxy(proxyType &nameProxyOut)
Definition: netbase.cpp:753
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:166
bool IsInternal() const
Definition: netaddress.cpp:325
#define INVALID_SOCKET
Definition: compat.h:59
bool SetNameProxy(const proxyType &addrProxy)
Set the name proxy to use for all connections to nodes specified by a hostname.
Definition: netbase.cpp:745
#define WSAGetLastError()
Definition: compat.h:50
No authentication required.
Definition: netbase.cpp:283
SOCKS5Command
Values defined for CMD in RFC1928.
Definition: netbase.cpp:290
static const int SOCKS5_RECV_TIMEOUT
Definition: netbase.cpp:39
bool ConnectThroughProxy(const proxyType &proxy, const std::string &strDest, int port, const SOCKET &hSocket, int nTimeout, bool &outProxyConnectionFailed)
Connect to a specified destination service through a SOCKS5 proxy by first connecting to the SOCKS5 p...
Definition: netbase.cpp:790
bool LookupSubNet(const std::string &strSubnet, CSubNet &ret)
Parse and resolve a specified subnet string into the appropriate internal representation.
Definition: netbase.cpp:824
bool Lookup(const std::string &name, std::vector< CService > &vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
Resolve a service string to its corresponding service.
Definition: netbase.cpp:206
bool HaveNameProxy()
Definition: netbase.cpp:761
#define SOCKET_ERROR
Definition: compat.h:60
bool randomize_credentials
Definition: netbase.h:37
No acceptable methods.
Definition: netbase.cpp:286
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Obtain the IPv4/6 socket address this represents.
Definition: netaddress.cpp:701
#define LOCK(cs)
Definition: sync.h:228
const char * name
Definition: rest.cpp:41
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:196
void format(std::ostream &out, const char *fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1062
Credentials for proxy authentication.
Definition: netbase.cpp:393
IntrRecvError
Status codes that can be returned by InterruptibleRecv.
Definition: netbase.cpp:317
static bool LookupIntern(const std::string &name, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:64
bool IsProxy(const CNetAddr &addr)
Definition: netbase.cpp:766
bool ParseInt32(const std::string &str, int32_t *out)
Convert string to signed 32-bit integer with strict parse error feedback.
SOCKSVersion
SOCKS version.
Definition: netbase.cpp:276
General failure.
Definition: netbase.cpp:299
Network
A network type.
Definition: netaddress.h:28
static std::atomic< bool > interruptSocks5Recv(false)
static const int DEFAULT_NAME_LOOKUP
-dns default
Definition: netbase.h:26
static bool Socks5(const std::string &strDest, int port, const ProxyCredentials *auth, const SOCKET &hSocket)
Connect to a specified destination service through an already connected SOCKS5 proxy.
Definition: netbase.cpp:442
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
Definition: netbase.cpp:900
int nConnectTimeout
Definition: netbase.cpp:35
#define WSAEWOULDBLOCK
Definition: compat.h:53
static std::string Socks5ErrorString(uint8_t err)
Convert SOCKS5 reply to an error message.
Definition: netbase.cpp:400
SOCKS5Method
Values defined for METHOD in RFC1928.
Definition: netbase.cpp:282
unsigned int SOCKET
Definition: compat.h:48
bool SetProxy(enum Network net, const proxyType &addrProxy)
Definition: netbase.cpp:711
bool SetSocketNonBlocking(const SOCKET &hSocket, bool fNonBlocking)
Disable or enable blocking-mode for a socket.
Definition: netbase.cpp:916
enum Network ParseNetwork(const std::string &net_in)
Definition: netbase.cpp:42
struct timeval MillisToTimeval(int64_t nTimeout)
Convert milliseconds to a struct timeval for e.g.
Definition: netbase.cpp:267
Network address.
Definition: netaddress.h:55
bool LookupHost(const std::string &name, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Resolve a host string to its corresponding network addresses.
Definition: netbase.cpp:152
Network unreachable.
Definition: netbase.cpp:302
bool IsValid() const
Definition: netaddress.cpp:889
CService proxy
Definition: netbase.h:36
bool IsValid() const
Definition: netbase.h:34
TTL expired.
Definition: netbase.cpp:304
#define WSAEINVAL
Definition: compat.h:51
bool SetSocketNoDelay(const SOCKET &hSocket)
Set the TCP_NODELAY flag on a socket.
Definition: netbase.cpp:943
#define MSG_NOSIGNAL
Definition: netbase.cpp:28
static const int DEFAULT_CONNECT_TIMEOUT
-timeout default
Definition: netbase.h:24
IPv6.
Definition: netaddress.h:37
SOCKET CreateSocket(const CService &addrConnect)
Try to create a socket file descriptor with specific properties in the communications domain (address...
Definition: netbase.cpp:568
TORv2.
Definition: netaddress.h:40
Succeeded.
Definition: netbase.cpp:298
bool SetSpecial(const std::string &strName)
Try to make this a dummy address that maps the specified onion address into IPv6 using OnionCat&#39;s ran...
Definition: netaddress.cpp:103
void InterruptSocks5(bool interrupt)
Definition: netbase.cpp:950
std::string password
Definition: netbase.cpp:396
std::string ToString() const
Definition: netaddress.cpp:756
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:720
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
Definition: netbase.cpp:882
Address type not supported.
Definition: netbase.cpp:306
Command not supported.
Definition: netbase.cpp:305
Connection not allowed by ruleset.
Definition: netbase.cpp:300
std::string GetNetworkName(enum Network net)
Definition: netbase.cpp:54
std::string username
Definition: netbase.cpp:395
SOCKS5Atyp
Values defined for ATYPE in RFC1928.
Definition: netbase.cpp:310
bool error(const char *fmt, const Args &... args)
Definition: system.h:52
bool fNameLookup
Definition: netbase.cpp:36
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
Addresses from these networks are not publicly routable on the global Internet.
Definition: netaddress.h:31