Skip to content

Commit

Permalink
add network information(include interface index, MAC, Description, IP…
Browse files Browse the repository at this point in the history
…v4, IPv6), already tested on Windows and Linux (#112)
  • Loading branch information
MRsoymilk authored Oct 15, 2024
1 parent 5ca79cd commit cf9fa44
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 0 deletions.
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

0 comments on commit cf9fa44

Please sign in to comment.