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