Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
27 changes: 27 additions & 0 deletions examples/system_infoMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
1 change: 1 addition & 0 deletions include/hwinfo/hwinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 34 additions & 0 deletions include/hwinfo/network.h
Original file line number Diff line number Diff line change
@@ -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
34 changes: 34 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions src/apple/network.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 106 additions & 0 deletions src/linux/network.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions src/network.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 86 additions & 0 deletions src/windows/network.cpp
Original file line number Diff line number Diff line change
@@ -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
Loading