From 85457e65f6ad95edcb0e25fa4f73b5aafe5498ac Mon Sep 17 00:00:00 2001 From: MRsoymilk Date: Tue, 15 Oct 2024 01:11:19 +0800 Subject: [PATCH] add network information --- CMakeLists.txt | 1 + examples/system_infoMain.cpp | 27 +++++++++ include/hwinfo/hwinfo.h | 1 + include/hwinfo/network.h | 34 +++++++++++ src/CMakeLists.txt | 34 +++++++++++ src/apple/network.cpp | 12 ++++ src/linux/network.cpp | 106 +++++++++++++++++++++++++++++++++ src/linux/os.cpp | 2 +- src/linux/utils/filesystem.cpp | 2 +- src/network.cpp | 20 +++++++ src/windows/network.cpp | 86 ++++++++++++++++++++++++++ 11 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 include/hwinfo/network.h create mode 100644 src/apple/network.cpp create mode 100644 src/linux/network.cpp create mode 100644 src/network.cpp create mode 100644 src/windows/network.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c307cfc..465949c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/examples/system_infoMain.cpp b/examples/system_infoMain.cpp index f616697..2190520 100644 --- a/examples/system_infoMain.cpp +++ b/examples/system_infoMain.cpp @@ -179,5 +179,32 @@ int main(int argc, char** argv) { } else { fmt::print("No Disks installed or detected\n"); } + + std::vector 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; } diff --git a/include/hwinfo/hwinfo.h b/include/hwinfo/hwinfo.h index 5abf38a..7ae5de2 100644 --- a/include/hwinfo/hwinfo.h +++ b/include/hwinfo/hwinfo.h @@ -8,5 +8,6 @@ #include #include #include +#include #include #include diff --git a/include/hwinfo/network.h b/include/hwinfo/network.h new file mode 100644 index 0000000..639f053 --- /dev/null +++ b/include/hwinfo/network.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include +#include + +namespace hwinfo { + +class HWINFO_API Network { + friend std::vector 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 getAllNetworks(); + +} // namespace hwinfo \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1233817..212a808 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 $ $) + + + + 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 diff --git a/src/apple/network.cpp b/src/apple/network.cpp new file mode 100644 index 0000000..9eef550 --- /dev/null +++ b/src/apple/network.cpp @@ -0,0 +1,12 @@ +#include + +#ifdef HWINFO_APPLE +#include +namespace hwinfo { +std::vector getAllNetworks() { + std::vector networks; + return networks; +} +} // namespace hwinfo + +#endif // HWINFO_APPLE diff --git a/src/linux/network.cpp b/src/linux/network.cpp new file mode 100644 index 0000000..5678a93 --- /dev/null +++ b/src/linux/network.cpp @@ -0,0 +1,106 @@ +#include + +#ifdef HWINFO_UNIX +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace hwinfo { + +std::string getInterfaceIndex(const std::string& path) { + int index = if_nametoindex(path.c_str()); + return (index > 0) ? std::to_string(index) : ""; +} + +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() ? "" : mac; +} + +std::string getIp4(const std::string& interface) { + std::string ip4 = ""; + 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 = ""; + 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 getAllNetworks() { + std::vector 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 diff --git a/src/linux/os.cpp b/src/linux/os.cpp index af20e8c..0dfa430 100644 --- a/src/linux/os.cpp +++ b/src/linux/os.cpp @@ -48,7 +48,7 @@ OS::OS() { } } { // architecture - struct stat buffer {}; + struct stat buffer{}; _64bit = stat("/lib64/ld-linux-x86-64.so.2", &buffer) == 0; _32bit = !_64bit; } diff --git a/src/linux/utils/filesystem.cpp b/src/linux/utils/filesystem.cpp index 7d996e9..ab601c5 100644 --- a/src/linux/utils/filesystem.cpp +++ b/src/linux/utils/filesystem.cpp @@ -19,7 +19,7 @@ namespace hwinfo { namespace filesystem { bool exists(const std::string& path) { - struct stat sb {}; + struct stat sb{}; return stat(path.c_str(), &sb) == 0; } diff --git a/src/network.cpp b/src/network.cpp new file mode 100644 index 0000000..bfbec8d --- /dev/null +++ b/src/network.cpp @@ -0,0 +1,20 @@ + +#include +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 diff --git a/src/windows/network.cpp b/src/windows/network.cpp new file mode 100644 index 0000000..5e2c97d --- /dev/null +++ b/src/windows/network.cpp @@ -0,0 +1,86 @@ +#include "hwinfo/platform.h" + +#ifdef HWINFO_WINDOWS + +#include +#include +#include + +namespace hwinfo { + +// _____________________________________________________________________________________________________________________ +std::vector 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 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 \ No newline at end of file