Bitcoin ABC  0.24.7
P2P Digital Currency
netbase.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 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 #endif
20 
21 #ifdef USE_POLL
22 #include <poll.h>
23 #endif
24 
25 #if !defined(MSG_NOSIGNAL)
26 #define MSG_NOSIGNAL 0
27 #endif
28 
29 // Settings
32 static proxyType nameProxy GUARDED_BY(g_proxyinfo_mutex);
35 
36 // Need ample time for negotiation for very slow proxies such as Tor
37 // (milliseconds)
38 static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
39 static std::atomic<bool> interruptSocks5Recv(false);
40 
41 enum Network ParseNetwork(const std::string &net_in) {
42  std::string net = ToLower(net_in);
43  if (net == "ipv4") {
44  return NET_IPV4;
45  }
46  if (net == "ipv6") {
47  return NET_IPV6;
48  }
49  if (net == "onion") {
50  return NET_ONION;
51  }
52  if (net == "tor") {
53  LogPrintf("Warning: net name 'tor' is deprecated and will be removed "
54  "in the future. You should use 'onion' instead.\n");
55  return NET_ONION;
56  }
57  return NET_UNROUTABLE;
58 }
59 
60 std::string GetNetworkName(enum Network net) {
61  switch (net) {
62  case NET_IPV4:
63  return "ipv4";
64  case NET_IPV6:
65  return "ipv6";
66  case NET_ONION:
67  return "onion";
68  default:
69  return "";
70  }
71 }
72 
73 static bool LookupIntern(const std::string &name, std::vector<CNetAddr> &vIP,
74  unsigned int nMaxSolutions, bool fAllowLookup) {
75  vIP.clear();
76 
77  if (!ValidAsCString(name)) {
78  return false;
79  }
80 
81  {
82  CNetAddr addr;
83  // From our perspective, onion addresses are not hostnames but rather
84  // direct encodings of CNetAddr much like IPv4 dotted-decimal notation
85  // or IPv6 colon-separated hextet notation. Since we can't use
86  // getaddrinfo to decode them and it wouldn't make sense to resolve
87  // them, we return a network address representing it instead. See
88  // CNetAddr::SetSpecial(const std::string&) for more details.
89  if (addr.SetSpecial(name)) {
90  vIP.push_back(addr);
91  return true;
92  }
93  }
94 
95  struct addrinfo aiHint;
96  memset(&aiHint, 0, sizeof(struct addrinfo));
97 
98  // We want a TCP port, which is a streaming socket type
99  aiHint.ai_socktype = SOCK_STREAM;
100  aiHint.ai_protocol = IPPROTO_TCP;
101  // We don't care which address family (IPv4 or IPv6) is returned
102  aiHint.ai_family = AF_UNSPEC;
103  // If we allow lookups of hostnames, use the AI_ADDRCONFIG flag to only
104  // return addresses whose family we have an address configured for.
105  //
106  // If we don't allow lookups, then use the AI_NUMERICHOST flag for
107  // getaddrinfo to only decode numerical network addresses and suppress
108  // hostname lookups.
109  aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
110  struct addrinfo *aiRes = nullptr;
111  int nErr = getaddrinfo(name.c_str(), nullptr, &aiHint, &aiRes);
112  if (nErr) {
113  return false;
114  }
115 
116  // Traverse the linked list starting with aiTrav, add all non-internal
117  // IPv4,v6 addresses to vIP while respecting nMaxSolutions.
118  struct addrinfo *aiTrav = aiRes;
119  while (aiTrav != nullptr &&
120  (nMaxSolutions == 0 || vIP.size() < nMaxSolutions)) {
121  CNetAddr resolved;
122  if (aiTrav->ai_family == AF_INET) {
123  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
124  resolved =
125  CNetAddr(reinterpret_cast<struct sockaddr_in *>(aiTrav->ai_addr)
126  ->sin_addr);
127  }
128 
129  if (aiTrav->ai_family == AF_INET6) {
130  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
131  struct sockaddr_in6 *s6 =
132  reinterpret_cast<struct sockaddr_in6 *>(aiTrav->ai_addr);
133  resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id);
134  }
135 
136  // Never allow resolving to an internal address. Consider any such
137  // result invalid.
138  if (!resolved.IsInternal()) {
139  vIP.push_back(resolved);
140  }
141 
142  aiTrav = aiTrav->ai_next;
143  }
144 
145  freeaddrinfo(aiRes);
146 
147  return (vIP.size() > 0);
148 }
149 
165 bool LookupHost(const std::string &name, std::vector<CNetAddr> &vIP,
166  unsigned int nMaxSolutions, bool fAllowLookup) {
167  if (!ValidAsCString(name)) {
168  return false;
169  }
170  std::string strHost = name;
171  if (strHost.empty()) {
172  return false;
173  }
174  if (strHost.front() == '[' && strHost.back() == ']') {
175  strHost = strHost.substr(1, strHost.size() - 2);
176  }
177 
178  return LookupIntern(strHost, vIP, nMaxSolutions, fAllowLookup);
179 }
180 
187 bool LookupHost(const std::string &name, CNetAddr &addr, bool fAllowLookup) {
188  if (!ValidAsCString(name)) {
189  return false;
190  }
191  std::vector<CNetAddr> vIP;
192  LookupHost(name, vIP, 1, fAllowLookup);
193  if (vIP.empty()) {
194  return false;
195  }
196  addr = vIP.front();
197  return true;
198 }
199 
220 bool Lookup(const std::string &name, std::vector<CService> &vAddr,
221  int portDefault, bool fAllowLookup, unsigned int nMaxSolutions) {
222  if (name.empty() || !ValidAsCString(name)) {
223  return false;
224  }
225  int port = portDefault;
226  std::string hostname;
227  SplitHostPort(name, port, hostname);
228 
229  std::vector<CNetAddr> vIP;
230  bool fRet = LookupIntern(hostname, vIP, nMaxSolutions, fAllowLookup);
231  if (!fRet) {
232  return false;
233  }
234  vAddr.resize(vIP.size());
235  for (unsigned int i = 0; i < vIP.size(); i++) {
236  vAddr[i] = CService(vIP[i], port);
237  }
238  return true;
239 }
240 
247 bool Lookup(const std::string &name, CService &addr, int portDefault,
248  bool fAllowLookup) {
249  if (!ValidAsCString(name)) {
250  return false;
251  }
252  std::vector<CService> vService;
253  bool fRet = Lookup(name, vService, portDefault, fAllowLookup, 1);
254  if (!fRet) {
255  return false;
256  }
257  addr = vService[0];
258  return true;
259 }
260 
271 CService LookupNumeric(const std::string &name, int portDefault) {
272  if (!ValidAsCString(name)) {
273  return {};
274  }
275  CService addr;
276  // "1.2:345" will fail to resolve the ip, but will still set the port.
277  // If the ip fails to resolve, re-init the result.
278  if (!Lookup(name, addr, portDefault, false)) {
279  addr = CService();
280  }
281  return addr;
282 }
283 
284 struct timeval MillisToTimeval(int64_t nTimeout) {
285  struct timeval timeout;
286  timeout.tv_sec = nTimeout / 1000;
287  timeout.tv_usec = (nTimeout % 1000) * 1000;
288  return timeout;
289 }
290 
292 enum SOCKSVersion : uint8_t { SOCKS4 = 0x04, SOCKS5 = 0x05 };
293 
295 enum SOCKS5Method : uint8_t {
296  NOAUTH = 0x00,
297  GSSAPI = 0x01,
298  USER_PASS = 0x02,
299  NO_ACCEPTABLE = 0xff,
300 };
301 
303 enum SOCKS5Command : uint8_t {
304  CONNECT = 0x01,
305  BIND = 0x02,
307 };
308 
310 enum SOCKS5Reply : uint8_t {
311  SUCCEEDED = 0x00,
312  GENFAILURE = 0x01,
313  NOTALLOWED = 0x02,
314  NETUNREACHABLE = 0x03,
316  CONNREFUSED = 0x05,
317  TTLEXPIRED = 0x06,
318  CMDUNSUPPORTED = 0x07,
320 };
321 
323 enum SOCKS5Atyp : uint8_t {
324  IPV4 = 0x01,
325  DOMAINNAME = 0x03,
326  IPV6 = 0x04,
327 };
328 
330 enum class IntrRecvError {
331  OK,
332  Timeout,
333  Disconnected,
334  NetworkError,
336 };
337 
356 static IntrRecvError InterruptibleRecv(uint8_t *data, size_t len, int timeout,
357  const SOCKET &hSocket) {
358  int64_t curTime = GetTimeMillis();
359  int64_t endTime = curTime + timeout;
360  // Maximum time to wait for I/O readiness. It will take up until this time
361  // (in millis) to break off in case of an interruption.
362  const int64_t maxWait = 1000;
363  while (len > 0 && curTime < endTime) {
364  // Optimistically try the recv first
365  ssize_t ret = recv(hSocket, (char *)data, len, 0);
366  if (ret > 0) {
367  len -= ret;
368  data += ret;
369  } else if (ret == 0) {
370  // Unexpected disconnection
372  } else {
373  // Other error or blocking
374  int nErr = WSAGetLastError();
375  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK ||
376  nErr == WSAEINVAL) {
377  if (!IsSelectableSocket(hSocket)) {
379  }
380  // Only wait at most maxWait milliseconds at a time, unless
381  // we're approaching the end of the specified total timeout
382  int timeout_ms = std::min(endTime - curTime, maxWait);
383 #ifdef USE_POLL
384  struct pollfd pollfd = {};
385  pollfd.fd = hSocket;
386  pollfd.events = POLLIN;
387  int nRet = poll(&pollfd, 1, timeout_ms);
388 #else
389  struct timeval tval = MillisToTimeval(timeout_ms);
390  fd_set fdset;
391  FD_ZERO(&fdset);
392  FD_SET(hSocket, &fdset);
393  int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval);
394 #endif
395  if (nRet == SOCKET_ERROR) {
397  }
398  } else {
400  }
401  }
402  if (interruptSocks5Recv) {
404  }
405  curTime = GetTimeMillis();
406  }
407  return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
408 }
409 
412  std::string username;
413  std::string password;
414 };
415 
417 static std::string Socks5ErrorString(uint8_t err) {
418  switch (err) {
420  return "general failure";
422  return "connection not allowed";
424  return "network unreachable";
426  return "host unreachable";
428  return "connection refused";
430  return "TTL expired";
432  return "protocol error";
434  return "address type not supported";
435  default:
436  return "unknown";
437  }
438 }
439 
458 static bool Socks5(const std::string &strDest, int port,
459  const ProxyCredentials *auth, const SOCKET &hSocket) {
460  IntrRecvError recvr;
461  LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
462  if (strDest.size() > 255) {
463  return error("Hostname too long");
464  }
465  // Construct the version identifier/method selection message
466  std::vector<uint8_t> vSocks5Init;
467  // We want the SOCK5 protocol
468  vSocks5Init.push_back(SOCKSVersion::SOCKS5);
469  if (auth) {
470  // 2 method identifiers follow...
471  vSocks5Init.push_back(0x02);
472  vSocks5Init.push_back(SOCKS5Method::NOAUTH);
473  vSocks5Init.push_back(SOCKS5Method::USER_PASS);
474  } else {
475  // 1 method identifier follows...
476  vSocks5Init.push_back(0x01);
477  vSocks5Init.push_back(SOCKS5Method::NOAUTH);
478  }
479  ssize_t ret = send(hSocket, (const char *)vSocks5Init.data(),
480  vSocks5Init.size(), MSG_NOSIGNAL);
481  if (ret != (ssize_t)vSocks5Init.size()) {
482  return error("Error sending to proxy");
483  }
484  uint8_t pchRet1[2];
485  if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) !=
487  LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() "
488  "timeout or other failure\n",
489  strDest, port);
490  return false;
491  }
492  if (pchRet1[0] != SOCKSVersion::SOCKS5) {
493  return error("Proxy failed to initialize");
494  }
495  if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
496  // Perform username/password authentication (as described in RFC1929)
497  std::vector<uint8_t> vAuth;
498  // Current (and only) version of user/pass subnegotiation
499  vAuth.push_back(0x01);
500  if (auth->username.size() > 255 || auth->password.size() > 255) {
501  return error("Proxy username or password too long");
502  }
503  vAuth.push_back(auth->username.size());
504  vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
505  vAuth.push_back(auth->password.size());
506  vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
507  ret = send(hSocket, (const char *)vAuth.data(), vAuth.size(),
508  MSG_NOSIGNAL);
509  if (ret != (ssize_t)vAuth.size()) {
510  return error("Error sending authentication to proxy");
511  }
512  LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n",
513  auth->username, auth->password);
514  uint8_t pchRetA[2];
515  if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT,
516  hSocket)) != IntrRecvError::OK) {
517  return error("Error reading proxy authentication response");
518  }
519  if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
520  return error("Proxy authentication unsuccessful");
521  }
522  } else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
523  // Perform no authentication
524  } else {
525  return error("Proxy requested wrong authentication method %02x",
526  pchRet1[1]);
527  }
528  std::vector<uint8_t> vSocks5;
529  // VER protocol version
530  vSocks5.push_back(SOCKSVersion::SOCKS5);
531  // CMD CONNECT
532  vSocks5.push_back(SOCKS5Command::CONNECT);
533  // RSV Reserved must be 0
534  vSocks5.push_back(0x00);
535  // ATYP DOMAINNAME
536  vSocks5.push_back(SOCKS5Atyp::DOMAINNAME);
537  // Length<=255 is checked at beginning of function
538  vSocks5.push_back(strDest.size());
539  vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
540  vSocks5.push_back((port >> 8) & 0xFF);
541  vSocks5.push_back((port >> 0) & 0xFF);
542  ret = send(hSocket, (const char *)vSocks5.data(), vSocks5.size(),
543  MSG_NOSIGNAL);
544  if (ret != (ssize_t)vSocks5.size()) {
545  return error("Error sending to proxy");
546  }
547  uint8_t pchRet2[4];
548  if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) !=
550  if (recvr == IntrRecvError::Timeout) {
556  return false;
557  } else {
558  return error("Error while reading proxy response");
559  }
560  }
561  if (pchRet2[0] != SOCKSVersion::SOCKS5) {
562  return error("Proxy failed to accept request");
563  }
564  if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
565  // Failures to connect to a peer that are not proxy errors
566  LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port,
567  Socks5ErrorString(pchRet2[1]));
568  return false;
569  }
570  // Reserved field must be 0
571  if (pchRet2[2] != 0x00) {
572  return error("Error: malformed proxy response");
573  }
574  uint8_t pchRet3[256];
575  switch (pchRet2[3]) {
576  case SOCKS5Atyp::IPV4:
577  recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket);
578  break;
579  case SOCKS5Atyp::IPV6:
580  recvr =
581  InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket);
582  break;
583  case SOCKS5Atyp::DOMAINNAME: {
584  recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
585  if (recvr != IntrRecvError::OK) {
586  return error("Error reading from proxy");
587  }
588  int nRecv = pchRet3[0];
589  recvr =
590  InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
591  break;
592  }
593  default:
594  return error("Error: malformed proxy response");
595  }
596  if (recvr != IntrRecvError::OK) {
597  return error("Error reading from proxy");
598  }
599  if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) !=
601  return error("Error reading from proxy");
602  }
603  LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
604  return true;
605 }
606 
614 SOCKET CreateSocket(const CService &addrConnect) {
615  // Create a sockaddr from the specified service.
616  struct sockaddr_storage sockaddr;
617  socklen_t len = sizeof(sockaddr);
618  if (!addrConnect.GetSockAddr((struct sockaddr *)&sockaddr, &len)) {
619  LogPrintf("Cannot create socket for %s: unsupported network\n",
620  addrConnect.ToString());
621  return INVALID_SOCKET;
622  }
623 
624  // Create a TCP socket in the address family of the specified service.
625  SOCKET hSocket = socket(((struct sockaddr *)&sockaddr)->sa_family,
626  SOCK_STREAM, IPPROTO_TCP);
627  if (hSocket == INVALID_SOCKET) {
628  return INVALID_SOCKET;
629  }
630 
631  // Ensure that waiting for I/O on this socket won't result in undefined
632  // behavior.
633  if (!IsSelectableSocket(hSocket)) {
634  CloseSocket(hSocket);
635  LogPrintf("Cannot create connection: non-selectable socket created (fd "
636  ">= FD_SETSIZE ?)\n");
637  return INVALID_SOCKET;
638  }
639 
640 #ifdef SO_NOSIGPIPE
641  int set = 1;
642  // Set the no-sigpipe option on the socket for BSD systems, other UNIXes
643  // should use the MSG_NOSIGNAL flag for every send.
644  setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (sockopt_arg_type)&set,
645  sizeof(int));
646 #endif
647 
648  // Set the no-delay option (disable Nagle's algorithm) on the TCP socket.
649  SetSocketNoDelay(hSocket);
650 
651  // Set the non-blocking option on the socket.
652  if (!SetSocketNonBlocking(hSocket, true)) {
653  CloseSocket(hSocket);
654  LogPrintf("CreateSocket: Setting socket to non-blocking "
655  "failed, error %s\n",
657  }
658  return hSocket;
659 }
660 
661 template <typename... Args>
662 static void LogConnectFailure(bool manual_connection, const char *fmt,
663  const Args &... args) {
664  std::string error_message = tfm::format(fmt, args...);
665  if (manual_connection) {
666  LogPrintf("%s\n", error_message);
667  } else {
668  LogPrint(BCLog::NET, "%s\n", error_message);
669  }
670 }
671 
684 bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET &hSocket,
685  int nTimeout, bool manual_connection) {
686  // Create a sockaddr from the specified service.
687  struct sockaddr_storage sockaddr;
688  socklen_t len = sizeof(sockaddr);
689  if (hSocket == INVALID_SOCKET) {
690  LogPrintf("Cannot connect to %s: invalid socket\n",
691  addrConnect.ToString());
692  return false;
693  }
694  if (!addrConnect.GetSockAddr((struct sockaddr *)&sockaddr, &len)) {
695  LogPrintf("Cannot connect to %s: unsupported network\n",
696  addrConnect.ToString());
697  return false;
698  }
699 
700  // Connect to the addrConnect service on the hSocket socket.
701  if (connect(hSocket, (struct sockaddr *)&sockaddr, len) == SOCKET_ERROR) {
702  int nErr = WSAGetLastError();
703  // WSAEINVAL is here because some legacy version of winsock uses it
704  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK ||
705  nErr == WSAEINVAL) {
706  // Connection didn't actually fail, but is being established
707  // asynchronously. Thus, use async I/O api (select/poll)
708  // synchronously to check for successful connection with a timeout.
709 #ifdef USE_POLL
710  struct pollfd pollfd = {};
711  pollfd.fd = hSocket;
712  pollfd.events = POLLIN | POLLOUT;
713  int nRet = poll(&pollfd, 1, nTimeout);
714 #else
715  struct timeval timeout = MillisToTimeval(nTimeout);
716  fd_set fdset;
717  FD_ZERO(&fdset);
718  FD_SET(hSocket, &fdset);
719  int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout);
720 #endif
721  // Upon successful completion, both select and poll return the total
722  // number of file descriptors that have been selected. A value of 0
723  // indicates that the call timed out and no file descriptors have
724  // been selected.
725  if (nRet == 0) {
726  LogPrint(BCLog::NET, "connection to %s timeout\n",
727  addrConnect.ToString());
728  return false;
729  }
730  if (nRet == SOCKET_ERROR) {
731  LogPrintf("select() for %s failed: %s\n",
732  addrConnect.ToString(),
734  return false;
735  }
736 
737  // Even if the select/poll was successful, the connect might not
738  // have been successful. The reason for this failure is hidden away
739  // in the SO_ERROR for the socket in modern systems. We read it into
740  // nRet here.
741  socklen_t nRetSize = sizeof(nRet);
742  if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR,
743  (sockopt_arg_type)&nRet,
744  &nRetSize) == SOCKET_ERROR) {
745  LogPrintf("getsockopt() for %s failed: %s\n",
746  addrConnect.ToString(),
748  return false;
749  }
750  if (nRet != 0) {
751  LogConnectFailure(manual_connection,
752  "connect() to %s failed after select(): %s",
753  addrConnect.ToString(),
754  NetworkErrorString(nRet));
755  return false;
756  }
757  }
758 #ifdef WIN32
759  else if (WSAGetLastError() != WSAEISCONN)
760 #else
761  else
762 #endif
763  {
764  LogConnectFailure(manual_connection, "connect() to %s failed: %s",
765  addrConnect.ToString(),
767  return false;
768  }
769  }
770  return true;
771 }
772 
773 bool SetProxy(enum Network net, const proxyType &addrProxy) {
774  assert(net >= 0 && net < NET_MAX);
775  if (!addrProxy.IsValid()) {
776  return false;
777  }
779  proxyInfo[net] = addrProxy;
780  return true;
781 }
782 
783 bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
784  assert(net >= 0 && net < NET_MAX);
786  if (!proxyInfo[net].IsValid()) {
787  return false;
788  }
789  proxyInfoOut = proxyInfo[net];
790  return true;
791 }
792 
809 bool SetNameProxy(const proxyType &addrProxy) {
810  if (!addrProxy.IsValid()) {
811  return false;
812  }
814  nameProxy = addrProxy;
815  return true;
816 }
817 
818 bool GetNameProxy(proxyType &nameProxyOut) {
820  if (!nameProxy.IsValid()) {
821  return false;
822  }
823  nameProxyOut = nameProxy;
824  return true;
825 }
826 
829  return nameProxy.IsValid();
830 }
831 
832 bool IsProxy(const CNetAddr &addr) {
834  for (int i = 0; i < NET_MAX; i++) {
835  if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy)) {
836  return true;
837  }
838  }
839  return false;
840 }
841 
857 bool ConnectThroughProxy(const proxyType &proxy, const std::string &strDest,
858  int port, const SOCKET &hSocket, int nTimeout,
859  bool &outProxyConnectionFailed) {
860  // first connect to proxy server
861  if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout, true)) {
862  outProxyConnectionFailed = true;
863  return false;
864  }
865  // do socks negotiation
866  if (proxy.randomize_credentials) {
867  ProxyCredentials random_auth;
868  static std::atomic_int counter(0);
869  random_auth.username = random_auth.password =
870  strprintf("%i", counter++);
871  if (!Socks5(strDest, uint16_t(port), &random_auth, hSocket)) {
872  return false;
873  }
874  } else if (!Socks5(strDest, uint16_t(port), 0, hSocket)) {
875  return false;
876  }
877  return true;
878 }
879 
891 bool LookupSubNet(const std::string &strSubnet, CSubNet &ret) {
892  if (!ValidAsCString(strSubnet)) {
893  return false;
894  }
895  size_t slash = strSubnet.find_last_of('/');
896  std::vector<CNetAddr> vIP;
897 
898  std::string strAddress = strSubnet.substr(0, slash);
899  // TODO: Use LookupHost(const std::string&, CNetAddr&, bool) instead to just
900  // get one CNetAddr.
901  if (LookupHost(strAddress, vIP, 1, false)) {
902  CNetAddr network = vIP[0];
903  if (slash != strSubnet.npos) {
904  std::string strNetmask = strSubnet.substr(slash + 1);
905  uint8_t n;
906  if (ParseUInt8(strNetmask, &n)) {
907  // If valid number, assume CIDR variable-length subnet masking
908  ret = CSubNet(network, n);
909  return ret.IsValid();
910  } else {
911  // If not a valid number, try full netmask syntax
912  // Never allow lookup for netmask
913  if (LookupHost(strNetmask, vIP, 1, false)) {
914  ret = CSubNet(network, vIP[0]);
915  return ret.IsValid();
916  }
917  }
918  } else {
919  ret = CSubNet(network);
920  return ret.IsValid();
921  }
922  }
923  return false;
924 }
925 
926 #ifdef WIN32
927 std::string NetworkErrorString(int err) {
928  char buf[256];
929  buf[0] = 0;
930  if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
931  FORMAT_MESSAGE_IGNORE_INSERTS |
932  FORMAT_MESSAGE_MAX_WIDTH_MASK,
933  nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
934  buf, sizeof(buf), nullptr)) {
935  return strprintf("%s (%d)", buf, err);
936  } else {
937  return strprintf("Unknown error (%d)", err);
938  }
939 }
940 #else
941 std::string NetworkErrorString(int err) {
942  char buf[256];
943  buf[0] = 0;
948  const char *s;
949 #ifdef STRERROR_R_CHAR_P
950  /* GNU variant can return a pointer outside the passed buffer */
951  s = strerror_r(err, buf, sizeof(buf));
952 #else
953  s = buf;
954  /* POSIX variant always returns message in buffer */
955  if (strerror_r(err, buf, sizeof(buf))) {
956  buf[0] = 0;
957  }
958 #endif
959  return strprintf("%s (%d)", s, err);
960 }
961 #endif
962 
963 bool CloseSocket(SOCKET &hSocket) {
964  if (hSocket == INVALID_SOCKET) {
965  return false;
966  }
967 #ifdef WIN32
968  int ret = closesocket(hSocket);
969 #else
970  int ret = close(hSocket);
971 #endif
972  if (ret) {
973  LogPrintf("Socket close failed: %d. Error: %s\n", hSocket,
975  }
976  hSocket = INVALID_SOCKET;
977  return ret != SOCKET_ERROR;
978 }
979 
980 bool SetSocketNonBlocking(const SOCKET &hSocket, bool fNonBlocking) {
981  if (fNonBlocking) {
982 #ifdef WIN32
983  u_long nOne = 1;
984  if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
985 #else
986  int fFlags = fcntl(hSocket, F_GETFL, 0);
987  if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
988 #endif
989  return false;
990  }
991  } else {
992 #ifdef WIN32
993  u_long nZero = 0;
994  if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
995 #else
996  int fFlags = fcntl(hSocket, F_GETFL, 0);
997  if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
998 #endif
999  return false;
1000  }
1001  }
1002 
1003  return true;
1004 }
1005 
1006 bool SetSocketNoDelay(const SOCKET &hSocket) {
1007  int set = 1;
1008  int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY,
1009  (sockopt_arg_type)&set, sizeof(int));
1010  return rc == 0;
1011 }
1012 
1013 void InterruptSocks5(bool interrupt) {
1014  interruptSocks5Recv = interrupt;
1015 }
LogConnectFailure
static void LogConnectFailure(bool manual_connection, const char *fmt, const Args &... args)
Definition: netbase.cpp:662
ConnectSocketDirectly
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:684
CService
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:514
CMDUNSUPPORTED
@ CMDUNSUPPORTED
Command not supported.
Definition: netbase.cpp:318
CService::GetSockAddr
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Obtain the IPv4/6 socket address this represents.
Definition: netaddress.cpp:961
SOCKS5Method
SOCKS5Method
Values defined for METHOD in RFC1928.
Definition: netbase.cpp:295
proxyType::IsValid
bool IsValid() const
Definition: netbase.h:35
NET_UNROUTABLE
@ NET_UNROUTABLE
Addresses from these networks are not publicly routable on the global Internet.
Definition: netaddress.h:46
ParseNetwork
enum Network ParseNetwork(const std::string &net_in)
Definition: netbase.cpp:41
tinyformat::format
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:1111
NET_IPV4
@ NET_IPV4
IPv4.
Definition: netaddress.h:49
LookupIntern
static bool LookupIntern(const std::string &name, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:73
IPV4
@ IPV4
Definition: netbase.cpp:324
CONNREFUSED
@ CONNREFUSED
Connection refused.
Definition: netbase.cpp:316
SOCKS5_RECV_TIMEOUT
static const int SOCKS5_RECV_TIMEOUT
Definition: netbase.cpp:38
sync.h
WSAEINPROGRESS
#define WSAEINPROGRESS
Definition: compat.h:52
string.h
USER_PASS
@ USER_PASS
Username/password.
Definition: netbase.cpp:298
CNetAddr
Network address.
Definition: netaddress.h:117
NET_MAX
@ NET_MAX
Dummy value to indicate the number of NET_* constants.
Definition: netaddress.h:68
Socks5
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:458
GUARDED_BY
static proxyType proxyInfo[NET_MAX] GUARDED_BY(g_proxyinfo_mutex)
BIND
@ BIND
Definition: netbase.cpp:305
nConnectTimeout
int nConnectTimeout
Definition: netbase.cpp:33
GetNameProxy
bool GetNameProxy(proxyType &nameProxyOut)
Definition: netbase.cpp:818
NETUNREACHABLE
@ NETUNREACHABLE
Network unreachable.
Definition: netbase.cpp:314
AnnotatedMixin< std::mutex >
IntrRecvError::Disconnected
@ Disconnected
SOCKS5
@ SOCKS5
Definition: netbase.cpp:292
WSAGetLastError
#define WSAGetLastError()
Definition: compat.h:46
SplitHostPort
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
Definition: strencodings.cpp:113
GSSAPI
@ GSSAPI
GSSAPI.
Definition: netbase.cpp:297
NetworkErrorString
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
Definition: netbase.cpp:941
Network
Network
A network type.
Definition: netaddress.h:43
IntrRecvError::Interrupted
@ Interrupted
SOCKS4
@ SOCKS4
Definition: netbase.cpp:292
CNetAddr::IsInternal
bool IsInternal() const
Definition: netaddress.cpp:485
SOCKS5Command
SOCKS5Command
Values defined for CMD in RFC1928.
Definition: netbase.cpp:303
proxyType
Definition: netbase.h:28
InterruptibleRecv
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:356
BCLog::PROXY
@ PROXY
Definition: logging.h:53
tinyformat.h
IPV6
@ IPV6
Definition: netbase.cpp:326
MSG_NOSIGNAL
#define MSG_NOSIGNAL
Definition: netbase.cpp:26
HaveNameProxy
bool HaveNameProxy()
Definition: netbase.cpp:827
WSAEINVAL
#define WSAEINVAL
Definition: compat.h:47
UDP_ASSOCIATE
@ UDP_ASSOCIATE
Definition: netbase.cpp:306
IsProxy
bool IsProxy(const CNetAddr &addr)
Definition: netbase.cpp:832
strencodings.h
CService::ToString
std::string ToString() const
Definition: netaddress.cpp:1020
NO_ACCEPTABLE
@ NO_ACCEPTABLE
No acceptable methods.
Definition: netbase.cpp:299
NOAUTH
@ NOAUTH
No authentication required.
Definition: netbase.cpp:296
Socks5ErrorString
static std::string Socks5ErrorString(uint8_t err)
Convert SOCKS5 reply to an error message.
Definition: netbase.cpp:417
Lookup
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:220
INVALID_SOCKET
#define INVALID_SOCKET
Definition: compat.h:55
MillisToTimeval
struct timeval MillisToTimeval(int64_t nTimeout)
Convert milliseconds to a struct timeval for e.g.
Definition: netbase.cpp:284
IsSelectableSocket
static bool IsSelectableSocket(const SOCKET &s)
Definition: compat.h:97
send
static RPCHelpMan send()
Definition: rpcwallet.cpp:4730
IntrRecvError::NetworkError
@ NetworkError
GENFAILURE
@ GENFAILURE
General failure.
Definition: netbase.cpp:312
ProxyCredentials::password
std::string password
Definition: netbase.cpp:413
SOCKS5Atyp
SOCKS5Atyp
Values defined for ATYPE in RFC1928.
Definition: netbase.cpp:323
fNameLookup
bool fNameLookup
Definition: netbase.cpp:34
CSubNet
Definition: netaddress.h:465
SOCKET_ERROR
#define SOCKET_ERROR
Definition: compat.h:56
IntrRecvError
IntrRecvError
Status codes that can be returned by InterruptibleRecv.
Definition: netbase.cpp:330
SOCKSVersion
SOCKSVersion
SOCKS version.
Definition: netbase.cpp:292
LogPrint
#define LogPrint(category,...)
Definition: logging.h:193
ValidAsCString
NODISCARD bool ValidAsCString(const std::string &str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
Definition: string.h:62
ConnectThroughProxy
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:857
DEFAULT_CONNECT_TIMEOUT
static const int DEFAULT_CONNECT_TIMEOUT
-timeout default
Definition: netbase.h:24
WSAEWOULDBLOCK
#define WSAEWOULDBLOCK
Definition: compat.h:49
ProxyCredentials
Credentials for proxy authentication.
Definition: netbase.cpp:411
SUCCEEDED
@ SUCCEEDED
Succeeded.
Definition: netbase.cpp:311
name
const char * name
Definition: rest.cpp:43
DEFAULT_NAME_LOOKUP
static const int DEFAULT_NAME_LOOKUP
-dns default
Definition: netbase.h:26
system.h
InterruptSocks5
void InterruptSocks5(bool interrupt)
Definition: netbase.cpp:1013
SetProxy
bool SetProxy(enum Network net, const proxyType &addrProxy)
Definition: netbase.cpp:773
CNetAddr::SetSpecial
bool SetSpecial(const std::string &strName)
Parse a TOR address and set this object to it.
Definition: netaddress.cpp:234
strprintf
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
LookupHost
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:165
SetNameProxy
bool SetNameProxy(const proxyType &addrProxy)
Set the name proxy to use for all connections to nodes specified by a hostname.
Definition: netbase.cpp:809
SetSocketNoDelay
bool SetSocketNoDelay(const SOCKET &hSocket)
Set the TCP_NODELAY flag on a socket.
Definition: netbase.cpp:1006
IntrRecvError::Timeout
@ Timeout
proxyType::randomize_credentials
bool randomize_credentials
Definition: netbase.h:38
LOCK
#define LOCK(cs)
Definition: sync.h:241
NET_ONION
@ NET_ONION
TOR (v2 or v3)
Definition: netaddress.h:55
CreateSocket
SOCKET CreateSocket(const CService &addrConnect)
Try to create a socket file descriptor with specific properties in the communications domain (address...
Definition: netbase.cpp:614
TTLEXPIRED
@ TTLEXPIRED
TTL expired.
Definition: netbase.cpp:317
ATYPEUNSUPPORTED
@ ATYPEUNSUPPORTED
Address type not supported.
Definition: netbase.cpp:319
CSubNet::IsValid
bool IsValid() const
Definition: netaddress.cpp:1155
GetProxy
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:783
NET_IPV6
@ NET_IPV6
IPv6.
Definition: netaddress.h:52
sockopt_arg_type
void * sockopt_arg_type
Definition: compat.h:82
SOCKS5Reply
SOCKS5Reply
Values defined for REP in RFC1928.
Definition: netbase.cpp:310
LookupNumeric
CService LookupNumeric(const std::string &name, int portDefault)
Resolve a service string with a numeric IP to its first corresponding service.
Definition: netbase.cpp:271
HOSTUNREACHABLE
@ HOSTUNREACHABLE
Network unreachable.
Definition: netbase.cpp:315
netbase.h
GetNetworkName
std::string GetNetworkName(enum Network net)
Definition: netbase.cpp:60
CONNECT
@ CONNECT
Definition: netbase.cpp:304
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:48
BCLog::NET
@ NET
Definition: logging.h:38
SetSocketNonBlocking
bool SetSocketNonBlocking(const SOCKET &hSocket, bool fNonBlocking)
Disable or enable blocking-mode for a socket.
Definition: netbase.cpp:980
g_proxyinfo_mutex
static Mutex g_proxyinfo_mutex
Definition: netbase.cpp:30
IntrRecvError::OK
@ OK
ParseUInt8
bool ParseUInt8(const std::string &str, uint8_t *out)
Convert decimal string to unsigned 8-bit integer with strict parse error feedback.
Definition: strencodings.cpp:353
NOTALLOWED
@ NOTALLOWED
Connection not allowed by ruleset.
Definition: netbase.cpp:313
ProxyCredentials::username
std::string username
Definition: netbase.cpp:412
LogPrintf
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:175
GetTimeMillis
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:59
proxyType::proxy
CService proxy
Definition: netbase.h:37
LookupSubNet
bool LookupSubNet(const std::string &strSubnet, CSubNet &ret)
Parse and resolve a specified subnet string into the appropriate internal representation.
Definition: netbase.cpp:891
interruptSocks5Recv
static std::atomic< bool > interruptSocks5Recv(false)
SOCKET
unsigned int SOCKET
Definition: compat.h:44
ToLower
std::string ToLower(const std::string &str)
Returns the lowercase equivalent of the given string.
Definition: strencodings.cpp:632
CloseSocket
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
Definition: netbase.cpp:963
DOMAINNAME
@ DOMAINNAME
Definition: netbase.cpp:325