Skip to content

Commit 296928e

Browse files
committed
Merge #10478: rpc: Add listen address to incoming connections in getpeerinfo
3457331 test: Add test for `getpeerinfo` `bindaddr` field (Wladimir J. van der Laan) a7e3c28 rpc: Add listen address to incoming connections in `getpeerinfo` (Wladimir J. van der Laan) Tree-SHA512: bcd58bca2d35fc9698e958e22a7cf8268a6c731a3a309df183f43fc5e725a88ae09f006290fde7aa03cee9a403e2e25772097409677cedbce8f267e01e9040f6
2 parents 400fdd0 + 3457331 commit 296928e

File tree

6 files changed

+53
-13
lines changed

6 files changed

+53
-13
lines changed

src/net.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,22 @@ bool CConnman::CheckIncomingNonce(uint64_t nonce)
340340
return true;
341341
}
342342

343+
/** Get the bind address for a socket as CAddress */
344+
static CAddress GetBindAddress(SOCKET sock)
345+
{
346+
CAddress addr_bind;
347+
struct sockaddr_storage sockaddr_bind;
348+
socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
349+
if (sock != INVALID_SOCKET) {
350+
if (!getsockname(sock, (struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
351+
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
352+
} else {
353+
LogPrint(BCLog::NET, "Warning: getsockname failed\n");
354+
}
355+
}
356+
return addr_bind;
357+
}
358+
343359
CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure)
344360
{
345361
if (pszDest == NULL) {
@@ -393,7 +409,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
393409
// Add node
394410
NodeId id = GetNewNodeId();
395411
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
396-
CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, pszDest ? pszDest : "", false);
412+
CAddress addr_bind = GetBindAddress(hSocket);
413+
CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false);
397414
pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices);
398415
pnode->AddRef();
399416

@@ -635,6 +652,7 @@ void CNode::copyStats(CNodeStats &stats)
635652
stats.nodeid = this->GetId();
636653
X(nServices);
637654
X(addr);
655+
X(addrBind);
638656
{
639657
LOCK(cs_filter);
640658
X(fRelayTxes);
@@ -1036,9 +1054,11 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
10361054
int nInbound = 0;
10371055
int nMaxInbound = nMaxConnections - (nMaxOutbound + nMaxFeeler);
10381056

1039-
if (hSocket != INVALID_SOCKET)
1040-
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
1057+
if (hSocket != INVALID_SOCKET) {
1058+
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
10411059
LogPrintf("Warning: Unknown socket family\n");
1060+
}
1061+
}
10421062

10431063
bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr);
10441064
{
@@ -1092,8 +1112,9 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
10921112

10931113
NodeId id = GetNewNodeId();
10941114
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
1115+
CAddress addr_bind = GetBindAddress(hSocket);
10951116

1096-
CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, "", true);
1117+
CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", true);
10971118
pnode->AddRef();
10981119
pnode->fWhitelisted = whitelisted;
10991120
GetNodeSignals().InitializeNode(pnode, *this);
@@ -2639,9 +2660,10 @@ int CConnman::GetBestHeight() const
26392660
unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
26402661
unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; }
26412662

2642-
CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const std::string& addrNameIn, bool fInboundIn) :
2663+
CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string& addrNameIn, bool fInboundIn) :
26432664
nTimeConnected(GetSystemTimeInSeconds()),
26442665
addr(addrIn),
2666+
addrBind(addrBindIn),
26452667
fInbound(fInboundIn),
26462668
nKeyedNetGroup(nKeyedNetGroupIn),
26472669
addrKnown(5000, 0.001),

src/net.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,12 @@ class CNodeStats
504504
double dPingTime;
505505
double dPingWait;
506506
double dMinPing;
507+
// Our address, as reported by the peer
507508
std::string addrLocal;
509+
// Address of this peer
508510
CAddress addr;
511+
// Bind address of our side of the connection
512+
CAddress addrBind;
509513
};
510514

511515

@@ -586,7 +590,10 @@ class CNode
586590
std::atomic<int64_t> nLastRecv;
587591
const int64_t nTimeConnected;
588592
std::atomic<int64_t> nTimeOffset;
593+
// Address of this peer
589594
const CAddress addr;
595+
// Bind address of our side of the connection
596+
const CAddress addrBind;
590597
std::atomic<int> nVersion;
591598
// strSubVer is whatever byte array we read from the wire. However, this field is intended
592599
// to be printed out, displayed to humans in various forms and so on. So we sanitize it and
@@ -676,7 +683,7 @@ class CNode
676683
CAmount lastSentFeeFilter;
677684
int64_t nextSendTimeFeeFilter;
678685

679-
CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const std::string &addrNameIn = "", bool fInboundIn = false);
686+
CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn = "", bool fInboundIn = false);
680687
~CNode();
681688

682689
private:
@@ -695,6 +702,7 @@ class CNode
695702
mutable CCriticalSection cs_addrName;
696703
std::string addrName;
697704

705+
// Our address, as reported by the peer
698706
CService addrLocal;
699707
mutable CCriticalSection cs_addrLocal;
700708
public:

src/rpc/net.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ UniValue getpeerinfo(const JSONRPCRequest& request)
7676
" {\n"
7777
" \"id\": n, (numeric) Peer index\n"
7878
" \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
79-
" \"addrlocal\":\"ip:port\", (string) local address\n"
79+
" \"addrbind\":\"ip:port\", (string) Bind address of the connection to the peer\n"
80+
" \"addrlocal\":\"ip:port\", (string) Local address as reported by the peer\n"
8081
" \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
8182
" \"relaytxes\":true|false, (boolean) Whether peer has asked us to relay transactions to it\n"
8283
" \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
@@ -133,6 +134,8 @@ UniValue getpeerinfo(const JSONRPCRequest& request)
133134
obj.push_back(Pair("addr", stats.addrName));
134135
if (!(stats.addrLocal.empty()))
135136
obj.push_back(Pair("addrlocal", stats.addrLocal));
137+
if (stats.addrBind.IsValid())
138+
obj.push_back(Pair("addrbind", stats.addrBind.ToString()));
136139
obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
137140
obj.push_back(Pair("relaytxes", stats.fRelayTxes));
138141
obj.push_back(Pair("lastsend", stats.nLastSend));

src/test/DoS_tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
5151

5252
connman->ClearBanned();
5353
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
54-
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, "", true);
54+
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true);
5555
dummyNode1.SetSendVersion(PROTOCOL_VERSION);
5656
GetNodeSignals().InitializeNode(&dummyNode1, *connman);
5757
dummyNode1.nVersion = 1;
@@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
6262
BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
6363

6464
CAddress addr2(ip(0xa0b0c002), NODE_NONE);
65-
CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, "", true);
65+
CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true);
6666
dummyNode2.SetSendVersion(PROTOCOL_VERSION);
6767
GetNodeSignals().InitializeNode(&dummyNode2, *connman);
6868
dummyNode2.nVersion = 1;
@@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
8383
connman->ClearBanned();
8484
ForceSetArg("-banscore", "111"); // because 11 is my favorite number
8585
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
86-
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, "", true);
86+
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true);
8787
dummyNode1.SetSendVersion(PROTOCOL_VERSION);
8888
GetNodeSignals().InitializeNode(&dummyNode1, *connman);
8989
dummyNode1.nVersion = 1;
@@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
109109
SetMockTime(nStartTime); // Overrides future calls to GetTime()
110110

111111
CAddress addr(ip(0xa0b0c001), NODE_NONE);
112-
CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, "", true);
112+
CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, CAddress(), "", true);
113113
dummyNode.SetSendVersion(PROTOCOL_VERSION);
114114
GetNodeSignals().InitializeNode(&dummyNode, *connman);
115115
dummyNode.nVersion = 1;

src/test/net_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,12 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
175175
bool fInboundIn = false;
176176

177177
// Test that fFeeler is false by default.
178-
std::unique_ptr<CNode> pnode1(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, pszDest, fInboundIn));
178+
std::unique_ptr<CNode> pnode1(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, CAddress(), pszDest, fInboundIn));
179179
BOOST_CHECK(pnode1->fInbound == false);
180180
BOOST_CHECK(pnode1->fFeeler == false);
181181

182182
fInboundIn = true;
183-
std::unique_ptr<CNode> pnode2(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, pszDest, fInboundIn));
183+
std::unique_ptr<CNode> pnode2(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, CAddress(), pszDest, fInboundIn));
184184
BOOST_CHECK(pnode2->fInbound == true);
185185
BOOST_CHECK(pnode2->fFeeler == false);
186186
}

test/functional/net.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def run_test(self):
2929
self._test_getnettotals()
3030
self._test_getnetworkinginfo()
3131
self._test_getaddednodeinfo()
32+
self._test_getpeerinfo()
3233

3334
def _test_connection_count(self):
3435
# connect_nodes_bi connects each node to the other
@@ -88,6 +89,12 @@ def _test_getaddednodeinfo(self):
8889
assert_raises_jsonrpc(-24, "Node has not been added",
8990
self.nodes[0].getaddednodeinfo, '1.1.1.1')
9091

92+
def _test_getpeerinfo(self):
93+
peer_info = [x.getpeerinfo() for x in self.nodes]
94+
# check both sides of bidirectional connection between nodes
95+
# the address bound to on one side will be the source address for the other node
96+
assert_equal(peer_info[0][0]['addrbind'], peer_info[1][0]['addr'])
97+
assert_equal(peer_info[1][0]['addrbind'], peer_info[0][0]['addr'])
9198

9299
if __name__ == '__main__':
93100
NetTest().main()

0 commit comments

Comments
 (0)