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