Skip to content

Commit 4b91e4d

Browse files
cjihrigBridgeAR
authored andcommitted
report: include network interfaces in report
PR-URL: #28911 Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]> Reviewed-By: Yongsheng Zhang <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent 57f5d50 commit 4b91e4d

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

doc/api/report.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ is provided below for reference.
8383
"irq": 0
8484
}
8585
],
86+
"networkInterfaces": [
87+
{
88+
"name": "en0",
89+
"internal": false,
90+
"mac": "13:10:de:ad:be:ef",
91+
"address": "10.0.0.37",
92+
"netmask": "255.255.255.0",
93+
"family": "IPv4"
94+
}
95+
],
8696
"host": "test_machine"
8797
},
8898
"javascriptStack": {

src/node_report.cc

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static void PrintLoadedLibraries(JSONWriter* writer);
6767
static void PrintComponentVersions(JSONWriter* writer);
6868
static void PrintRelease(JSONWriter* writer);
6969
static void PrintCpuInfo(JSONWriter* writer);
70+
static void PrintNetworkInterfaceInfo(JSONWriter* writer);
7071

7172
// External function to trigger a report, writing to file.
7273
// The 'name' parameter is in/out: an input filename is used
@@ -318,6 +319,7 @@ static void PrintVersionInformation(JSONWriter* writer) {
318319
}
319320

320321
PrintCpuInfo(writer);
322+
PrintNetworkInterfaceInfo(writer);
321323

322324
char host[UV_MAXHOSTNAMESIZE];
323325
size_t host_size = sizeof(host);
@@ -348,6 +350,57 @@ static void PrintCpuInfo(JSONWriter* writer) {
348350
}
349351
}
350352

353+
static void PrintNetworkInterfaceInfo(JSONWriter* writer) {
354+
uv_interface_address_t* interfaces;
355+
char ip[INET6_ADDRSTRLEN];
356+
char netmask[INET6_ADDRSTRLEN];
357+
char mac[18];
358+
int count;
359+
360+
if (uv_interface_addresses(&interfaces, &count) == 0) {
361+
writer->json_arraystart("networkInterfaces");
362+
363+
for (int i = 0; i < count; i++) {
364+
writer->json_start();
365+
writer->json_keyvalue("name", interfaces[i].name);
366+
writer->json_keyvalue("internal", !!interfaces[i].is_internal);
367+
snprintf(mac,
368+
sizeof(mac),
369+
"%02x:%02x:%02x:%02x:%02x:%02x",
370+
static_cast<unsigned char>(interfaces[i].phys_addr[0]),
371+
static_cast<unsigned char>(interfaces[i].phys_addr[1]),
372+
static_cast<unsigned char>(interfaces[i].phys_addr[2]),
373+
static_cast<unsigned char>(interfaces[i].phys_addr[3]),
374+
static_cast<unsigned char>(interfaces[i].phys_addr[4]),
375+
static_cast<unsigned char>(interfaces[i].phys_addr[5]));
376+
writer->json_keyvalue("mac", mac);
377+
378+
if (interfaces[i].address.address4.sin_family == AF_INET) {
379+
uv_ip4_name(&interfaces[i].address.address4, ip, sizeof(ip));
380+
uv_ip4_name(&interfaces[i].netmask.netmask4, netmask, sizeof(netmask));
381+
writer->json_keyvalue("address", ip);
382+
writer->json_keyvalue("netmask", netmask);
383+
writer->json_keyvalue("family", "IPv4");
384+
} else if (interfaces[i].address.address4.sin_family == AF_INET6) {
385+
uv_ip6_name(&interfaces[i].address.address6, ip, sizeof(ip));
386+
uv_ip6_name(&interfaces[i].netmask.netmask6, netmask, sizeof(netmask));
387+
writer->json_keyvalue("address", ip);
388+
writer->json_keyvalue("netmask", netmask);
389+
writer->json_keyvalue("family", "IPv6");
390+
writer->json_keyvalue("scopeid",
391+
interfaces[i].address.address6.sin6_scope_id);
392+
} else {
393+
writer->json_keyvalue("family", "unknown");
394+
}
395+
396+
writer->json_end();
397+
}
398+
399+
writer->json_arrayend();
400+
uv_free_interface_addresses(interfaces, count);
401+
}
402+
}
403+
351404
// Report the JavaScript stack.
352405
static void PrintJavaScriptStack(JSONWriter* writer,
353406
Isolate* isolate,

test/common/report.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
'use strict';
33
const assert = require('assert');
44
const fs = require('fs');
5+
const net = require('net');
56
const os = require('os');
67
const path = require('path');
78
const util = require('util');
@@ -73,7 +74,7 @@ function _validateContent(report) {
7374
'componentVersions', 'release', 'osName', 'osRelease',
7475
'osVersion', 'osMachine', 'cpus', 'host',
7576
'glibcVersionRuntime', 'glibcVersionCompiler', 'cwd',
76-
'reportVersion'];
77+
'reportVersion', 'networkInterfaces'];
7778
checkForUnknownFields(header, headerFields);
7879
assert.strictEqual(header.reportVersion, 1); // Increment as needed.
7980
assert.strictEqual(typeof header.event, 'string');
@@ -112,6 +113,28 @@ function _validateContent(report) {
112113
return c.model === cpu.model;
113114
}));
114115
});
116+
117+
assert(Array.isArray(header.networkInterfaces));
118+
header.networkInterfaces.forEach((iface) => {
119+
assert.strictEqual(typeof iface.name, 'string');
120+
assert.strictEqual(typeof iface.internal, 'boolean');
121+
assert(/^([0-9A-F][0-9A-F]:){5}[0-9A-F]{2}$/i.test(iface.mac));
122+
123+
if (iface.family === 'IPv4') {
124+
assert.strictEqual(net.isIPv4(iface.address), true);
125+
assert.strictEqual(net.isIPv4(iface.netmask), true);
126+
assert.strictEqual(iface.scopeid, undefined);
127+
} else if (iface.family === 'IPv6') {
128+
assert.strictEqual(net.isIPv6(iface.address), true);
129+
assert.strictEqual(net.isIPv6(iface.netmask), true);
130+
assert(Number.isInteger(iface.scopeid));
131+
} else {
132+
assert.strictEqual(iface.family, 'unknown');
133+
assert.strictEqual(iface.address, undefined);
134+
assert.strictEqual(iface.netmask, undefined);
135+
assert.strictEqual(iface.scopeid, undefined);
136+
}
137+
});
115138
assert.strictEqual(header.host, os.hostname());
116139

117140
// Verify the format of the javascriptStack section.

0 commit comments

Comments
 (0)