Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2015 The Bitcoin developers
3 : // Copyright (c) 2017-2022 The PIVX Core developers
4 : // Distributed under the MIT software license, see the accompanying
5 : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
6 :
7 : #include "netbase.h"
8 :
9 : #include "sync.h"
10 : #include "random.h"
11 : #include "tinyformat.h"
12 : #include "util/string.h"
13 : #include "util/system.h"
14 : #include "utilstrencodings.h"
15 :
16 : #include <atomic>
17 : #include <cstdint>
18 : #include <limits>
19 :
20 : #ifndef WIN32
21 : #include <fcntl.h>
22 : #else
23 : #include <codecvt>
24 : #endif
25 :
26 : #ifdef USE_POLL
27 : #include <poll.h>
28 : #endif
29 :
30 : #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
31 : #define MSG_NOSIGNAL 0
32 : #endif
33 :
34 :
35 : // Settings
36 : static proxyType proxyInfo[NET_MAX];
37 : static proxyType nameProxy;
38 : static RecursiveMutex cs_proxyInfos;
39 : int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
40 : bool fNameLookup = false;
41 :
42 : // Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
43 : static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
44 : static std::atomic<bool> interruptSocks5Recv(false);
45 :
46 17 : enum Network ParseNetwork(std::string net)
47 : {
48 17 : Downcase(net);
49 17 : if (net == "ipv4") return NET_IPV4;
50 13 : if (net == "ipv6") return NET_IPV6;
51 18 : if (net == "tor" || net == "onion") return NET_ONION;
52 : return NET_UNROUTABLE;
53 : }
54 :
55 12832 : std::string GetNetworkName(enum Network net)
56 : {
57 12832 : switch (net) {
58 314 : case NET_UNROUTABLE: return "unroutable";
59 10073 : case NET_IPV4: return "ipv4";
60 1223 : case NET_IPV6: return "ipv6";
61 1222 : case NET_ONION: return "onion";
62 0 : case NET_I2P: return "i2p";
63 0 : case NET_CJDNS: return "cjdns";
64 0 : case NET_INTERNAL: return "internal";
65 0 : case NET_MAX: assert(false);
66 : } // no default case, so the compiler can warn about missing cases
67 :
68 0 : assert(false);
69 : }
70 :
71 604649 : void SplitHostPort(std::string in, int& portOut, std::string& hostOut)
72 : {
73 604649 : size_t colon = in.find_last_of(':');
74 : // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
75 604649 : bool fHaveColon = colon != in.npos;
76 604649 : bool fBracketed = fHaveColon && (in[0] == '[' && in[colon - 1] == ']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
77 604649 : bool fMultiColon = fHaveColon && (in.find_last_of(':', colon - 1) != in.npos);
78 604649 : if (fHaveColon && (colon == 0 || fBracketed || !fMultiColon)) {
79 2045 : int32_t n;
80 4090 : if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
81 1957 : in = in.substr(0, colon);
82 1957 : portOut = n;
83 : }
84 : }
85 604649 : if (in.size() > 0 && in[0] == '[' && in[in.size() - 1] == ']')
86 18 : hostOut = in.substr(1, in.size() - 2);
87 : else
88 604631 : hostOut = in;
89 604649 : }
90 :
91 623055 : bool static LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
92 : {
93 623055 : vIP.clear();
94 :
95 623055 : if (!ValidAsCString(name)) {
96 : return false;
97 : }
98 :
99 623055 : {
100 623055 : CNetAddr addr;
101 623055 : if (addr.SetSpecial(name)) {
102 7 : vIP.push_back(addr);
103 7 : return true;
104 : }
105 : }
106 :
107 623048 : struct addrinfo aiHint;
108 623048 : memset(&aiHint, 0, sizeof(struct addrinfo));
109 :
110 623048 : aiHint.ai_socktype = SOCK_STREAM;
111 623048 : aiHint.ai_protocol = IPPROTO_TCP;
112 623048 : aiHint.ai_family = AF_UNSPEC;
113 : #ifdef WIN32
114 : aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
115 : #else
116 623048 : aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
117 : #endif
118 623048 : struct addrinfo* aiRes = nullptr;
119 623048 : int nErr = getaddrinfo(name.c_str(), nullptr, &aiHint, &aiRes);
120 623048 : if (nErr)
121 : return false;
122 :
123 622940 : struct addrinfo* aiTrav = aiRes;
124 1245880 : while (aiTrav != nullptr && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions)) {
125 1245880 : CNetAddr resolved;
126 622940 : if (aiTrav->ai_family == AF_INET) {
127 622105 : assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
128 622105 : resolved = CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr);
129 : }
130 :
131 622940 : if (aiTrav->ai_family == AF_INET6) {
132 835 : assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
133 835 : struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
134 835 : resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id);
135 : }
136 : /* Never allow resolving to an internal address. Consider any such result invalid */
137 622940 : if (!resolved.IsInternal()) {
138 622939 : vIP.push_back(resolved);
139 : }
140 :
141 622940 : aiTrav = aiTrav->ai_next;
142 : }
143 :
144 622940 : freeaddrinfo(aiRes);
145 :
146 622940 : return (vIP.size() > 0);
147 : }
148 :
149 19678 : bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
150 : {
151 19678 : if (!ValidAsCString(name)) {
152 : return false;
153 : }
154 39356 : std::string strHost = name;
155 19678 : if (strHost.empty())
156 : return false;
157 19677 : if (strHost.front() == '[' && strHost.back() == ']') {
158 1 : strHost = strHost.substr(1, strHost.size() - 2);
159 : }
160 :
161 19677 : return LookupIntern(strHost, vIP, nMaxSolutions, fAllowLookup);
162 : }
163 :
164 19490 : bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup)
165 : {
166 19490 : if (!ValidAsCString(name)) {
167 : return false;
168 : }
169 38974 : std::vector<CNetAddr> vIP;
170 19487 : LookupHost(name, vIP, 1, fAllowLookup);
171 19487 : if (vIP.empty())
172 : return false;
173 19389 : addr = vIP.front();
174 19389 : return true;
175 : }
176 :
177 603378 : bool Lookup(const std::string& name, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
178 : {
179 603378 : if (name.empty() || !ValidAsCString(name)) {
180 : return false;
181 : }
182 603378 : int port = portDefault;
183 1206760 : std::string hostname;
184 1206760 : SplitHostPort(name, port, hostname);
185 :
186 1206760 : std::vector<CNetAddr> vIP;
187 603378 : bool fRet = LookupIntern(hostname, vIP, nMaxSolutions, fAllowLookup);
188 603378 : if (!fRet)
189 : return false;
190 603372 : vAddr.resize(vIP.size());
191 1206746 : for (unsigned int i = 0; i < vIP.size(); i++)
192 603372 : vAddr[i] = CService(vIP[i], port);
193 : return true;
194 : }
195 :
196 602685 : bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllowLookup)
197 : {
198 602685 : if (!ValidAsCString(name)) {
199 : return false;
200 : }
201 1205370 : std::vector<CService> vService;
202 602684 : bool fRet = Lookup(name, vService, portDefault, fAllowLookup, 1);
203 602684 : if (!fRet)
204 : return false;
205 602682 : addr = vService[0];
206 602682 : return true;
207 : }
208 :
209 595285 : CService LookupNumeric(const std::string& name, int portDefault)
210 : {
211 595285 : if (!ValidAsCString(name)) {
212 0 : return {};
213 : }
214 1190574 : CService addr;
215 : // "1.2:345" will fail to resolve the ip, but will still set the port.
216 : // If the ip fails to resolve, re-init the result.
217 595285 : if (!Lookup(name, addr, portDefault, false))
218 2 : addr = CService();
219 595285 : return addr;
220 : }
221 :
222 0 : struct timeval MillisToTimeval(int64_t nTimeout)
223 : {
224 0 : struct timeval timeout;
225 0 : timeout.tv_sec = nTimeout / 1000;
226 0 : timeout.tv_usec = (nTimeout % 1000) * 1000;
227 0 : return timeout;
228 : }
229 :
230 : /** SOCKS version */
231 : enum SOCKSVersion: uint8_t {
232 : SOCKS4 = 0x04,
233 : SOCKS5 = 0x05
234 : };
235 :
236 : /** Values defined for METHOD in RFC1928 */
237 : enum SOCKS5Method: uint8_t {
238 : NOAUTH = 0x00, //! No authentication required
239 : GSSAPI = 0x01, //! GSSAPI
240 : USER_PASS = 0x02, //! Username/password
241 : NO_ACCEPTABLE = 0xff, //! No acceptable methods
242 : };
243 :
244 : /** Values defined for CMD in RFC1928 */
245 : enum SOCKS5Command: uint8_t {
246 : CONNECT = 0x01,
247 : BIND = 0x02,
248 : UDP_ASSOCIATE = 0x03
249 : };
250 :
251 : /** Values defined for REP in RFC1928 */
252 : enum SOCKS5Reply: uint8_t {
253 : SUCCEEDED = 0x00, //! Succeeded
254 : GENFAILURE = 0x01, //! General failure
255 : NOTALLOWED = 0x02, //! Connection not allowed by ruleset
256 : NETUNREACHABLE = 0x03, //! Network unreachable
257 : HOSTUNREACHABLE = 0x04, //! Network unreachable
258 : CONNREFUSED = 0x05, //! Connection refused
259 : TTLEXPIRED = 0x06, //! TTL expired
260 : CMDUNSUPPORTED = 0x07, //! Command not supported
261 : ATYPEUNSUPPORTED = 0x08, //! Address type not supported
262 : };
263 :
264 : /** Values defined for ATYPE in RFC1928 */
265 : enum SOCKS5Atyp: uint8_t {
266 : IPV4 = 0x01,
267 : DOMAINNAME = 0x03,
268 : IPV6 = 0x04,
269 : };
270 :
271 : /** Status codes that can be returned by InterruptibleRecv */
272 : enum class IntrRecvError {
273 : OK,
274 : Timeout,
275 : Disconnected,
276 : NetworkError,
277 : Interrupted
278 : };
279 :
280 : /**
281 : * Read bytes from socket. This will either read the full number of bytes requested
282 : * or return False on error or timeout.
283 : * This function can be interrupted by calling InterruptSocks5()
284 : *
285 : * @param data Buffer to receive into
286 : * @param len Length of data to receive
287 : * @param timeout Timeout in milliseconds for receive operation
288 : *
289 : * @note This function requires that hSocket is in non-blocking mode.
290 : */
291 64 : static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const SOCKET& hSocket)
292 : {
293 64 : int64_t curTime = GetTimeMillis();
294 64 : int64_t endTime = curTime + timeout;
295 : // Maximum time to wait in one select call. It will take up until this time (in millis)
296 : // to break off in case of an interruption.
297 64 : const int64_t maxWait = 1000;
298 2661 : while (len > 0 && curTime < endTime) {
299 2597 : ssize_t ret = recv(hSocket, (char*)data, len, 0); // Optimistically try the recv first
300 2597 : if (ret > 0) {
301 64 : len -= ret;
302 64 : data += ret;
303 2533 : } else if (ret == 0) { // Unexpected disconnection
304 : return IntrRecvError::Disconnected;
305 : } else { // Other error or blocking
306 2533 : int nErr = WSAGetLastError();
307 2533 : if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
308 2533 : if (!IsSelectableSocket(hSocket)) {
309 0 : return IntrRecvError::NetworkError;
310 : }
311 2533 : int timeout_ms = std::min(endTime - curTime, maxWait);
312 : #ifdef USE_POLL
313 2533 : struct pollfd pollfd = {};
314 2533 : pollfd.fd = hSocket;
315 2533 : pollfd.events = POLLIN | POLLOUT;
316 2533 : int nRet = poll(&pollfd, 1, timeout_ms);
317 : #else
318 : struct timeval tval = MillisToTimeval(timeout_ms);
319 : fd_set fdset;
320 : FD_ZERO(&fdset);
321 : FD_SET(hSocket, &fdset);
322 : int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval);
323 : #endif
324 2533 : if (nRet == SOCKET_ERROR) {
325 0 : return IntrRecvError::NetworkError;
326 2533 : }
327 : } else {
328 : return IntrRecvError::NetworkError;
329 : }
330 : }
331 2597 : if (interruptSocks5Recv)
332 : return IntrRecvError::Interrupted;
333 2597 : curTime = GetTimeMillis();
334 : }
335 64 : return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
336 : }
337 :
338 : /** Credentials for proxy authentication */
339 8 : struct ProxyCredentials
340 : {
341 : std::string username;
342 : std::string password;
343 : };
344 :
345 : /** Convert SOCKS5 reply to a an error message */
346 0 : static std::string Socks5ErrorString(uint8_t err)
347 : {
348 0 : switch(err) {
349 0 : case SOCKS5Reply::GENFAILURE:
350 0 : return "general failure";
351 0 : case SOCKS5Reply::NOTALLOWED:
352 0 : return "connection not allowed";
353 0 : case SOCKS5Reply::NETUNREACHABLE:
354 0 : return "network unreachable";
355 0 : case SOCKS5Reply::HOSTUNREACHABLE:
356 0 : return "host unreachable";
357 0 : case SOCKS5Reply::CONNREFUSED:
358 0 : return "connection refused";
359 0 : case SOCKS5Reply::TTLEXPIRED:
360 0 : return "TTL expired";
361 0 : case SOCKS5Reply::CMDUNSUPPORTED:
362 0 : return "protocol error";
363 0 : case SOCKS5Reply::ATYPEUNSUPPORTED:
364 0 : return "address type not supported";
365 0 : default:
366 0 : return "unknown";
367 : }
368 : }
369 :
370 : /** Connect using SOCKS5 (as described in RFC1928) */
371 15 : bool static Socks5(std::string strDest, int port, const ProxyCredentials *auth, const SOCKET& hSocket)
372 : {
373 15 : IntrRecvError recvr;
374 15 : LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
375 15 : if (strDest.size() > 255) {
376 0 : return error("Hostname too long");
377 : }
378 : // Accepted authentication methods
379 30 : std::vector<uint8_t> vSocks5Init;
380 15 : vSocks5Init.push_back(SOCKSVersion::SOCKS5);
381 15 : if (auth) {
382 8 : vSocks5Init.push_back(0x02); // Number of methods
383 8 : vSocks5Init.push_back(SOCKS5Method::NOAUTH);
384 8 : vSocks5Init.push_back(SOCKS5Method::USER_PASS);
385 : } else {
386 7 : vSocks5Init.push_back(0x01); // Number of methods
387 7 : vSocks5Init.push_back(SOCKS5Method::NOAUTH);
388 : }
389 15 : ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
390 15 : if (ret != (ssize_t)vSocks5Init.size()) {
391 0 : return error("Error sending to proxy");
392 : }
393 15 : uint8_t pchRet1[2];
394 15 : if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
395 0 : LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
396 : return false;
397 : }
398 15 : if (pchRet1[0] != SOCKSVersion::SOCKS5) {
399 0 : return error("Proxy failed to initialize");
400 : }
401 15 : if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
402 : // Perform username/password authentication (as described in RFC1929)
403 8 : std::vector<uint8_t> vAuth;
404 4 : vAuth.push_back(0x01); // Current (and only) version of user/pass subnegotiation
405 4 : if (auth->username.size() > 255 || auth->password.size() > 255)
406 0 : return error("Proxy username or password too long");
407 4 : vAuth.push_back(auth->username.size());
408 4 : vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
409 4 : vAuth.push_back(auth->password.size());
410 4 : vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
411 4 : ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL);
412 4 : if (ret != (ssize_t)vAuth.size()) {
413 0 : return error("Error sending authentication to proxy");
414 : }
415 4 : LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
416 4 : uint8_t pchRetA[2];
417 4 : if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
418 0 : return error("Error reading proxy authentication response");
419 : }
420 4 : if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
421 0 : return error("Proxy authentication unsuccessful");
422 : }
423 11 : } else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
424 : // Perform no authentication
425 : } else {
426 0 : return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
427 : }
428 30 : std::vector<uint8_t> vSocks5;
429 15 : vSocks5.push_back(SOCKSVersion::SOCKS5); // VER protocol version
430 15 : vSocks5.push_back(SOCKS5Command::CONNECT); // CMD CONNECT
431 15 : vSocks5.push_back(0x00); // RSV Reserved must be 0
432 15 : vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); // ATYP DOMAINNAME
433 15 : vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function
434 15 : vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
435 15 : vSocks5.push_back((port >> 8) & 0xFF);
436 15 : vSocks5.push_back((port >> 0) & 0xFF);
437 15 : ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL);
438 15 : if (ret != (ssize_t)vSocks5.size()) {
439 0 : return error("Error sending to proxy");
440 : }
441 15 : uint8_t pchRet2[4];
442 15 : if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
443 0 : if (recvr == IntrRecvError::Timeout) {
444 : /* If a timeout happens here, this effectively means we timed out while connecting
445 : * to the remote node. This is very common for Tor, so do not print an
446 : * error message. */
447 : return false;
448 : } else {
449 0 : return error("Error while reading proxy response");
450 : }
451 : }
452 15 : if (pchRet2[0] != SOCKSVersion::SOCKS5) {
453 0 : return error("Proxy failed to accept request");
454 : }
455 15 : if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
456 : // Failures to connect to a peer that are not proxy errors
457 0 : LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
458 0 : return false;
459 : }
460 15 : if (pchRet2[2] != 0x00) { // Reserved field must be 0
461 0 : return error("Error: malformed proxy response");
462 : }
463 15 : uint8_t pchRet3[256];
464 15 : switch (pchRet2[3])
465 : {
466 15 : case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
467 0 : case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
468 0 : case SOCKS5Atyp::DOMAINNAME:
469 0 : {
470 0 : recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
471 0 : if (recvr != IntrRecvError::OK) {
472 0 : return error("Error reading from proxy");
473 : }
474 0 : int nRecv = pchRet3[0];
475 0 : recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
476 : break;
477 : }
478 0 : default: return error("Error: malformed proxy response");
479 : }
480 15 : if (recvr != IntrRecvError::OK) {
481 0 : return error("Error reading from proxy");
482 : }
483 15 : if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
484 0 : return error("Error reading from proxy");
485 : }
486 15 : LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
487 : return true;
488 : }
489 :
490 1095 : SOCKET CreateSocket(const CService& addrConnect)
491 : {
492 1095 : struct sockaddr_storage sockaddr;
493 1095 : socklen_t len = sizeof(sockaddr);
494 1095 : if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
495 0 : LogPrintf("Cannot create socket for %s: unsupported network\n", addrConnect.ToString());
496 0 : return INVALID_SOCKET;
497 : }
498 :
499 1095 : SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
500 1095 : if (hSocket == INVALID_SOCKET)
501 : return INVALID_SOCKET;
502 :
503 1095 : if (!IsSelectableSocket(hSocket)) {
504 : CloseSocket(hSocket);
505 : LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
506 : return INVALID_SOCKET;
507 : }
508 :
509 : #ifdef SO_NOSIGPIPE
510 : int set = 1;
511 : // Different way of disabling SIGPIPE on BSD
512 : setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
513 : #endif
514 :
515 : // Set to non-blocking
516 1095 : if (!SetSocketNonBlocking(hSocket, true)) {
517 0 : CloseSocket(hSocket);
518 0 : LogPrintf("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
519 : }
520 1095 : return hSocket;
521 : }
522 :
523 : template<typename... Args>
524 1 : static void LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args) {
525 1 : std::string error_message = tfm::format(fmt, args...);
526 1 : if (manual_connection) {
527 1 : LogPrintf("%s\n", error_message);
528 : } else {
529 0 : LogPrint(BCLog::NET, "%s\n", error_message);
530 : }
531 1 : }
532 :
533 749 : bool ConnectSocketDirectly(const CService& addrConnect, const SOCKET& hSocket, int nTimeout, bool manual_connection)
534 : {
535 749 : struct sockaddr_storage sockaddr;
536 749 : socklen_t len = sizeof(sockaddr);
537 749 : if (hSocket == INVALID_SOCKET) {
538 0 : LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString());
539 0 : return false;
540 : }
541 749 : if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
542 0 : LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
543 0 : return false;
544 : }
545 749 : if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) {
546 749 : int nErr = WSAGetLastError();
547 : // WSAEINVAL is here because some legacy version of winsock uses it
548 749 : if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
549 : #ifdef USE_POLL
550 749 : struct pollfd pollfd = {};
551 749 : pollfd.fd = hSocket;
552 749 : pollfd.events = POLLIN | POLLOUT;
553 749 : int nRet = poll(&pollfd, 1, nTimeout);
554 : #else
555 : struct timeval timeout = MillisToTimeval(nTimeout);
556 : fd_set fdset;
557 : FD_ZERO(&fdset);
558 : FD_SET(hSocket, &fdset);
559 : int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout);
560 : #endif
561 749 : if (nRet == 0) {
562 24 : LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
563 13 : return false;
564 : }
565 737 : if (nRet == SOCKET_ERROR) {
566 0 : LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
567 0 : return false;
568 : }
569 737 : socklen_t nRetSize = sizeof(nRet);
570 737 : if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (sockopt_arg_type)&nRet, &nRetSize) == SOCKET_ERROR)
571 : {
572 0 : LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
573 0 : return false;
574 : }
575 737 : if (nRet != 0) {
576 2 : LogConnectFailure(manual_connection, "connect() to %s failed after select(): %s", addrConnect.ToString(), NetworkErrorString(nRet));
577 1 : return false;
578 736 : }
579 : }
580 : #ifdef WIN32
581 : else if (WSAGetLastError() != WSAEISCONN)
582 : #else
583 : else
584 : #endif
585 : {
586 0 : LogConnectFailure(manual_connection, "connect() to %s failed: %s", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
587 0 : return false;
588 : }
589 : }
590 : return true;
591 : }
592 :
593 13 : bool SetProxy(enum Network net, const proxyType &addrProxy)
594 : {
595 13 : assert(net >= 0 && net < NET_MAX);
596 13 : if (!addrProxy.IsValid())
597 : return false;
598 13 : LOCK(cs_proxyInfos);
599 13 : proxyInfo[net] = addrProxy;
600 13 : return true;
601 : }
602 :
603 4369 : bool GetProxy(enum Network net, proxyType& proxyInfoOut)
604 : {
605 4369 : assert(net >= 0 && net < NET_MAX);
606 8738 : LOCK(cs_proxyInfos);
607 4369 : if (!proxyInfo[net].IsValid())
608 : return false;
609 41 : proxyInfoOut = proxyInfo[net];
610 41 : return true;
611 : }
612 :
613 4 : bool SetNameProxy(const proxyType &addrProxy)
614 : {
615 4 : if (!addrProxy.IsValid())
616 : return false;
617 4 : LOCK(cs_proxyInfos);
618 4 : nameProxy = addrProxy;
619 4 : return true;
620 : }
621 :
622 4 : bool GetNameProxy(proxyType &nameProxyOut)
623 : {
624 8 : LOCK(cs_proxyInfos);
625 4 : if (!nameProxy.IsValid())
626 : return false;
627 4 : nameProxyOut = nameProxy;
628 4 : return true;
629 : }
630 :
631 694 : bool HaveNameProxy()
632 : {
633 694 : LOCK(cs_proxyInfos);
634 1388 : return nameProxy.IsValid();
635 : }
636 :
637 11 : bool IsProxy(const CNetAddr& addr)
638 : {
639 22 : LOCK(cs_proxyInfos);
640 88 : for (int i = 0; i < NET_MAX; i++) {
641 77 : if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy))
642 : return true;
643 : }
644 : return false;
645 : }
646 :
647 15 : bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocket, int nTimeout, bool *outProxyConnectionFailed)
648 : {
649 : // first connect to proxy server
650 15 : if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout, true)) {
651 0 : if (outProxyConnectionFailed)
652 0 : *outProxyConnectionFailed = true;
653 0 : return false;
654 : }
655 : // do socks negotiation
656 15 : if (proxy.randomize_credentials) {
657 16 : ProxyCredentials random_auth;
658 8 : static std::atomic_int counter;
659 8 : random_auth.username = random_auth.password = strprintf("%i", counter++);
660 20 : if (!Socks5(strDest, (uint16_t)port, &random_auth, hSocket)) {
661 0 : return false;
662 : }
663 : } else {
664 10 : if (!Socks5(strDest, (uint16_t)port, 0, hSocket)) {
665 0 : return false;
666 : }
667 : }
668 : return true;
669 : }
670 :
671 151 : bool LookupSubNet(const std::string& strSubnet, CSubNet& ret)
672 : {
673 151 : if (!ValidAsCString(strSubnet)) {
674 : return false;
675 : }
676 145 : size_t slash = strSubnet.find_last_of('/');
677 145 : std::vector<CNetAddr> vIP;
678 :
679 290 : std::string strAddress = strSubnet.substr(0, slash);
680 145 : if (LookupHost(strAddress, vIP, 1, false))
681 : {
682 143 : CNetAddr network = vIP[0];
683 141 : if (slash != strSubnet.npos) {
684 83 : std::string strNetmask = strSubnet.substr(slash + 1);
685 81 : uint8_t n;
686 81 : if (ParseUInt8(strNetmask, &n)) {
687 : // If valid number, assume CIDR variable-length subnet masking
688 70 : ret = CSubNet(network, n);
689 114 : return ret.IsValid();
690 : } else // If not a valid number, try full netmask syntax
691 : {
692 : // Never allow lookup for netmask
693 46 : if (LookupHost(strNetmask, vIP, 1, false)) {
694 88 : ret = CSubNet(network, vIP[0]);
695 44 : return ret.IsValid();
696 : }
697 : }
698 : } else {
699 120 : ret = CSubNet(network);
700 60 : return ret.IsValid();
701 : }
702 : }
703 : return false;
704 : }
705 :
706 : #ifdef WIN32
707 : std::string NetworkErrorString(int err)
708 : {
709 : wchar_t buf[256];
710 : buf[0] = 0;
711 : if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
712 : nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
713 : buf, ARRAYSIZE(buf), nullptr))
714 : {
715 : const auto& bufConvert = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().to_bytes(buf);
716 : return strprintf("%s (%d)", bufConvert, err);
717 : } else {
718 : return strprintf("Unknown error (%d)", err);
719 : }
720 : }
721 : #else
722 52 : std::string NetworkErrorString(int err)
723 : {
724 52 : char buf[256];
725 52 : buf[0] = 0;
726 : /* Too bad there are two incompatible implementations of the
727 : * thread-safe strerror. */
728 52 : const char *s;
729 : #ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */
730 52 : s = strerror_r(err, buf, sizeof(buf));
731 : #else /* POSIX variant always returns message in buffer */
732 : s = buf;
733 : if (strerror_r(err, buf, sizeof(buf)))
734 : buf[0] = 0;
735 : #endif
736 52 : return strprintf("%s (%d)", s, err);
737 : }
738 : #endif
739 :
740 3350 : bool CloseSocket(SOCKET& hSocket)
741 : {
742 3350 : if (hSocket == INVALID_SOCKET)
743 : return false;
744 : #ifdef WIN32
745 : int ret = closesocket(hSocket);
746 : #else
747 1886 : int ret = close(hSocket);
748 : #endif
749 1886 : hSocket = INVALID_SOCKET;
750 1886 : return ret != SOCKET_ERROR;
751 : }
752 :
753 1095 : bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking)
754 : {
755 1095 : if (fNonBlocking) {
756 : #ifdef WIN32
757 : u_long nOne = 1;
758 : if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
759 : #else
760 1095 : int fFlags = fcntl(hSocket, F_GETFL, 0);
761 1095 : if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
762 : #endif
763 0 : CloseSocket(hSocket);
764 0 : return false;
765 : }
766 : } else {
767 : #ifdef WIN32
768 : u_long nZero = 0;
769 : if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
770 : #else
771 0 : int fFlags = fcntl(hSocket, F_GETFL, 0);
772 0 : if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
773 : #endif
774 0 : CloseSocket(hSocket);
775 0 : return false;
776 : }
777 : }
778 :
779 : return true;
780 : }
781 :
782 1205 : void InterruptSocks5(bool interrupt)
783 : {
784 1205 : interruptSocks5Recv = interrupt;
785 1205 : }
|