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