bool UtilAll::macAddress()

in cpp/source/base/UtilAll.cpp [54:130]


bool UtilAll::macAddress(std::vector<unsigned char>& mac) {
  static std::vector<unsigned char> cache;
  static bool mac_cached = false;

  if (mac_cached) {
    mac = cache;
    return true;
  }

#ifndef _WIN32
  struct ifaddrs *head = nullptr, *node;
  if (getifaddrs(&head)) {
    return false;
  }

  for (node = head; node; node = node->ifa_next) {
    if (node->ifa_addr->sa_family == AF_FAMILY) {
#if defined(__APPLE__)
      auto* ptr = reinterpret_cast<unsigned char*>(LLADDR(reinterpret_cast<struct sockaddr_dl*>(node->ifa_addr)));
#elif defined(__linux__)
      auto* ptr = reinterpret_cast<unsigned char*>(reinterpret_cast<struct sockaddr_ll*>(node->ifa_addr)->sll_addr);
#endif
      bool all_zero = true;
      for (int i = 0; i < 6; i++) {
        if (*(ptr + i) != 0) {
          all_zero = false;
          break;
        }
      }
      if (all_zero) {
        SPDLOG_TRACE("Skip MAC address of network interface {}", node->ifa_name);
        continue;
      }
      SPDLOG_DEBUG("Use MAC address of network interface {}", node->ifa_name);
      // MAC address has 48 bits
      cache.resize(6);
      memcpy(cache.data(), ptr, 6);
      mac_cached = true;
      mac = cache;
      break;
    }
  }
  freeifaddrs(head);
  return true;
#else
  PIP_ADAPTER_INFO adaptor_info;
  DWORD buf_len = sizeof(IP_ADAPTER_INFO);
  char mac_address[18];
  adaptor_info = (IP_ADAPTER_INFO*)malloc(buf_len);
  if (!adaptor_info) {
    // TODO: running out of memory
  }

  if (GetAdaptersInfo(adaptor_info, &buf_len) == NO_ERROR) {
    PIP_ADAPTER_INFO item = adaptor_info;
    do {
      bool all_zero = true;
      for (auto& b : item->Address) {
        if (b != 0) {
          all_zero = false;
          break;
        }
      }
      if (!all_zero) {
        cache.resize(6);
        memcpy(cache.data(), item->Address, 6);
        mac_cached = true;
        mac = cache;
        break;
      }
      item = item->Next;
    } while (item);
  } else {
    free(adaptor_info);
  }
#endif
}