Netif.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #include "pch.h"
  2. #include <WinSock2.h>
  3. #include <iphlpapi.h>
  4. #include "Netif.h"
  5. #if __has_include("Netif.g.cpp")
  6. #include "Netif.g.cpp"
  7. #endif
  8. constexpr auto WORKING_BUFFER_SIZE = 15000;
  9. constexpr auto ADDR_BUFFER_SIZE = 64;
  10. constexpr auto MAX_TRIES = 3;
  11. #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
  12. #define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
  13. namespace winrt::Maple_App::implementation
  14. {
  15. Netif::Netif(const hstring& desc, const hstring& Addr)
  16. : m_desc(desc), m_addr(Addr)
  17. {
  18. }
  19. hstring Netif::Desc()
  20. {
  21. return m_desc;
  22. }
  23. hstring Netif::Addr()
  24. {
  25. return m_addr;
  26. }
  27. std::vector<Maple_App::Netif> Netif::EnumerateInterfaces() {
  28. /* Declare and initialize variables */
  29. DWORD dwRetVal = 0;
  30. unsigned int i = 0;
  31. // Set the flags to pass to GetAdaptersAddresses
  32. ULONG flags =
  33. GAA_FLAG_SKIP_ANYCAST
  34. | GAA_FLAG_SKIP_MULTICAST
  35. | GAA_FLAG_SKIP_DNS_SERVER
  36. | GAA_FLAG_SKIP_FRIENDLY_NAME;
  37. // default to unspecified address family (both)
  38. ULONG family = AF_INET;
  39. PIP_ADAPTER_ADDRESSES pAddresses = NULL;
  40. ULONG outBufLen = 0;
  41. ULONG Iterations = 0;
  42. PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
  43. PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
  44. // Allocate a 15 KB buffer to start with.
  45. outBufLen = WORKING_BUFFER_SIZE;
  46. std::array<WCHAR, ADDR_BUFFER_SIZE> addrBuf{};
  47. const auto& sniffed = Netif::SniffOutboundAddress();
  48. do {
  49. pAddresses = (IP_ADAPTER_ADDRESSES*)MALLOC(outBufLen);
  50. if (pAddresses == NULL) {
  51. throw std::bad_alloc{};
  52. }
  53. dwRetVal =
  54. GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
  55. if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
  56. FREE(pAddresses);
  57. pAddresses = NULL;
  58. }
  59. else {
  60. break;
  61. }
  62. Iterations++;
  63. } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));
  64. if (dwRetVal != NO_ERROR) {
  65. if (pAddresses) {
  66. FREE(pAddresses);
  67. }
  68. return {};
  69. }
  70. // If successful, output some information from the data we received
  71. std::vector<Maple_App::Netif> ret;
  72. pCurrAddresses = pAddresses;
  73. while (pCurrAddresses) {
  74. if (!(pCurrAddresses->Flags & IP_ADAPTER_IPV4_ENABLED)) {
  75. pCurrAddresses = pCurrAddresses->Next;
  76. continue;
  77. }
  78. const auto& friendlyName = to_hstring(pCurrAddresses->FriendlyName);
  79. pUnicast = pCurrAddresses->FirstUnicastAddress;
  80. if (pUnicast != NULL) {
  81. for (i = 0; pUnicast != NULL; i++) {
  82. // pUnicast->Address.lpSockaddr->sa_family;
  83. auto bufSize = static_cast<DWORD>(addrBuf.size());
  84. if (FAILED(WSAAddressToStringW(pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength, nullptr, addrBuf.data(), &bufSize))) {
  85. pUnicast = pUnicast->Next;
  86. continue;
  87. }
  88. if (bufSize > 0) {
  89. bufSize--;
  90. }
  91. hstring addr(addrBuf.data(), bufSize);
  92. hstring desc = addr == sniffed ? L"★" : L"";
  93. desc = desc + friendlyName + L" (" + addr + L")";
  94. ret.emplace_back(winrt::make<Netif>(desc, addr));
  95. pUnicast = pUnicast->Next;
  96. }
  97. }
  98. pCurrAddresses = pCurrAddresses->Next;
  99. }
  100. FREE(pAddresses);
  101. return ret;
  102. }
  103. hstring Netif::SniffOutboundAddress()
  104. {
  105. const auto s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  106. if (s == INVALID_SOCKET) {
  107. return {};
  108. }
  109. sockaddr saddr{};
  110. saddr.sa_family = AF_INET;
  111. saddr.sa_data[1] = 53;
  112. memset(&saddr.sa_data[2], 8, 4);
  113. if (connect(s, &saddr, sizeof(saddr)) == SOCKET_ERROR) {
  114. return {};
  115. }
  116. sockaddr_storage localAddr{};
  117. int localAddrLen = sizeof(localAddr);
  118. getsockname(s, (sockaddr*)&localAddr, &localAddrLen);
  119. localAddr.__ss_pad1[0] = 0;
  120. localAddr.__ss_pad1[1] = 0;
  121. std::array<WCHAR, ADDR_BUFFER_SIZE> addrBuf{};
  122. auto bufSize = static_cast<DWORD>(addrBuf.size());
  123. if (FAILED(WSAAddressToStringW((LPSOCKADDR)&localAddr, localAddrLen, nullptr, addrBuf.data(), &bufSize))) {
  124. return {};
  125. }
  126. if (bufSize > 0) {
  127. bufSize--;
  128. }
  129. return hstring(addrBuf.data(), bufSize);
  130. }
  131. }