interface.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #include "interface.h"
  2. #include <util/string/ascii.h>
  3. #if defined(_unix_)
  4. #include <ifaddrs.h>
  5. #endif
  6. #ifdef _win_
  7. #include <iphlpapi.h>
  8. #pragma comment(lib, "Iphlpapi.lib")
  9. #endif
  10. namespace NAddr {
  11. static bool IsInetAddress(sockaddr* addr) {
  12. return (addr != nullptr) && ((addr->sa_family == AF_INET) || (addr->sa_family == AF_INET6));
  13. }
  14. TNetworkInterfaceList GetNetworkInterfaces() {
  15. TNetworkInterfaceList result;
  16. #ifdef _win_
  17. TVector<char> buf;
  18. buf.resize(1000000);
  19. PIP_ADAPTER_ADDRESSES adapterBuf = (PIP_ADAPTER_ADDRESSES)&buf[0];
  20. ULONG bufSize = buf.ysize();
  21. if (GetAdaptersAddresses(AF_UNSPEC, 0, nullptr, adapterBuf, &bufSize) == ERROR_SUCCESS) {
  22. for (PIP_ADAPTER_ADDRESSES ptr = adapterBuf; ptr != 0; ptr = ptr->Next) {
  23. // The check below makes code working on Vista+
  24. if ((ptr->Flags & (IP_ADAPTER_IPV4_ENABLED | IP_ADAPTER_IPV6_ENABLED)) == 0) {
  25. continue;
  26. }
  27. if (ptr->IfType == IF_TYPE_TUNNEL) {
  28. // ignore tunnels
  29. continue;
  30. }
  31. if (ptr->OperStatus != IfOperStatusUp) {
  32. // ignore disable adapters
  33. continue;
  34. }
  35. for (IP_ADAPTER_UNICAST_ADDRESS* addr = ptr->FirstUnicastAddress; addr != 0; addr = addr->Next) {
  36. sockaddr* a = (sockaddr*)addr->Address.lpSockaddr;
  37. if (IsInetAddress(a)) {
  38. TNetworkInterface networkInterface;
  39. // Not very efficient but straightforward
  40. wchar_t* it = ptr->FriendlyName;
  41. while (*it != '\0') {
  42. networkInterface.Name += IsAscii(*it) ? static_cast<char>(*it) : '?';
  43. ++it;
  44. }
  45. networkInterface.Address = new TOpaqueAddr(a);
  46. result.push_back(networkInterface);
  47. }
  48. }
  49. }
  50. }
  51. #else
  52. ifaddrs* ifap;
  53. if (getifaddrs(&ifap) != -1) {
  54. for (ifaddrs* ifa = ifap; ifa != nullptr; ifa = ifa->ifa_next) {
  55. if (IsInetAddress(ifa->ifa_addr)) {
  56. TNetworkInterface interface;
  57. interface.Name = ifa->ifa_name;
  58. interface.Address = new TOpaqueAddr(ifa->ifa_addr);
  59. if (IsInetAddress(ifa->ifa_netmask)) {
  60. interface.Mask = new TOpaqueAddr(ifa->ifa_netmask);
  61. }
  62. result.push_back(interface);
  63. }
  64. }
  65. freeifaddrs(ifap);
  66. }
  67. #endif
  68. return result;
  69. }
  70. }