Bitcoin Core  0.18.99
P2P Digital Currency
netbase.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2018 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/system.h>
11 #include <util/strencodings.h>
12 
13 #include <atomic>
14 
15 #ifndef WIN32
16 #include <fcntl.h>
17 #else
18 #include <codecvt>
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
31 static proxyType proxyInfo[NET_MAX] GUARDED_BY(cs_proxyInfos);
32 static proxyType nameProxy GUARDED_BY(cs_proxyInfos);
35 
36 // Need ample time for negotiation for very slow proxies such as Tor (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") return NET_IPV4;
43  if (net == "ipv6") return NET_IPV6;
44  if (net == "onion") return NET_ONION;
45  if (net == "tor") {
46  LogPrintf("Warning: net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.\n");
47  return NET_ONION;
48  }
49  return NET_UNROUTABLE;
50 }
51 
52 std::string GetNetworkName(enum Network net) {
53  switch(net)
54  {
55  case NET_IPV4: return "ipv4";
56  case NET_IPV6: return "ipv6";
57  case NET_ONION: return "onion";
58  default: return "";
59  }
60 }
61 
62 bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
63 {
64  vIP.clear();
65 
66  {
67  CNetAddr addr;
68  // From our perspective, onion addresses are not hostnames but rather
69  // direct encodings of CNetAddr much like IPv4 dotted-decimal notation
70  // or IPv6 colon-separated hextet notation. Since we can't use
71  // getaddrinfo to decode them and it wouldn't make sense to resolve
72  // them, we return a network address representing it instead. See
73  // CNetAddr::SetSpecial(const std::string&) for more details.
74  if (addr.SetSpecial(std::string(pszName))) {
75  vIP.push_back(addr);
76  return true;
77  }
78  }
79 
80  struct addrinfo aiHint;
81  memset(&aiHint, 0, sizeof(struct addrinfo));
82 
83  // We want a TCP port, which is a streaming socket type
84  aiHint.ai_socktype = SOCK_STREAM;
85  aiHint.ai_protocol = IPPROTO_TCP;
86  // We don't care which address family (IPv4 or IPv6) is returned
87  aiHint.ai_family = AF_UNSPEC;
88  // If we allow lookups of hostnames, use the AI_ADDRCONFIG flag to only
89  // return addresses whose family we have an address configured for.
90  //
91  // If we don't allow lookups, then use the AI_NUMERICHOST flag for
92  // getaddrinfo to only decode numerical network addresses and suppress
93  // hostname lookups.
94  aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
95  struct addrinfo *aiRes = nullptr;
96  int nErr = getaddrinfo(pszName, nullptr, &aiHint, &aiRes);
97  if (nErr)
98  return false;
99 
100  // Traverse the linked list starting with aiTrav, add all non-internal
101  // IPv4,v6 addresses to vIP while respecting nMaxSolutions.
102  struct addrinfo *aiTrav = aiRes;
103  while (aiTrav != nullptr && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
104  {
105  CNetAddr resolved;
106  if (aiTrav->ai_family == AF_INET)
107  {
108  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
109  resolved = CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr);
110  }
111 
112  if (aiTrav->ai_family == AF_INET6)
113  {
114  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
115  struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
116  resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id);
117  }
118  /* Never allow resolving to an internal address. Consider any such result invalid */
119  if (!resolved.IsInternal()) {
120  vIP.push_back(resolved);
121  }
122 
123  aiTrav = aiTrav->ai_next;
124  }
125 
126  freeaddrinfo(aiRes);
127 
128  return (vIP.size() > 0);
129 }
130 
146 bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
147 {
148  std::string strHost(pszName);
149  if (strHost.empty())
150  return false;
151  if (strHost.front() == '[' && strHost.back() == ']') {
152  strHost = strHost.substr(1, strHost.size() - 2);
153  }
154 
155  return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
156 }
157 
164 bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup)
165 {
166  std::vector<CNetAddr> vIP;
167  LookupHost(pszName, vIP, 1, fAllowLookup);
168  if(vIP.empty())
169  return false;
170  addr = vIP.front();
171  return true;
172 }
173 
194 bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
195 {
196  if (pszName[0] == 0)
197  return false;
198  int port = portDefault;
199  std::string hostname;
200  SplitHostPort(std::string(pszName), port, hostname);
201 
202  std::vector<CNetAddr> vIP;
203  bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
204  if (!fRet)
205  return false;
206  vAddr.resize(vIP.size());
207  for (unsigned int i = 0; i < vIP.size(); i++)
208  vAddr[i] = CService(vIP[i], port);
209  return true;
210 }
211 
218 bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
219 {
220  std::vector<CService> vService;
221  bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
222  if (!fRet)
223  return false;
224  addr = vService[0];
225  return true;
226 }
227 
238 CService LookupNumeric(const char *pszName, int portDefault)
239 {
240  CService addr;
241  // "1.2:345" will fail to resolve the ip, but will still set the port.
242  // If the ip fails to resolve, re-init the result.
243  if(!Lookup(pszName, addr, portDefault, false))
244  addr = CService();
245  return addr;
246 }
247 
248 struct timeval MillisToTimeval(int64_t nTimeout)
249 {
250  struct timeval timeout;
251  timeout.tv_sec = nTimeout / 1000;
252  timeout.tv_usec = (nTimeout % 1000) * 1000;
253  return timeout;
254 }
255 
257 enum SOCKSVersion: uint8_t {
258  SOCKS4 = 0x04,
259  SOCKS5 = 0x05
260 };
261 
263 enum SOCKS5Method: uint8_t {
264  NOAUTH = 0x00,
265  GSSAPI = 0x01,
266  USER_PASS = 0x02,
267  NO_ACCEPTABLE = 0xff,
268 };
269 
271 enum SOCKS5Command: uint8_t {
272  CONNECT = 0x01,
273  BIND = 0x02,
275 };
276 
278 enum SOCKS5Reply: uint8_t {
279  SUCCEEDED = 0x00,
280  GENFAILURE = 0x01,
281  NOTALLOWED = 0x02,
282  NETUNREACHABLE = 0x03,
284  CONNREFUSED = 0x05,
285  TTLEXPIRED = 0x06,
286  CMDUNSUPPORTED = 0x07,
288 };
289 
291 enum SOCKS5Atyp: uint8_t {
292  IPV4 = 0x01,
293  DOMAINNAME = 0x03,
294  IPV6 = 0x04,
295 };
296 
298 enum class IntrRecvError {
299  OK,
300  Timeout,
301  Disconnected,
302  NetworkError,
304 };
305 
324 static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const SOCKET& hSocket)
325 {
326  int64_t curTime = GetTimeMillis();
327  int64_t endTime = curTime + timeout;
328  // Maximum time to wait for I/O readiness. It will take up until this time
329  // (in millis) to break off in case of an interruption.
330  const int64_t maxWait = 1000;
331  while (len > 0 && curTime < endTime) {
332  ssize_t ret = recv(hSocket, (char*)data, len, 0); // Optimistically try the recv first
333  if (ret > 0) {
334  len -= ret;
335  data += ret;
336  } else if (ret == 0) { // Unexpected disconnection
338  } else { // Other error or blocking
339  int nErr = WSAGetLastError();
340  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
341  if (!IsSelectableSocket(hSocket)) {
343  }
344  // Only wait at most maxWait milliseconds at a time, unless
345  // we're approaching the end of the specified total timeout
346  int timeout_ms = std::min(endTime - curTime, maxWait);
347 #ifdef USE_POLL
348  struct pollfd pollfd = {};
349  pollfd.fd = hSocket;
350  pollfd.events = POLLIN;
351  int nRet = poll(&pollfd, 1, timeout_ms);
352 #else
353  struct timeval tval = MillisToTimeval(timeout_ms);
354  fd_set fdset;
355  FD_ZERO(&fdset);
356  FD_SET(hSocket, &fdset);
357  int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval);
358 #endif
359  if (nRet == SOCKET_ERROR) {
361  }
362  } else {
364  }
365  }
368  curTime = GetTimeMillis();
369  }
370  return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
371 }
372 
375 {
376  std::string username;
377  std::string password;
378 };
379 
381 static std::string Socks5ErrorString(uint8_t err)
382 {
383  switch(err) {
385  return "general failure";
387  return "connection not allowed";
389  return "network unreachable";
391  return "host unreachable";
393  return "connection refused";
395  return "TTL expired";
397  return "protocol error";
399  return "address type not supported";
400  default:
401  return "unknown";
402  }
403 }
404 
423 static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, const SOCKET& hSocket)
424 {
425  IntrRecvError recvr;
426  LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
427  if (strDest.size() > 255) {
428  return error("Hostname too long");
429  }
430  // Construct the version identifier/method selection message
431  std::vector<uint8_t> vSocks5Init;
432  vSocks5Init.push_back(SOCKSVersion::SOCKS5); // We want the SOCK5 protocol
433  if (auth) {
434  vSocks5Init.push_back(0x02); // 2 method identifiers follow...
435  vSocks5Init.push_back(SOCKS5Method::NOAUTH);
436  vSocks5Init.push_back(SOCKS5Method::USER_PASS);
437  } else {
438  vSocks5Init.push_back(0x01); // 1 method identifier follows...
439  vSocks5Init.push_back(SOCKS5Method::NOAUTH);
440  }
441  ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
442  if (ret != (ssize_t)vSocks5Init.size()) {
443  return error("Error sending to proxy");
444  }
445  uint8_t pchRet1[2];
446  if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
447  LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
448  return false;
449  }
450  if (pchRet1[0] != SOCKSVersion::SOCKS5) {
451  return error("Proxy failed to initialize");
452  }
453  if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
454  // Perform username/password authentication (as described in RFC1929)
455  std::vector<uint8_t> vAuth;
456  vAuth.push_back(0x01); // Current (and only) version of user/pass subnegotiation
457  if (auth->username.size() > 255 || auth->password.size() > 255)
458  return error("Proxy username or password too long");
459  vAuth.push_back(auth->username.size());
460  vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
461  vAuth.push_back(auth->password.size());
462  vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
463  ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL);
464  if (ret != (ssize_t)vAuth.size()) {
465  return error("Error sending authentication to proxy");
466  }
467  LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
468  uint8_t pchRetA[2];
469  if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
470  return error("Error reading proxy authentication response");
471  }
472  if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
473  return error("Proxy authentication unsuccessful");
474  }
475  } else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
476  // Perform no authentication
477  } else {
478  return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
479  }
480  std::vector<uint8_t> vSocks5;
481  vSocks5.push_back(SOCKSVersion::SOCKS5); // VER protocol version
482  vSocks5.push_back(SOCKS5Command::CONNECT); // CMD CONNECT
483  vSocks5.push_back(0x00); // RSV Reserved must be 0
484  vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); // ATYP DOMAINNAME
485  vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function
486  vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
487  vSocks5.push_back((port >> 8) & 0xFF);
488  vSocks5.push_back((port >> 0) & 0xFF);
489  ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL);
490  if (ret != (ssize_t)vSocks5.size()) {
491  return error("Error sending to proxy");
492  }
493  uint8_t pchRet2[4];
494  if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
495  if (recvr == IntrRecvError::Timeout) {
496  /* If a timeout happens here, this effectively means we timed out while connecting
497  * to the remote node. This is very common for Tor, so do not print an
498  * error message. */
499  return false;
500  } else {
501  return error("Error while reading proxy response");
502  }
503  }
504  if (pchRet2[0] != SOCKSVersion::SOCKS5) {
505  return error("Proxy failed to accept request");
506  }
507  if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
508  // Failures to connect to a peer that are not proxy errors
509  LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
510  return false;
511  }
512  if (pchRet2[2] != 0x00) { // Reserved field must be 0
513  return error("Error: malformed proxy response");
514  }
515  uint8_t pchRet3[256];
516  switch (pchRet2[3])
517  {
518  case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
519  case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
521  {
522  recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
523  if (recvr != IntrRecvError::OK) {
524  return error("Error reading from proxy");
525  }
526  int nRecv = pchRet3[0];
527  recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
528  break;
529  }
530  default: return error("Error: malformed proxy response");
531  }
532  if (recvr != IntrRecvError::OK) {
533  return error("Error reading from proxy");
534  }
535  if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
536  return error("Error reading from proxy");
537  }
538  LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
539  return true;
540 }
541 
549 SOCKET CreateSocket(const CService &addrConnect)
550 {
551  // Create a sockaddr from the specified service.
552  struct sockaddr_storage sockaddr;
553  socklen_t len = sizeof(sockaddr);
554  if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
555  LogPrintf("Cannot create socket for %s: unsupported network\n", addrConnect.ToString());
556  return INVALID_SOCKET;
557  }
558 
559  // Create a TCP socket in the address family of the specified service.
560  SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
561  if (hSocket == INVALID_SOCKET)
562  return INVALID_SOCKET;
563 
564  // Ensure that waiting for I/O on this socket won't result in undefined
565  // behavior.
566  if (!IsSelectableSocket(hSocket)) {
567  CloseSocket(hSocket);
568  LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
569  return INVALID_SOCKET;
570  }
571 
572 #ifdef SO_NOSIGPIPE
573  int set = 1;
574  // Set the no-sigpipe option on the socket for BSD systems, other UNIXes
575  // should use the MSG_NOSIGNAL flag for every send.
576  setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
577 #endif
578 
579  // Set the no-delay option (disable Nagle's algorithm) on the TCP socket.
580  SetSocketNoDelay(hSocket);
581 
582  // Set the non-blocking option on the socket.
583  if (!SetSocketNonBlocking(hSocket, true)) {
584  CloseSocket(hSocket);
585  LogPrintf("CreateSocket: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
586  }
587  return hSocket;
588 }
589 
590 template<typename... Args>
591 static void LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args) {
592  std::string error_message = tfm::format(fmt, args...);
593  if (manual_connection) {
594  LogPrintf("%s\n", error_message);
595  } else {
596  LogPrint(BCLog::NET, "%s\n", error_message);
597  }
598 }
599 
612 bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout, bool manual_connection)
613 {
614  // Create a sockaddr from the specified service.
615  struct sockaddr_storage sockaddr;
616  socklen_t len = sizeof(sockaddr);
617  if (hSocket == INVALID_SOCKET) {
618  LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString());
619  return false;
620  }
621  if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
622  LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
623  return false;
624  }
625 
626  // Connect to the addrConnect service on the hSocket socket.
627  if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
628  {
629  int nErr = WSAGetLastError();
630  // WSAEINVAL is here because some legacy version of winsock uses it
631  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
632  {
633  // Connection didn't actually fail, but is being established
634  // asynchronously. Thus, use async I/O api (select/poll)
635  // synchronously to check for successful connection with a timeout.
636 #ifdef USE_POLL
637  struct pollfd pollfd = {};
638  pollfd.fd = hSocket;
639  pollfd.events = POLLIN | POLLOUT;
640  int nRet = poll(&pollfd, 1, nTimeout);
641 #else
642  struct timeval timeout = MillisToTimeval(nTimeout);
643  fd_set fdset;
644  FD_ZERO(&fdset);
645  FD_SET(hSocket, &fdset);
646  int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout);
647 #endif
648  // Upon successful completion, both select and poll return the total
649  // number of file descriptors that have been selected. A value of 0
650  // indicates that the call timed out and no file descriptors have
651  // been selected.
652  if (nRet == 0)
653  {
654  LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
655  return false;
656  }
657  if (nRet == SOCKET_ERROR)
658  {
659  LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
660  return false;
661  }
662 
663  // Even if the select/poll was successful, the connect might not
664  // have been successful. The reason for this failure is hidden away
665  // in the SO_ERROR for the socket in modern systems. We read it into
666  // nRet here.
667  socklen_t nRetSize = sizeof(nRet);
668  if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (sockopt_arg_type)&nRet, &nRetSize) == SOCKET_ERROR)
669  {
670  LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
671  return false;
672  }
673  if (nRet != 0)
674  {
675  LogConnectFailure(manual_connection, "connect() to %s failed after select(): %s", addrConnect.ToString(), NetworkErrorString(nRet));
676  return false;
677  }
678  }
679 #ifdef WIN32
680  else if (WSAGetLastError() != WSAEISCONN)
681 #else
682  else
683 #endif
684  {
685  LogConnectFailure(manual_connection, "connect() to %s failed: %s", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
686  return false;
687  }
688  }
689  return true;
690 }
691 
692 bool SetProxy(enum Network net, const proxyType &addrProxy) {
693  assert(net >= 0 && net < NET_MAX);
694  if (!addrProxy.IsValid())
695  return false;
696  LOCK(cs_proxyInfos);
697  proxyInfo[net] = addrProxy;
698  return true;
699 }
700 
701 bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
702  assert(net >= 0 && net < NET_MAX);
703  LOCK(cs_proxyInfos);
704  if (!proxyInfo[net].IsValid())
705  return false;
706  proxyInfoOut = proxyInfo[net];
707  return true;
708 }
709 
726 bool SetNameProxy(const proxyType &addrProxy) {
727  if (!addrProxy.IsValid())
728  return false;
729  LOCK(cs_proxyInfos);
730  nameProxy = addrProxy;
731  return true;
732 }
733 
734 bool GetNameProxy(proxyType &nameProxyOut) {
735  LOCK(cs_proxyInfos);
736  if(!nameProxy.IsValid())
737  return false;
738  nameProxyOut = nameProxy;
739  return true;
740 }
741 
743  LOCK(cs_proxyInfos);
744  return nameProxy.IsValid();
745 }
746 
747 bool IsProxy(const CNetAddr &addr) {
748  LOCK(cs_proxyInfos);
749  for (int i = 0; i < NET_MAX; i++) {
750  if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy))
751  return true;
752  }
753  return false;
754 }
755 
771 bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocket, int nTimeout, bool *outProxyConnectionFailed)
772 {
773  // first connect to proxy server
774  if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout, true)) {
775  if (outProxyConnectionFailed)
776  *outProxyConnectionFailed = true;
777  return false;
778  }
779  // do socks negotiation
780  if (proxy.randomize_credentials) {
781  ProxyCredentials random_auth;
782  static std::atomic_int counter(0);
783  random_auth.username = random_auth.password = strprintf("%i", counter++);
784  if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) {
785  return false;
786  }
787  } else {
788  if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) {
789  return false;
790  }
791  }
792  return true;
793 }
794 
806 bool LookupSubNet(const char* pszName, CSubNet& ret)
807 {
808  std::string strSubnet(pszName);
809  size_t slash = strSubnet.find_last_of('/');
810  std::vector<CNetAddr> vIP;
811 
812  std::string strAddress = strSubnet.substr(0, slash);
813  // TODO: Use LookupHost(const char *, CNetAddr&, bool) instead to just get
814  // one CNetAddr.
815  if (LookupHost(strAddress.c_str(), vIP, 1, false))
816  {
817  CNetAddr network = vIP[0];
818  if (slash != strSubnet.npos)
819  {
820  std::string strNetmask = strSubnet.substr(slash + 1);
821  int32_t n;
822  if (ParseInt32(strNetmask, &n)) {
823  // If valid number, assume CIDR variable-length subnet masking
824  ret = CSubNet(network, n);
825  return ret.IsValid();
826  }
827  else // If not a valid number, try full netmask syntax
828  {
829  // Never allow lookup for netmask
830  if (LookupHost(strNetmask.c_str(), vIP, 1, false)) {
831  ret = CSubNet(network, vIP[0]);
832  return ret.IsValid();
833  }
834  }
835  }
836  else
837  {
838  ret = CSubNet(network);
839  return ret.IsValid();
840  }
841  }
842  return false;
843 }
844 
845 #ifdef WIN32
846 std::string NetworkErrorString(int err)
847 {
848  wchar_t buf[256];
849  buf[0] = 0;
850  if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
851  nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
852  buf, ARRAYSIZE(buf), nullptr))
853  {
854  return strprintf("%s (%d)", std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().to_bytes(buf), err);
855  }
856  else
857  {
858  return strprintf("Unknown error (%d)", err);
859  }
860 }
861 #else
862 std::string NetworkErrorString(int err)
863 {
864  char buf[256];
865  buf[0] = 0;
866  /* Too bad there are two incompatible implementations of the
867  * thread-safe strerror. */
868  const char *s;
869 #ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */
870  s = strerror_r(err, buf, sizeof(buf));
871 #else /* POSIX variant always returns message in buffer */
872  s = buf;
873  if (strerror_r(err, buf, sizeof(buf)))
874  buf[0] = 0;
875 #endif
876  return strprintf("%s (%d)", s, err);
877 }
878 #endif
879 
880 bool CloseSocket(SOCKET& hSocket)
881 {
882  if (hSocket == INVALID_SOCKET)
883  return false;
884 #ifdef WIN32
885  int ret = closesocket(hSocket);
886 #else
887  int ret = close(hSocket);
888 #endif
889  if (ret) {
890  LogPrintf("Socket close failed: %d. Error: %s\n", hSocket, NetworkErrorString(WSAGetLastError()));
891  }
892  hSocket = INVALID_SOCKET;
893  return ret != SOCKET_ERROR;
894 }
895 
896 bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking)
897 {
898  if (fNonBlocking) {
899 #ifdef WIN32
900  u_long nOne = 1;
901  if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
902 #else
903  int fFlags = fcntl(hSocket, F_GETFL, 0);
904  if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
905 #endif
906  return false;
907  }
908  } else {
909 #ifdef WIN32
910  u_long nZero = 0;
911  if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
912 #else
913  int fFlags = fcntl(hSocket, F_GETFL, 0);
914  if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
915 #endif
916  return false;
917  }
918  }
919 
920  return true;
921 }
922 
923 bool SetSocketNoDelay(const SOCKET& hSocket)
924 {
925  int set = 1;
926  int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int));
927  return rc == 0;
928 }
929 
930 void InterruptSocks5(bool interrupt)
931 {
932  interruptSocks5Recv = interrupt;
933 }
#define WSAEINPROGRESS
Definition: compat.h:56
Connection refused.
Definition: netbase.cpp:284
SOCKS5Reply
Values defined for REP in RFC1928.
Definition: netbase.cpp:278
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:612
std::string ToLower(const std::string &str)
Returns the lowercase equivalent of the given string.
Username/password.
Definition: netbase.cpp:266
static bool IsSelectableSocket(const SOCKET &s)
Definition: compat.h:98
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:54
GSSAPI.
Definition: netbase.cpp:265
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1067
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:324
Network unreachable.
Definition: netbase.cpp:282
CService LookupNumeric(const char *pszName, int portDefault)
Resolve a service string with a numeric IP to its first corresponding service.
Definition: netbase.cpp:238
static void LogConnectFailure(bool manual_connection, const char *fmt, const Args &... args)
Definition: netbase.cpp:591
void * sockopt_arg_type
Definition: compat.h:86
bool GetNameProxy(proxyType &nameProxyOut)
Definition: netbase.cpp:734
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:144
bool IsInternal() const
Definition: netaddress.cpp:305
#define INVALID_SOCKET
Definition: compat.h:59
bool SetNameProxy(const proxyType &addrProxy)
Set the name proxy to use for all connections to nodes specified by a hostname.
Definition: netbase.cpp:726
#define WSAGetLastError()
Definition: compat.h:50
static CCriticalSection cs_proxyInfos
Definition: netbase.cpp:30
No authentication required.
Definition: netbase.cpp:264
SOCKS5Command
Values defined for CMD in RFC1928.
Definition: netbase.cpp:271
static const int SOCKS5_RECV_TIMEOUT
Definition: netbase.cpp:37
bool HaveNameProxy()
Definition: netbase.cpp:742
#define SOCKET_ERROR
Definition: compat.h:60
static bool LookupIntern(const char *pszName, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:62
bool randomize_credentials
Definition: netbase.h:37
No acceptable methods.
Definition: netbase.cpp:267
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Obtain the IPv4/6 socket address this represents.
Definition: netaddress.cpp:636
#define LOCK(cs)
Definition: sync.h:182
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:140
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:967
Credentials for proxy authentication.
Definition: netbase.cpp:374
IntrRecvError
Status codes that can be returned by InterruptibleRecv.
Definition: netbase.cpp:298
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:771
bool IsProxy(const CNetAddr &addr)
Definition: netbase.cpp:747
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:257
General failure.
Definition: netbase.cpp:280
static void LogPrint(const BCLog::LogFlags &category, const Args &... args)
Definition: logging.h:159
Network
Definition: netaddress.h:20
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:423
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
Definition: netbase.cpp:880
int nConnectTimeout
Definition: netbase.cpp:33
#define WSAEWOULDBLOCK
Definition: compat.h:53
static std::string Socks5ErrorString(uint8_t err)
Convert SOCKS5 reply to an error message.
Definition: netbase.cpp:381
SOCKS5Method
Values defined for METHOD in RFC1928.
Definition: netbase.cpp:263
bool LookupSubNet(const char *pszName, CSubNet &ret)
Parse and resolve a specified subnet string into the appropriate internal representation.
Definition: netbase.cpp:806
unsigned int SOCKET
Definition: compat.h:48
bool SetProxy(enum Network net, const proxyType &addrProxy)
Definition: netbase.cpp:692
bool SetSocketNonBlocking(const SOCKET &hSocket, bool fNonBlocking)
Disable or enable blocking-mode for a socket.
Definition: netbase.cpp:896
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:248
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:32
Network unreachable.
Definition: netbase.cpp:283
bool IsValid() const
Definition: netaddress.cpp:826
CService proxy
Definition: netbase.h:36
bool IsValid() const
Definition: netbase.h:34
TTL expired.
Definition: netbase.cpp:285
#define WSAEINVAL
Definition: compat.h:51
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:923
#define MSG_NOSIGNAL
Definition: netbase.cpp:26
static const int DEFAULT_CONNECT_TIMEOUT
-timeout default
Definition: netbase.h:24
bool Lookup(const char *pszName, std::vector< CService > &vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
Resolve a service string to its corresponding service.
Definition: netbase.cpp:194
SOCKET CreateSocket(const CService &addrConnect)
Try to create a socket file descriptor with specific properties in the communications domain (address...
Definition: netbase.cpp:549
Succeeded.
Definition: netbase.cpp:279
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:84
void InterruptSocks5(bool interrupt)
Definition: netbase.cpp:930
std::string password
Definition: netbase.cpp:377
std::string ToString() const
Definition: netaddress.cpp:693
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:701
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
Definition: netbase.cpp:862
Address type not supported.
Definition: netbase.cpp:287
Command not supported.
Definition: netbase.cpp:286
Connection not allowed by ruleset.
Definition: netbase.cpp:281
std::string GetNetworkName(enum Network net)
Definition: netbase.cpp:52
bool LookupHost(const char *pszName, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Resolve a host string to its corresponding network addresses.
Definition: netbase.cpp:146
std::string username
Definition: netbase.cpp:376
SOCKS5Atyp
Values defined for ATYPE in RFC1928.
Definition: netbase.cpp:291
bool error(const char *fmt, const Args &... args)
Definition: system.h:47
bool fNameLookup
Definition: netbase.cpp:34
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)