add network information(include interface index, MAC, Description, IPv4, IPv6), already tested on Windows and Linux (#112)

This commit is contained in:
milk
2024-10-15 22:53:59 +08:00
committed by GitHub
parent 5ca79cd342
commit cf9fa4452b
9 changed files with 323 additions and 0 deletions

View File

@@ -49,6 +49,7 @@ option(HWINFO_RAM "Enable RAM information" ON)
option(HWINFO_GPU "Enable GPU information" ON)
option(HWINFO_GPU_OPENCL "Enable OpenCL for more GPU information" OFF)
option(HWINFO_BATTERY "Enable battery information" ON)
option(HWINFO_NETWORK "Enable network information" ON)
if(NOT HWINFO_STATIC AND HWINFO_SHARED)
set(HWINFO_BUILD SHARED)

View File

@@ -179,5 +179,32 @@ int main(int argc, char** argv) {
} else {
fmt::print("No Disks installed or detected\n");
}
std::vector<hwinfo::Network> networks = hwinfo::getAllNetworks();
fmt::print("--------------------------------- Networks -----------------------------------\n");
if (!networks.empty()) {
int network_counter = 0;
for (const auto& network : networks) {
// clang-format off
if (network.ip4().size() > 0 || network.ip6().size() > 0) {
fmt::print(
"Network {}:\n"
"{:<20} {}\n"
"{:<20} {}\n"
"{:<20} {}\n"
"{:<20} {}\n"
"{:<20} {}\n",
network_counter++,
"description:", network.description(),
"interface index:", network.interfaceIndex(),
"mac:", network.mac(),
"ipv4:", network.ip4(),
"ipv6:", network.ip6());
}
// clang-format on
}
} else {
fmt::print("No Networks installed or detected\n");
}
return EXIT_SUCCESS;
}

View File

@@ -8,5 +8,6 @@
#include <hwinfo/disk.h>
#include <hwinfo/gpu.h>
#include <hwinfo/mainboard.h>
#include <hwinfo/network.h>
#include <hwinfo/os.h>
#include <hwinfo/ram.h>

34
include/hwinfo/network.h Normal file
View File

@@ -0,0 +1,34 @@
#pragma once
#include <hwinfo/platform.h>
#include <string>
#include <vector>
namespace hwinfo {
class HWINFO_API Network {
friend std::vector<Network> getAllNetworks();
public:
~Network() = default;
HWI_NODISCARD const std::string& interfaceIndex() const;
HWI_NODISCARD const std::string& description() const;
HWI_NODISCARD const std::string& mac() const;
HWI_NODISCARD const std::string& ip4() const;
HWI_NODISCARD const std::string& ip6() const;
private:
Network() = default;
std::string _index;
std::string _description;
std::string _mac;
std::string _ip4;
std::string _ip6;
};
std::vector<Network> getAllNetworks();
} // namespace hwinfo

View File

@@ -250,6 +250,40 @@ if (HWINFO_RAM)
endif ()
# ______________________________________________________________________________________________________________________
# ----- NETWORK --------------------------------------------------------------------------------------------------------
if (HWINFO_NETWORK)
set(NETWORK_SRC_FILES
network.cpp
apple/network.cpp
linux/network.cpp
windows/network.cpp
windows/utils/wmi_wrapper.cpp
apple/utils/filesystem.cpp
linux/utils/filesystem.cpp
)
add_library(hwinfo_network ${HWINFO_BUILD} ${NETWORK_SRC_FILES})
if(${HWINFO_SHARED})
target_compile_definitions(hwinfo_network PUBLIC -DHWINFO_EXPORTS)
endif()
target_include_directories(hwinfo_network PUBLIC $<BUILD_INTERFACE:${HWINFO_INCLUDE_DIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_link_libraries(hwinfo INTERFACE hwinfo_network)
set_target_properties(hwinfo_network PROPERTIES OUTPUT_NAME "hwinfo_network")
install(TARGETS hwinfo_network
EXPORT lfreist-hwinfoTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin)
install(FILES ${HWINFO_INCLUDE_DIR}/hwinfo/network.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hwinfo)
endif ()
# ______________________________________________________________________________________________________________________
install(FILES ${HWINFO_INCLUDE_DIR}/hwinfo/platform.h ${HWINFO_INCLUDE_DIR}/hwinfo/hwinfo.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hwinfo)
install(DIRECTORY ${HWINFO_INCLUDE_DIR}/hwinfo/utils DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hwinfo)
install(TARGETS hwinfo

14
src/apple/network.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include <hwinfo/platform.h>
#ifdef HWINFO_APPLE
#include <hwinfo/network.h>
#include <vector>
namespace hwinfo {
std::vector<Network> getAllNetworks() {
std::vector<Network> networks;
return networks;
}
} // namespace hwinfo
#endif // HWINFO_APPLE

106
src/linux/network.cpp Normal file
View File

@@ -0,0 +1,106 @@
#include <hwinfo/platform.h>
#ifdef HWINFO_UNIX
#include <arpa/inet.h>
#include <hwinfo/network.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <sys/ioctl.h>
#include <cstring>
#include <fstream>
#include <string>
#include <vector>
namespace hwinfo {
std::string getInterfaceIndex(const std::string& path) {
int index = if_nametoindex(path.c_str());
return (index > 0) ? std::to_string(index) : "<unknown>";
}
std::string getDescription(const std::string& path) { return path; }
std::string getMac(const std::string& path) {
std::ifstream file("/sys/class/net/" + path + "/address");
std::string mac;
if (file.is_open()) {
std::getline(file, mac);
file.close();
}
return mac.empty() ? "<unknown>" : mac;
}
std::string getIp4(const std::string& interface) {
std::string ip4 = "<unknown>";
struct ifaddrs* ifaddr;
if (getifaddrs(&ifaddr) == -1) {
return ip4;
}
for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr) continue;
if (ifa->ifa_addr->sa_family == AF_INET && interface == ifa->ifa_name) {
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &((struct sockaddr_in*)ifa->ifa_addr)->sin_addr, ip, sizeof(ip));
ip4 = ip;
break;
}
}
freeifaddrs(ifaddr);
return ip4;
}
std::string getIp6(const std::string& interface) {
std::string ip6 = "<unknown>";
struct ifaddrs* ifaddr;
if (getifaddrs(&ifaddr) == -1) {
return ip6;
}
for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr) {
continue;
}
if (ifa->ifa_addr->sa_family == AF_INET6 && interface == ifa->ifa_name) {
char ip[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr, ip, sizeof(ip));
if (std::strncmp(ip, "fe80", 4) == 0) {
ip6 = ip;
break;
}
}
}
freeifaddrs(ifaddr);
return ip6;
}
std::vector<Network> getAllNetworks() {
std::vector<Network> networks;
struct ifaddrs* ifaddr;
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
return networks;
}
for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr) continue;
if (ifa->ifa_addr->sa_family != AF_PACKET) continue;
std::string interface = ifa->ifa_name;
Network network;
network._index = getInterfaceIndex(interface);
network._description = getDescription(interface);
network._mac = getMac(interface);
network._ip4 = getIp4(interface);
network._ip6 = getIp6(interface);
networks.push_back(std::move(network));
}
freeifaddrs(ifaddr);
return networks;
}
} // namespace hwinfo
#endif

20
src/network.cpp Normal file
View File

@@ -0,0 +1,20 @@
#include <hwinfo/network.h>
namespace hwinfo {
// _____________________________________________________________________________________________________________________
const std::string& Network::interfaceIndex() const { return _index; }
// _____________________________________________________________________________________________________________________
const std::string& Network::description() const { return _description; }
// _____________________________________________________________________________________________________________________
const std::string& Network::mac() const { return _mac; }
// _____________________________________________________________________________________________________________________
const std::string& Network::ip4() const { return _ip4; }
// _____________________________________________________________________________________________________________________
const std::string& Network::ip6() const { return _ip6; }
} // namespace hwinfo

86
src/windows/network.cpp Normal file
View File

@@ -0,0 +1,86 @@
#include "hwinfo/platform.h"
#ifdef HWINFO_WINDOWS
#include <hwinfo/network.h>
#include <hwinfo/utils/stringutils.h>
#include <hwinfo/utils/wmi_wrapper.h>
namespace hwinfo {
// _____________________________________________________________________________________________________________________
std::vector<Network> getAllNetworks() {
utils::WMI::_WMI wmi;
const std::wstring query_string(
L"SELECT InterfaceIndex, IPAddress, Description, MACAddress "
L"FROM Win32_NetworkAdapterConfiguration");
bool success = wmi.execute_query(query_string);
if (!success) {
return {};
}
std::vector<Network> networks;
ULONG u_return = 0;
IWbemClassObject* obj = nullptr;
int network_id = 0;
while (wmi.enumerator) {
wmi.enumerator->Next(WBEM_INFINITE, 1, &obj, &u_return);
if (!u_return) {
break;
}
Network network;
VARIANT vt_prop;
HRESULT hr;
hr = obj->Get(L"InterfaceIndex", 0, &vt_prop, nullptr, nullptr);
if (SUCCEEDED(hr)) {
network._index = std::to_string(vt_prop.uintVal);
}
hr = obj->Get(L"IPAddress", 0, &vt_prop, nullptr, nullptr);
if (SUCCEEDED(hr)) {
if (vt_prop.vt == (VT_ARRAY | VT_BSTR)) {
LONG lbound, ubound;
SafeArrayGetLBound(vt_prop.parray, 1, &lbound);
SafeArrayGetUBound(vt_prop.parray, 1, &ubound);
std::string ipv4, ipv6;
for (LONG i = lbound; i <= ubound; ++i) {
BSTR bstr;
SafeArrayGetElement(vt_prop.parray, &i, &bstr);
std::wstring ws(bstr, SysStringLen(bstr));
std::string ip = utils::wstring_to_std_string(ws);
if (ip.find(':') != std::string::npos) {
if (ip.find("fe80::") == 0) {
ipv6 = ip;
} else {
ipv6 = "";
}
} else {
ipv4 = ip;
}
SysFreeString(bstr);
}
network._ip4 = ipv4;
network._ip6 = ipv6;
}
}
hr = obj->Get(L"Description", 0, &vt_prop, nullptr, nullptr);
if (SUCCEEDED(hr)) {
if (vt_prop.vt == VT_BSTR) {
network._description = utils::wstring_to_std_string(vt_prop.bstrVal);
}
}
hr = obj->Get(L"MACAddress", 0, &vt_prop, nullptr, nullptr);
if (SUCCEEDED(hr)) {
if (vt_prop.vt == VT_BSTR) {
network._mac = utils::wstring_to_std_string(vt_prop.bstrVal);
}
}
VariantClear(&vt_prop);
obj->Release();
networks.push_back(std::move(network));
}
return networks;
}
} // namespace hwinfo
#endif // HWINFO_WINDOWS