Skip to content

Commit bae86c8

Browse files
committed
netbase: refactor CreateSock() to accept sa_family_t
Also implement CService::GetSAFamily() to provide sa_family_t
1 parent adb3a3e commit bae86c8

File tree

9 files changed

+46
-25
lines changed

9 files changed

+46
-25
lines changed

src/compat/compat.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@
3232
#include <unistd.h> // IWYU pragma: export
3333
#endif
3434

35+
// Windows does not have `sa_family_t` - it defines `sockaddr::sa_family` as `u_short`.
36+
// Thus define `sa_family_t` on Windows too so that the rest of the code can use `sa_family_t`.
37+
// See https://learn.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-sockaddr#syntax
38+
#ifdef WIN32
39+
typedef u_short sa_family_t;
40+
#endif
41+
3542
// We map Linux / BSD error functions and codes, to the equivalent
3643
// Windows definitions, and use the WSA* names throughout our code.
3744
// Note that glibc defines EWOULDBLOCK as EAGAIN (see errno.h).

src/i2p.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ Session::Reply Session::SendRequestAndGetReply(const Sock& sock,
326326

327327
std::unique_ptr<Sock> Session::Hello() const
328328
{
329-
auto sock = CreateSock(m_control_host);
329+
auto sock = CreateSock(m_control_host.GetSAFamily());
330330

331331
if (!sock) {
332332
throw std::runtime_error("Cannot create socket");

src/net.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,15 +483,16 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
483483
addr_bind = CAddress{conn.me, NODE_NONE};
484484
}
485485
} else if (use_proxy) {
486-
sock = CreateSock(proxy.proxy);
486+
sock = CreateSock(proxy.proxy.GetSAFamily());
487487
if (!sock) {
488488
return nullptr;
489489
}
490+
LogPrintLevel(BCLog::PROXY, BCLog::Level::Debug, "Using proxy: %s to connect to %s:%s\n", proxy.proxy.ToStringAddrPort(), addrConnect.ToStringAddr(), addrConnect.GetPort());
490491
connected = ConnectThroughProxy(proxy, addrConnect.ToStringAddr(), addrConnect.GetPort(),
491492
*sock, nConnectTimeout, proxyConnectionFailed);
492493
} else {
493494
// no proxy needed (none set for target network)
494-
sock = CreateSock(addrConnect);
495+
sock = CreateSock(addrConnect.GetSAFamily());
495496
if (!sock) {
496497
return nullptr;
497498
}
@@ -504,7 +505,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
504505
addrman.Attempt(addrConnect, fCountFailure);
505506
}
506507
} else if (pszDest && GetNameProxy(proxy)) {
507-
sock = CreateSock(proxy.proxy);
508+
sock = CreateSock(proxy.proxy.GetSAFamily());
508509
if (!sock) {
509510
return nullptr;
510511
}
@@ -2993,7 +2994,7 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
29932994
return false;
29942995
}
29952996

2996-
std::unique_ptr<Sock> sock = CreateSock(addrBind);
2997+
std::unique_ptr<Sock> sock = CreateSock(addrBind.GetSAFamily());
29972998
if (!sock) {
29982999
strError = strprintf(Untranslated("Couldn't open socket for incoming connections (socket returned error %s)"), NetworkErrorString(WSAGetLastError()));
29993000
LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original);

src/netaddress.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,19 @@ bool CService::SetSockAddr(const struct sockaddr *paddr)
818818
}
819819
}
820820

821+
sa_family_t CService::GetSAFamily() const
822+
{
823+
switch (m_net) {
824+
case NET_IPV4:
825+
return AF_INET;
826+
case NET_IPV6:
827+
case NET_CJDNS:
828+
return AF_INET6;
829+
default:
830+
return AF_UNSPEC;
831+
}
832+
}
833+
821834
uint16_t CService::GetPort() const
822835
{
823836
return port;

src/netaddress.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,11 @@ class CService : public CNetAddr
540540
uint16_t GetPort() const;
541541
bool GetSockAddr(struct sockaddr* paddr, socklen_t* addrlen) const;
542542
bool SetSockAddr(const struct sockaddr* paddr);
543+
/**
544+
* Get the address family
545+
* @returns AF_UNSPEC if unspecified
546+
*/
547+
[[nodiscard]] sa_family_t GetSAFamily() const;
543548
friend bool operator==(const CService& a, const CService& b);
544549
friend bool operator!=(const CService& a, const CService& b) { return !(a == b); }
545550
friend bool operator<(const CService& a, const CService& b);

src/netbase.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -444,18 +444,13 @@ bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* a
444444
}
445445
}
446446

447-
std::unique_ptr<Sock> CreateSockTCP(const CService& address_family)
447+
std::unique_ptr<Sock> CreateSockOS(sa_family_t address_family)
448448
{
449-
// Create a sockaddr from the specified service.
450-
struct sockaddr_storage sockaddr;
451-
socklen_t len = sizeof(sockaddr);
452-
if (!address_family.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
453-
LogPrintf("Cannot create socket for %s: unsupported network\n", address_family.ToStringAddrPort());
454-
return nullptr;
455-
}
449+
// Not IPv4 or IPv6
450+
if (address_family == AF_UNSPEC) return nullptr;
456451

457452
// Create a TCP socket in the address family of the specified service.
458-
SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
453+
SOCKET hSocket = socket(address_family, SOCK_STREAM, IPPROTO_TCP);
459454
if (hSocket == INVALID_SOCKET) {
460455
return nullptr;
461456
}
@@ -493,7 +488,7 @@ std::unique_ptr<Sock> CreateSockTCP(const CService& address_family)
493488
return sock;
494489
}
495490

496-
std::function<std::unique_ptr<Sock>(const CService&)> CreateSock = CreateSockTCP;
491+
std::function<std::unique_ptr<Sock>(const sa_family_t&)> CreateSock = CreateSockOS;
497492

498493
template<typename... Args>
499494
static void LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args) {

src/netbase.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -229,16 +229,16 @@ CService LookupNumeric(const std::string& name, uint16_t portDefault = 0, DNSLoo
229229
CSubNet LookupSubNet(const std::string& subnet_str);
230230

231231
/**
232-
* Create a TCP socket in the given address family.
233-
* @param[in] address_family The socket is created in the same address family as this address.
232+
* Create a socket in the given address family.
233+
* @param[in] address_family to use for the socket.
234234
* @return pointer to the created Sock object or unique_ptr that owns nothing in case of failure
235235
*/
236-
std::unique_ptr<Sock> CreateSockTCP(const CService& address_family);
236+
std::unique_ptr<Sock> CreateSockOS(sa_family_t address_family);
237237

238238
/**
239-
* Socket factory. Defaults to `CreateSockTCP()`, but can be overridden by unit tests.
239+
* Socket factory. Defaults to `CreateSockOS()`, but can be overridden by unit tests.
240240
*/
241-
extern std::function<std::unique_ptr<Sock>(const CService&)> CreateSock;
241+
extern std::function<std::unique_ptr<Sock>(const sa_family_t&)> CreateSock;
242242

243243
/**
244244
* Try to connect to the specified service on the specified socket.

src/test/fuzz/fuzz.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static const TypeTestOneInput* g_test_one_input{nullptr};
8181
void initialize()
8282
{
8383
// Terminate immediately if a fuzzing harness ever tries to create a TCP socket.
84-
CreateSock = [](const CService&) -> std::unique_ptr<Sock> { std::terminate(); };
84+
CreateSock = [](const sa_family_t&) -> std::unique_ptr<Sock> { std::terminate(); };
8585

8686
// Terminate immediately if a fuzzing harness ever tries to perform a DNS lookup.
8787
g_dns_lookup = [](const std::string& name, bool allow_lookup) {

src/test/i2p_tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ class EnvTestingSetup : public BasicTestingSetup
3838

3939
private:
4040
const BCLog::Level m_prev_log_level;
41-
const std::function<std::unique_ptr<Sock>(const CService&)> m_create_sock_orig;
41+
const std::function<std::unique_ptr<Sock>(const sa_family_t&)> m_create_sock_orig;
4242
};
4343

4444
BOOST_FIXTURE_TEST_SUITE(i2p_tests, EnvTestingSetup)
4545

4646
BOOST_AUTO_TEST_CASE(unlimited_recv)
4747
{
4848
// Mock CreateSock() to create MockSock.
49-
CreateSock = [](const CService&) {
49+
CreateSock = [](const sa_family_t&) {
5050
return std::make_unique<StaticContentsSock>(std::string(i2p::sam::MAX_MSG_SIZE + 1, 'a'));
5151
};
5252

@@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(unlimited_recv)
6666
BOOST_AUTO_TEST_CASE(listen_ok_accept_fail)
6767
{
6868
size_t num_sockets{0};
69-
CreateSock = [&num_sockets](const CService&) {
69+
CreateSock = [&num_sockets](const sa_family_t&) {
7070
// clang-format off
7171
++num_sockets;
7272
// First socket is the control socket for creating the session.
@@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(damaged_private_key)
130130
{
131131
const auto CreateSockOrig = CreateSock;
132132

133-
CreateSock = [](const CService&) {
133+
CreateSock = [](const sa_family_t&) {
134134
return std::make_unique<StaticContentsSock>("HELLO REPLY RESULT=OK VERSION=3.1\n"
135135
"SESSION STATUS RESULT=OK DESTINATION=\n");
136136
};

0 commit comments

Comments
 (0)