Skip to content

Commit 5a437c4

Browse files
Tofandeladuh95
authored andcommitted
report: fix network queries in getReport libuv with exclude-network
PR-URL: #55602 Reviewed-By: Ethan Arrowood <ethan@arrowood.dev> Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
1 parent e0db9ed commit 5a437c4

File tree

6 files changed

+147
-28
lines changed

6 files changed

+147
-28
lines changed

doc/api/report.md

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ is provided below for reference.
3535
```json
3636
{
3737
"header": {
38-
"reportVersion": 3,
38+
"reportVersion": 4,
3939
"event": "exception",
4040
"trigger": "Exception",
4141
"filename": "report.20181221.005011.8974.0.001.json",
@@ -325,6 +325,50 @@ is provided below for reference.
325325
"is_active": true,
326326
"address": "0x000055fc7b2cb180",
327327
"loopIdleTimeSeconds": 22644.8
328+
},
329+
{
330+
"type": "tcp",
331+
"is_active": true,
332+
"is_referenced": true,
333+
"address": "0x000055e70fcb85d8",
334+
"localEndpoint": {
335+
"host": "localhost",
336+
"ip4": "127.0.0.1",
337+
"port": 48986
338+
},
339+
"remoteEndpoint": {
340+
"host": "localhost",
341+
"ip4": "127.0.0.1",
342+
"port": 38573
343+
},
344+
"sendBufferSize": 2626560,
345+
"recvBufferSize": 131072,
346+
"fd": 24,
347+
"writeQueueSize": 0,
348+
"readable": true,
349+
"writable": true
350+
},
351+
{
352+
"type": "tcp",
353+
"is_active": true,
354+
"is_referenced": true,
355+
"address": "0x000055e70fcd68c8",
356+
"localEndpoint": {
357+
"host": "ip6-localhost",
358+
"ip6": "::1",
359+
"port": 52266
360+
},
361+
"remoteEndpoint": {
362+
"host": "ip6-localhost",
363+
"ip6": "::1",
364+
"port": 38573
365+
},
366+
"sendBufferSize": 2626560,
367+
"recvBufferSize": 131072,
368+
"fd": 25,
369+
"writeQueueSize": 0,
370+
"readable": false,
371+
"writable": false
328372
}
329373
],
330374
"workers": [],
@@ -464,9 +508,9 @@ meaning of `SIGUSR2` for the said purposes.
464508
* `--report-signal` Sets or resets the signal for report generation
465509
(not supported on Windows). Default signal is `SIGUSR2`.
466510

467-
* `--report-exclude-network` Exclude `header.networkInterfaces` from the
468-
diagnostic report. By default this is not set and the network interfaces
469-
are included.
511+
* `--report-exclude-network` Exclude `header.networkInterfaces` and disable the reverse DNS queries
512+
in `libuv.*.(remote|local)Endpoint.host` from the diagnostic report.
513+
By default this is not set and the network interfaces are included.
470514

471515
* `--report-exclude-env` Exclude `environmentVariables` from the
472516
diagnostic report. By default this is not set and the environment

src/node_report.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include <cwctype>
2424
#include <fstream>
2525

26-
constexpr int NODE_REPORT_VERSION = 3;
26+
constexpr int NODE_REPORT_VERSION = 4;
2727
constexpr int NANOS_PER_SEC = 1000 * 1000 * 1000;
2828
constexpr double SEC_PER_MICROS = 1e-6;
2929
constexpr int MAX_FRAME_COUNT = node::kMaxFrameCountForLogging;
@@ -205,7 +205,9 @@ static void WriteNodeReport(Isolate* isolate,
205205

206206
writer.json_arraystart("libuv");
207207
if (env != nullptr) {
208-
uv_walk(env->event_loop(), WalkHandle, static_cast<void*>(&writer));
208+
uv_walk(env->event_loop(),
209+
exclude_network ? WalkHandleNoNetwork : WalkHandleNetwork,
210+
static_cast<void*>(&writer));
209211

210212
writer.json_start();
211213
writer.json_keyvalue("type", "loop");

src/node_report.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
namespace node {
2020
namespace report {
2121
// Function declarations - utility functions in src/node_report_utils.cc
22-
void WalkHandle(uv_handle_t* h, void* arg);
22+
void WalkHandleNetwork(uv_handle_t* h, void* arg);
23+
void WalkHandleNoNetwork(uv_handle_t* h, void* arg);
2324

2425
template <typename T>
2526
std::string ValueToHexString(T value) {

src/node_report_utils.cc

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,51 @@ static constexpr auto null = JSONWriter::Null{};
1212
static void ReportEndpoint(uv_handle_t* h,
1313
struct sockaddr* addr,
1414
const char* name,
15-
JSONWriter* writer) {
15+
JSONWriter* writer,
16+
bool exclude_network) {
1617
if (addr == nullptr) {
1718
writer->json_keyvalue(name, null);
1819
return;
1920
}
2021

2122
uv_getnameinfo_t endpoint;
2223
char* host = nullptr;
23-
char hostbuf[INET6_ADDRSTRLEN];
2424
const int family = addr->sa_family;
2525
const int port = ntohs(family == AF_INET ?
2626
reinterpret_cast<sockaddr_in*>(addr)->sin_port :
2727
reinterpret_cast<sockaddr_in6*>(addr)->sin6_port);
2828

29-
if (uv_getnameinfo(h->loop, &endpoint, nullptr, addr, NI_NUMERICSERV) == 0) {
29+
writer->json_objectstart(name);
30+
if (!exclude_network &&
31+
uv_getnameinfo(h->loop, &endpoint, nullptr, addr, NI_NUMERICSERV) == 0) {
3032
host = endpoint.host;
3133
DCHECK_EQ(port, std::stoi(endpoint.service));
34+
writer->json_keyvalue("host", host);
35+
}
36+
37+
if (family == AF_INET) {
38+
char ipbuf[INET_ADDRSTRLEN];
39+
if (uv_ip4_name(
40+
reinterpret_cast<sockaddr_in*>(addr), ipbuf, sizeof(ipbuf)) == 0) {
41+
writer->json_keyvalue("ip4", ipbuf);
42+
if (host == nullptr) writer->json_keyvalue("host", ipbuf);
43+
}
3244
} else {
33-
const void* src = family == AF_INET ?
34-
static_cast<void*>(
35-
&(reinterpret_cast<sockaddr_in*>(addr)->sin_addr)) :
36-
static_cast<void*>(
37-
&(reinterpret_cast<sockaddr_in6*>(addr)->sin6_addr));
38-
if (uv_inet_ntop(family, src, hostbuf, sizeof(hostbuf)) == 0) {
39-
host = hostbuf;
45+
char ipbuf[INET6_ADDRSTRLEN];
46+
if (uv_ip6_name(
47+
reinterpret_cast<sockaddr_in6*>(addr), ipbuf, sizeof(ipbuf)) == 0) {
48+
writer->json_keyvalue("ip6", ipbuf);
49+
if (host == nullptr) writer->json_keyvalue("host", ipbuf);
4050
}
4151
}
42-
writer->json_objectstart(name);
43-
if (host != nullptr) {
44-
writer->json_keyvalue("host", host);
45-
}
4652
writer->json_keyvalue("port", port);
4753
writer->json_objectend();
4854
}
4955

5056
// Utility function to format libuv socket information.
51-
static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) {
57+
static void ReportEndpoints(uv_handle_t* h,
58+
JSONWriter* writer,
59+
bool exclude_network) {
5260
struct sockaddr_storage addr_storage;
5361
struct sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
5462
uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
@@ -65,7 +73,8 @@ static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) {
6573
default:
6674
break;
6775
}
68-
ReportEndpoint(h, rc == 0 ? addr : nullptr, "localEndpoint", writer);
76+
ReportEndpoint(
77+
h, rc == 0 ? addr : nullptr, "localEndpoint", writer, exclude_network);
6978

7079
switch (h->type) {
7180
case UV_UDP:
@@ -77,7 +86,8 @@ static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) {
7786
default:
7887
break;
7988
}
80-
ReportEndpoint(h, rc == 0 ? addr : nullptr, "remoteEndpoint", writer);
89+
ReportEndpoint(
90+
h, rc == 0 ? addr : nullptr, "remoteEndpoint", writer, exclude_network);
8191
}
8292

8393
// Utility function to format libuv pipe information.
@@ -155,7 +165,7 @@ static void ReportPath(uv_handle_t* h, JSONWriter* writer) {
155165
}
156166

157167
// Utility function to walk libuv handles.
158-
void WalkHandle(uv_handle_t* h, void* arg) {
168+
void WalkHandle(uv_handle_t* h, void* arg, bool exclude_network = false) {
159169
const char* type = uv_handle_type_name(h->type);
160170
JSONWriter* writer = static_cast<JSONWriter*>(arg);
161171
uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
@@ -177,7 +187,7 @@ void WalkHandle(uv_handle_t* h, void* arg) {
177187
break;
178188
case UV_TCP:
179189
case UV_UDP:
180-
ReportEndpoints(h, writer);
190+
ReportEndpoints(h, writer, exclude_network);
181191
break;
182192
case UV_NAMED_PIPE:
183193
ReportPipeEndpoints(h, writer);
@@ -267,6 +277,11 @@ void WalkHandle(uv_handle_t* h, void* arg) {
267277
}
268278
writer->json_end();
269279
}
270-
280+
void WalkHandleNetwork(uv_handle_t* h, void* arg) {
281+
WalkHandle(h, arg, false);
282+
}
283+
void WalkHandleNoNetwork(uv_handle_t* h, void* arg) {
284+
WalkHandle(h, arg, true);
285+
}
271286
} // namespace report
272287
} // namespace node

test/common/report.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ function _validateContent(report, fields = []) {
110110
'glibcVersionRuntime', 'glibcVersionCompiler', 'cwd',
111111
'reportVersion', 'networkInterfaces', 'threadId'];
112112
checkForUnknownFields(header, headerFields);
113-
assert.strictEqual(header.reportVersion, 3); // Increment as needed.
113+
assert.strictEqual(header.reportVersion, 4); // Increment as needed.
114114
assert.strictEqual(typeof header.event, 'string');
115115
assert.strictEqual(typeof header.trigger, 'string');
116116
assert(typeof header.filename === 'string' || header.filename === null);

test/report/test-report-exclude-network.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22
require('../common');
3+
const http = require('node:http');
34
const assert = require('node:assert');
45
const { spawnSync } = require('node:child_process');
56
const tmpdir = require('../common/tmpdir');
@@ -38,4 +39,60 @@ describe('report exclude network option', () => {
3839
const report = process.report.getReport();
3940
assert.strictEqual(report.header.networkInterfaces, undefined);
4041
});
42+
43+
it('should not do DNS queries in libuv if exclude network', async () => {
44+
const server = http.createServer(function(req, res) {
45+
res.writeHead(200, { 'Content-Type': 'text/plain' });
46+
res.end();
47+
});
48+
let ipv6Available = true;
49+
const port = await new Promise((resolve) => server.listen(0, async () => {
50+
await Promise.all([
51+
fetch('http://127.0.0.1:' + server.address().port),
52+
fetch('http://[::1]:' + server.address().port).catch(() => ipv6Available = false),
53+
]);
54+
resolve(server.address().port);
55+
server.close();
56+
}));
57+
process.report.excludeNetwork = false;
58+
let report = process.report.getReport();
59+
let tcp = report.libuv.filter((uv) => uv.type === 'tcp' && uv.remoteEndpoint?.port === port);
60+
assert.strictEqual(tcp.length, ipv6Available ? 2 : 1);
61+
const findHandle = (local, ip4 = true) => {
62+
return tcp.find(
63+
({ [local ? 'localEndpoint' : 'remoteEndpoint']: ep }) =>
64+
(ep[ip4 ? 'ip4' : 'ip6'] === (ip4 ? '127.0.0.1' : '::1')),
65+
)?.[local ? 'localEndpoint' : 'remoteEndpoint'];
66+
};
67+
try {
68+
// The reverse DNS of 127.0.0.1 can be a lot of things other than localhost
69+
// it could resolve to the server name for instance
70+
assert.notStrictEqual(findHandle(true)?.host, '127.0.0.1');
71+
assert.notStrictEqual(findHandle(false)?.host, '127.0.0.1');
72+
73+
if (ipv6Available) {
74+
assert.notStrictEqual(findHandle(true, false)?.host, '::1');
75+
assert.notStrictEqual(findHandle(false, false)?.host, '::1');
76+
}
77+
} catch (e) {
78+
throw new Error(e?.message + ' in ' + JSON.stringify(tcp, null, 2), { cause: e });
79+
}
80+
81+
process.report.excludeNetwork = true;
82+
report = process.report.getReport();
83+
tcp = report.libuv.filter((uv) => uv.type === 'tcp' && uv.remoteEndpoint?.port === port);
84+
85+
try {
86+
assert.strictEqual(tcp.length, ipv6Available ? 2 : 1);
87+
assert.strictEqual(findHandle(true)?.host, '127.0.0.1');
88+
assert.strictEqual(findHandle(false)?.host, '127.0.0.1');
89+
90+
if (ipv6Available) {
91+
assert.strictEqual(findHandle(true, false)?.host, '::1');
92+
assert.strictEqual(findHandle(false, false)?.host, '::1');
93+
}
94+
} catch (e) {
95+
throw new Error(e?.message + ' in ' + JSON.stringify(tcp, null, 2), { cause: e });
96+
}
97+
});
4198
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy