5 #if defined(_WIN32) || defined(_WIN64)
6 #define PLATFORM_WINDOWS
9 #pragma comment(lib, "iphlpapi.lib")
10 #elif defined(__APPLE__) && defined(__MACH__)
11 #define PLATFORM_MACOS
12 #include <sys/socket.h>
13 #include <sys/sysctl.h>
15 #include <net/if_dl.h>
17 #include <arpa/inet.h>
18 #elif defined(__linux__)
19 #define PLATFORM_LINUX
20 #include <sys/ioctl.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
28 #error "Unsupported platform"
39 if (ifname ==
nullptr) {
43 int sock = socket(AF_INET, SOCK_DGRAM, 0);
49 std::memset(&ifr, 0,
sizeof(ifr));
50 std::strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
51 ifr.ifr_name[IFNAMSIZ - 1] =
'\0';
53 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
61 std::memcpy(mac.data(), ifr.ifr_hwaddr.sa_data, 6);
67 struct ifaddrs* ifaddr =
nullptr;
68 struct ifaddrs* ifa =
nullptr;
70 if (getifaddrs(&ifaddr) == -1) {
77 for (ifa = ifaddr; ifa !=
nullptr; ifa = ifa->ifa_next) {
78 if (ifa->ifa_addr ==
nullptr) {
83 if (std::strcmp(ifa->ifa_name,
"lo") == 0) {
91 for (
size_t i = 0; i < 6; ++i) {
109 #elif defined(PLATFORM_MACOS)
115 if (ifname ==
nullptr) {
119 struct ifaddrs* ifaddr =
nullptr;
120 struct ifaddrs* ifa =
nullptr;
122 if (getifaddrs(&ifaddr) == -1) {
128 for (ifa = ifaddr; ifa !=
nullptr; ifa = ifa->ifa_next) {
129 if (ifa->ifa_addr ==
nullptr) {
134 if (std::strcmp(ifa->ifa_name, ifname) != 0) {
139 if (ifa->ifa_addr->sa_family == AF_LINK) {
140 struct sockaddr_dl* sdl =
reinterpret_cast<struct sockaddr_dl*
>(ifa->ifa_addr);
142 if (sdl->sdl_alen == 6) {
143 unsigned char* ptr =
reinterpret_cast<unsigned char*
>(LLADDR(sdl));
144 std::memcpy(mac.data(), ptr, 6);
156 struct ifaddrs* ifaddr =
nullptr;
157 struct ifaddrs* ifa =
nullptr;
159 if (getifaddrs(&ifaddr) == -1) {
165 for (ifa = ifaddr; ifa !=
nullptr; ifa = ifa->ifa_next) {
166 if (ifa->ifa_addr ==
nullptr) {
171 if (std::strcmp(ifa->ifa_name,
"lo0") == 0) {
176 if (ifa->ifa_addr->sa_family == AF_LINK) {
177 struct sockaddr_dl* sdl =
reinterpret_cast<struct sockaddr_dl*
>(ifa->ifa_addr);
179 if (sdl->sdl_alen == 6) {
180 unsigned char* ptr =
reinterpret_cast<unsigned char*
>(LLADDR(sdl));
184 for (
int i = 0; i < 6; ++i) {
192 std::memcpy(mac.data(), ptr, 6);
204 #elif defined(PLATFORM_WINDOWS)
210 if (ifname ==
nullptr) {
214 ULONG bufferSize = 15000;
215 PIP_ADAPTER_INFO adapterInfo =
nullptr;
216 PIP_ADAPTER_INFO adapter =
nullptr;
218 adapterInfo =
reinterpret_cast<IP_ADAPTER_INFO*
>(
new BYTE[bufferSize]);
220 if (GetAdaptersInfo(adapterInfo, &bufferSize) == ERROR_BUFFER_OVERFLOW) {
221 delete[]
reinterpret_cast<BYTE*
>(adapterInfo);
222 adapterInfo =
reinterpret_cast<IP_ADAPTER_INFO*
>(
new BYTE[bufferSize]);
227 if (GetAdaptersInfo(adapterInfo, &bufferSize) == NO_ERROR) {
228 adapter = adapterInfo;
232 if (std::strcmp(adapter->AdapterName, ifname) == 0 ||
233 std::strcmp(adapter->Description, ifname) == 0) {
235 if (adapter->AddressLength == 6) {
236 std::memcpy(mac.data(), adapter->Address, 6);
241 adapter = adapter->Next;
245 delete[]
reinterpret_cast<BYTE*
>(adapterInfo);
250 ULONG bufferSize = 15000;
251 PIP_ADAPTER_INFO adapterInfo =
nullptr;
252 PIP_ADAPTER_INFO adapter =
nullptr;
254 adapterInfo =
reinterpret_cast<IP_ADAPTER_INFO*
>(
new BYTE[bufferSize]);
256 if (GetAdaptersInfo(adapterInfo, &bufferSize) == ERROR_BUFFER_OVERFLOW) {
257 delete[]
reinterpret_cast<BYTE*
>(adapterInfo);
258 adapterInfo =
reinterpret_cast<IP_ADAPTER_INFO*
>(
new BYTE[bufferSize]);
263 if (GetAdaptersInfo(adapterInfo, &bufferSize) == NO_ERROR) {
264 adapter = adapterInfo;
268 if (adapter->AddressLength == 6) {
271 for (UINT i = 0; i < 6; ++i) {
272 if (adapter->Address[i] != 0) {
278 if (!isZero && adapter->Type == MIB_IF_TYPE_ETHERNET) {
279 std::memcpy(mac.data(), adapter->Address, 6);
284 adapter = adapter->Next;
288 delete[]
reinterpret_cast<BYTE*
>(adapterInfo);
bool getFirstMacAddress(MacAddress &mac)
Retrieves the MAC address of the first available network interface.
bool getMacAddress(const char *ifname, MacAddress &mac)
std::array< uint8_t, 6 > MacAddress
Type alias for MAC address (6 bytes)