Skip to content

Commit cf9fa44

Browse files
authored
add network information(include interface index, MAC, Description, IPv4, IPv6), already tested on Windows and Linux (#112)
1 parent 5ca79cd commit cf9fa44

File tree

9 files changed

+323
-0
lines changed

9 files changed

+323
-0
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ option(HWINFO_RAM "Enable RAM information" ON)
4949
option(HWINFO_GPU "Enable GPU information" ON)
5050
option(HWINFO_GPU_OPENCL "Enable OpenCL for more GPU information" OFF)
5151
option(HWINFO_BATTERY "Enable battery information" ON)
52+
option(HWINFO_NETWORK "Enable network information" ON)
5253

5354
if(NOT HWINFO_STATIC AND HWINFO_SHARED)
5455
set(HWINFO_BUILD SHARED)

examples/system_infoMain.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -179,5 +179,32 @@ int main(int argc, char** argv) {
179179
} else {
180180
fmt::print("No Disks installed or detected\n");
181181
}
182+
183+
std::vector<hwinfo::Network> networks = hwinfo::getAllNetworks();
184+
fmt::print("--------------------------------- Networks -----------------------------------\n");
185+
if (!networks.empty()) {
186+
int network_counter = 0;
187+
for (const auto& network : networks) {
188+
// clang-format off
189+
if (network.ip4().size() > 0 || network.ip6().size() > 0) {
190+
fmt::print(
191+
"Network {}:\n"
192+
"{:<20} {}\n"
193+
"{:<20} {}\n"
194+
"{:<20} {}\n"
195+
"{:<20} {}\n"
196+
"{:<20} {}\n",
197+
network_counter++,
198+
"description:", network.description(),
199+
"interface index:", network.interfaceIndex(),
200+
"mac:", network.mac(),
201+
"ipv4:", network.ip4(),
202+
"ipv6:", network.ip6());
203+
}
204+
// clang-format on
205+
}
206+
} else {
207+
fmt::print("No Networks installed or detected\n");
208+
}
182209
return EXIT_SUCCESS;
183210
}

include/hwinfo/hwinfo.h

+1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88
#include <hwinfo/disk.h>
99
#include <hwinfo/gpu.h>
1010
#include <hwinfo/mainboard.h>
11+
#include <hwinfo/network.h>
1112
#include <hwinfo/os.h>
1213
#include <hwinfo/ram.h>

include/hwinfo/network.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
#include <hwinfo/platform.h>
4+
5+
#include <string>
6+
#include <vector>
7+
8+
namespace hwinfo {
9+
10+
class HWINFO_API Network {
11+
friend std::vector<Network> getAllNetworks();
12+
13+
public:
14+
~Network() = default;
15+
16+
HWI_NODISCARD const std::string& interfaceIndex() const;
17+
HWI_NODISCARD const std::string& description() const;
18+
HWI_NODISCARD const std::string& mac() const;
19+
HWI_NODISCARD const std::string& ip4() const;
20+
HWI_NODISCARD const std::string& ip6() const;
21+
22+
private:
23+
Network() = default;
24+
25+
std::string _index;
26+
std::string _description;
27+
std::string _mac;
28+
std::string _ip4;
29+
std::string _ip6;
30+
};
31+
32+
std::vector<Network> getAllNetworks();
33+
34+
} // namespace hwinfo

src/CMakeLists.txt

+34
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,40 @@ if (HWINFO_RAM)
250250
endif ()
251251
# ______________________________________________________________________________________________________________________
252252

253+
# ----- NETWORK --------------------------------------------------------------------------------------------------------
254+
if (HWINFO_NETWORK)
255+
set(NETWORK_SRC_FILES
256+
network.cpp
257+
apple/network.cpp
258+
linux/network.cpp
259+
windows/network.cpp
260+
261+
windows/utils/wmi_wrapper.cpp
262+
apple/utils/filesystem.cpp
263+
linux/utils/filesystem.cpp
264+
)
265+
266+
add_library(hwinfo_network ${HWINFO_BUILD} ${NETWORK_SRC_FILES})
267+
if(${HWINFO_SHARED})
268+
target_compile_definitions(hwinfo_network PUBLIC -DHWINFO_EXPORTS)
269+
endif()
270+
target_include_directories(hwinfo_network PUBLIC $<BUILD_INTERFACE:${HWINFO_INCLUDE_DIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
271+
272+
273+
274+
target_link_libraries(hwinfo INTERFACE hwinfo_network)
275+
276+
set_target_properties(hwinfo_network PROPERTIES OUTPUT_NAME "hwinfo_network")
277+
278+
install(TARGETS hwinfo_network
279+
EXPORT lfreist-hwinfoTargets
280+
LIBRARY DESTINATION lib
281+
ARCHIVE DESTINATION lib
282+
RUNTIME DESTINATION bin)
283+
install(FILES ${HWINFO_INCLUDE_DIR}/hwinfo/network.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hwinfo)
284+
endif ()
285+
# ______________________________________________________________________________________________________________________
286+
253287
install(FILES ${HWINFO_INCLUDE_DIR}/hwinfo/platform.h ${HWINFO_INCLUDE_DIR}/hwinfo/hwinfo.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hwinfo)
254288
install(DIRECTORY ${HWINFO_INCLUDE_DIR}/hwinfo/utils DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hwinfo)
255289
install(TARGETS hwinfo

src/apple/network.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include <hwinfo/platform.h>
2+
3+
#ifdef HWINFO_APPLE
4+
#include <hwinfo/network.h>
5+
6+
#include <vector>
7+
namespace hwinfo {
8+
std::vector<Network> getAllNetworks() {
9+
std::vector<Network> networks;
10+
return networks;
11+
}
12+
} // namespace hwinfo
13+
14+
#endif // HWINFO_APPLE

src/linux/network.cpp

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#include <hwinfo/platform.h>
2+
3+
#ifdef HWINFO_UNIX
4+
#include <arpa/inet.h>
5+
#include <hwinfo/network.h>
6+
#include <ifaddrs.h>
7+
#include <net/if.h>
8+
#include <netpacket/packet.h>
9+
#include <sys/ioctl.h>
10+
11+
#include <cstring>
12+
#include <fstream>
13+
#include <string>
14+
#include <vector>
15+
16+
namespace hwinfo {
17+
18+
std::string getInterfaceIndex(const std::string& path) {
19+
int index = if_nametoindex(path.c_str());
20+
return (index > 0) ? std::to_string(index) : "<unknown>";
21+
}
22+
23+
std::string getDescription(const std::string& path) { return path; }
24+
25+
std::string getMac(const std::string& path) {
26+
std::ifstream file("/sys/class/net/" + path + "/address");
27+
std::string mac;
28+
if (file.is_open()) {
29+
std::getline(file, mac);
30+
file.close();
31+
}
32+
return mac.empty() ? "<unknown>" : mac;
33+
}
34+
35+
std::string getIp4(const std::string& interface) {
36+
std::string ip4 = "<unknown>";
37+
struct ifaddrs* ifaddr;
38+
if (getifaddrs(&ifaddr) == -1) {
39+
return ip4;
40+
}
41+
42+
for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
43+
if (ifa->ifa_addr == nullptr) continue;
44+
if (ifa->ifa_addr->sa_family == AF_INET && interface == ifa->ifa_name) {
45+
char ip[INET_ADDRSTRLEN];
46+
inet_ntop(AF_INET, &((struct sockaddr_in*)ifa->ifa_addr)->sin_addr, ip, sizeof(ip));
47+
ip4 = ip;
48+
break;
49+
}
50+
}
51+
freeifaddrs(ifaddr);
52+
return ip4;
53+
}
54+
55+
std::string getIp6(const std::string& interface) {
56+
std::string ip6 = "<unknown>";
57+
struct ifaddrs* ifaddr;
58+
if (getifaddrs(&ifaddr) == -1) {
59+
return ip6;
60+
}
61+
62+
for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
63+
if (ifa->ifa_addr == nullptr) {
64+
continue;
65+
}
66+
if (ifa->ifa_addr->sa_family == AF_INET6 && interface == ifa->ifa_name) {
67+
char ip[INET6_ADDRSTRLEN];
68+
inet_ntop(AF_INET6, &((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr, ip, sizeof(ip));
69+
if (std::strncmp(ip, "fe80", 4) == 0) {
70+
ip6 = ip;
71+
break;
72+
}
73+
}
74+
}
75+
freeifaddrs(ifaddr);
76+
return ip6;
77+
}
78+
79+
std::vector<Network> getAllNetworks() {
80+
std::vector<Network> networks;
81+
struct ifaddrs* ifaddr;
82+
if (getifaddrs(&ifaddr) == -1) {
83+
perror("getifaddrs");
84+
return networks;
85+
}
86+
87+
for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
88+
if (ifa->ifa_addr == nullptr) continue;
89+
if (ifa->ifa_addr->sa_family != AF_PACKET) continue;
90+
91+
std::string interface = ifa->ifa_name;
92+
Network network;
93+
network._index = getInterfaceIndex(interface);
94+
network._description = getDescription(interface);
95+
network._mac = getMac(interface);
96+
network._ip4 = getIp4(interface);
97+
network._ip6 = getIp6(interface);
98+
networks.push_back(std::move(network));
99+
}
100+
freeifaddrs(ifaddr);
101+
return networks;
102+
}
103+
104+
} // namespace hwinfo
105+
106+
#endif

src/network.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
#include <hwinfo/network.h>
3+
namespace hwinfo {
4+
5+
// _____________________________________________________________________________________________________________________
6+
const std::string& Network::interfaceIndex() const { return _index; }
7+
8+
// _____________________________________________________________________________________________________________________
9+
const std::string& Network::description() const { return _description; }
10+
11+
// _____________________________________________________________________________________________________________________
12+
const std::string& Network::mac() const { return _mac; }
13+
14+
// _____________________________________________________________________________________________________________________
15+
const std::string& Network::ip4() const { return _ip4; }
16+
17+
// _____________________________________________________________________________________________________________________
18+
const std::string& Network::ip6() const { return _ip6; }
19+
20+
} // namespace hwinfo

src/windows/network.cpp

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#include "hwinfo/platform.h"
2+
3+
#ifdef HWINFO_WINDOWS
4+
5+
#include <hwinfo/network.h>
6+
#include <hwinfo/utils/stringutils.h>
7+
#include <hwinfo/utils/wmi_wrapper.h>
8+
9+
namespace hwinfo {
10+
11+
// _____________________________________________________________________________________________________________________
12+
std::vector<Network> getAllNetworks() {
13+
utils::WMI::_WMI wmi;
14+
const std::wstring query_string(
15+
L"SELECT InterfaceIndex, IPAddress, Description, MACAddress "
16+
L"FROM Win32_NetworkAdapterConfiguration");
17+
bool success = wmi.execute_query(query_string);
18+
if (!success) {
19+
return {};
20+
}
21+
std::vector<Network> networks;
22+
23+
ULONG u_return = 0;
24+
IWbemClassObject* obj = nullptr;
25+
int network_id = 0;
26+
while (wmi.enumerator) {
27+
wmi.enumerator->Next(WBEM_INFINITE, 1, &obj, &u_return);
28+
if (!u_return) {
29+
break;
30+
}
31+
Network network;
32+
VARIANT vt_prop;
33+
HRESULT hr;
34+
hr = obj->Get(L"InterfaceIndex", 0, &vt_prop, nullptr, nullptr);
35+
if (SUCCEEDED(hr)) {
36+
network._index = std::to_string(vt_prop.uintVal);
37+
}
38+
hr = obj->Get(L"IPAddress", 0, &vt_prop, nullptr, nullptr);
39+
if (SUCCEEDED(hr)) {
40+
if (vt_prop.vt == (VT_ARRAY | VT_BSTR)) {
41+
LONG lbound, ubound;
42+
SafeArrayGetLBound(vt_prop.parray, 1, &lbound);
43+
SafeArrayGetUBound(vt_prop.parray, 1, &ubound);
44+
std::string ipv4, ipv6;
45+
for (LONG i = lbound; i <= ubound; ++i) {
46+
BSTR bstr;
47+
SafeArrayGetElement(vt_prop.parray, &i, &bstr);
48+
std::wstring ws(bstr, SysStringLen(bstr));
49+
std::string ip = utils::wstring_to_std_string(ws);
50+
if (ip.find(':') != std::string::npos) {
51+
if (ip.find("fe80::") == 0) {
52+
ipv6 = ip;
53+
} else {
54+
ipv6 = "";
55+
}
56+
} else {
57+
ipv4 = ip;
58+
}
59+
SysFreeString(bstr);
60+
}
61+
network._ip4 = ipv4;
62+
network._ip6 = ipv6;
63+
}
64+
}
65+
hr = obj->Get(L"Description", 0, &vt_prop, nullptr, nullptr);
66+
if (SUCCEEDED(hr)) {
67+
if (vt_prop.vt == VT_BSTR) {
68+
network._description = utils::wstring_to_std_string(vt_prop.bstrVal);
69+
}
70+
}
71+
hr = obj->Get(L"MACAddress", 0, &vt_prop, nullptr, nullptr);
72+
if (SUCCEEDED(hr)) {
73+
if (vt_prop.vt == VT_BSTR) {
74+
network._mac = utils::wstring_to_std_string(vt_prop.bstrVal);
75+
}
76+
}
77+
VariantClear(&vt_prop);
78+
obj->Release();
79+
networks.push_back(std::move(network));
80+
}
81+
return networks;
82+
}
83+
84+
} // namespace hwinfo
85+
86+
#endif // HWINFO_WINDOWS

0 commit comments

Comments
 (0)