4#include "Stroika/Foundation/StroikaPreComp.h"
10#if qStroika_Foundation_Common_Platform_POSIX
12#include <net/if_arp.h>
14#include <netinet/in.h>
16#include <sys/socket.h>
18#if qStroika_Foundation_Common_Platform_Linux
19#include <linux/ethtool.h>
20#include <linux/sockios.h>
21#include <linux/wireless.h>
22#elif qStroika_Foundation_Common_Platform_MacOS
25#elif qStroika_Foundation_Common_Platform_Windows
40#include "Stroika/Foundation/Containers/Collection.h"
41#include "Stroika/Foundation/Containers/KeyedCollection.h"
42#include "Stroika/Foundation/Containers/Mapping.h"
45#include "Stroika/Foundation/Execution/Exceptions.h"
47#if qStroika_Foundation_Common_Platform_Windows
48#include "Stroika/Foundation/../Foundation/Execution/Platform/Windows/Exception.h"
50#include "Stroika/Foundation/Execution/ProcessRunner.h"
55#include "Stroika/Foundation/Streams/MemoryStream.h"
67using namespace Stroika::Foundation::Memory;
68using namespace Stroika::Foundation::IO;
78#pragma comment(lib, "Iphlpapi.lib")
84 auto PrintMacAddr_ (
const uint8_t* macaddrBytes, [[maybe_unused]]
const uint8_t* macaddrBytesEnd) ->
String
86 Require (macaddrBytesEnd - macaddrBytes == 6);
88 (void)snprintf (buf,
sizeof (buf),
"%02x:%02x:%02x:%02x:%02x:%02x", macaddrBytes[0], macaddrBytes[1], macaddrBytes[2],
89 macaddrBytes[3], macaddrBytes[4], macaddrBytes[5]);
90 Assert (::strlen (buf) < NEltsOf (buf));
104 sb <<
"SSID: "sv << fSSID;
105 sb <<
", State: "sv << fState;
106 sb <<
", ConnectionMode: "sv << fConnectionMode;
107 sb <<
", ProfileName: "sv << fProfileName;
108 sb <<
", BSSType: "sv << fBSSType;
109 sb <<
", MACAddress: "sv << fMACAddress;
110 sb <<
", PhysicalConnectionType: "sv << fPhysicalConnectionType;
112 sb <<
", SecurityEnabled: "sv << fSecurityEnabled;
113 sb <<
", 8021XEnabled: "sv << f8021XEnabled;
114 sb <<
", AuthAlgorithm: "sv << fAuthAlgorithm;
115 sb <<
", Cipher: "sv << fCipher;
125String Interface::Bindings::ToString ()
const
129 sb <<
"BoundAddressRanges: "sv << fAddressRanges;
130 sb <<
", BoundAddresses: "sv << fAddresses;
144#if qStroika_Foundation_Common_Platform_POSIX
145 sb <<
", InterfaceName: "sv << GetInterfaceName ();
155 sb <<
", Type: "sv << *fType;
167 sb <<
", Wireless-Info: "sv << fWirelessInfo;
174 sb <<
", Status: "sv << *
fStatus;
185#if qStroika_Foundation_Common_Platform_POSIX
191#if qMacUBSanitizerifreqAlignmentIssue_Buggy
192 Stroika_Foundation_Debug_ATTRIBUTE_NO_SANITIZE_UNDEFINED
195 GetInterfaces_POSIX_mkInterface_ (
int sd,
const ifreq* i, optional<Interface> prevInterfaceObject2Update)
200 auto getFlags = [] (
int sd,
const char* name) {
202 CString::Copy (ifreq.ifr_name, NEltsOf (ifreq.ifr_name), name);
203 int r = ::ioctl (sd, SIOCGIFFLAGS, (
char*)&ifreq);
204 Assert (r == 0 or errno == ENXIO);
205 return r == 0 ? ifreq.ifr_flags : 0;
207 int flags = getFlags (sd, i->ifr_name);
208#if qStroika_Foundation_Common_Platform_Linux
209 auto getWirelessFlag = [] (
int sd,
const char* name) ->
bool {
210#if defined(SIOCGIWNAME)
212 CString::Copy (pwrq.ifr_name, NEltsOf (pwrq.ifr_name), name);
213 int r = ::ioctl (sd, SIOCGIWNAME, (
char*)&pwrq);
220 if (flags & IFF_LOOPBACK) {
221 newInterface.fType = Interface::Type::eLoopback;
223#if qStroika_Foundation_Common_Platform_Linux
224 else if (getWirelessFlag (sd, i->ifr_name)) {
225 newInterface.fType = Interface::Type::eWIFI;
230 newInterface.fType = Interface::Type::eWiredEthernet;
233#if qStroika_Foundation_Common_Platform_Linux
236 if (::ioctl (sd, SIOCGIFHWADDR, &tmp) == 0 and tmp.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
237 newInterface.
fHardwareAddress = PrintMacAddr_ (
reinterpret_cast<const uint8_t*
> (tmp.ifr_hwaddr.sa_data),
238 reinterpret_cast<const uint8_t*
> (tmp.ifr_hwaddr.sa_data) + 6);
243#if qStroika_Foundation_Common_Platform_Linux || qStroika_Foundation_Common_Platform_MacOS
244 auto getNetMaskAsPrefix = [] (
int sd,
const char* name) -> optional<unsigned int> {
246 CString::Copy (ifreq.ifr_name, NEltsOf (ifreq.ifr_name), name);
247 int r = ::ioctl (sd, SIOCGIFNETMASK, (
char*)&ifreq);
250#if qStroika_Foundation_Common_Platform_Linux
252#elif qStroika_Foundation_Common_Platform_MacOS
255 if (sa.IsInternetAddress ()) {
258 for (
bool b : ia.As<vector<bool>> ()) {
273#if qStroika_Foundation_Common_Platform_Linux || qStroika_Foundation_Common_Platform_MacOS
274 auto getDefaultGateway = [] (
const char* name) -> optional<InternetAddress> {
276#if qStroika_Foundation_Common_Platform_Linux
278 static const filesystem::path kFileName_{
"/proc/net/route"};
288 reader.ReadMatrix (FileInputStream::New (kFileName_, IO::FileSystem::FileInputStream::eNotSeekable))) {
292 swscanf (line[2].As<wstring> ().c_str (), L
"%02x%02x%02x%02x", &tmp[3], &tmp[2], &tmp[1], &tmp[0]);
293 return InternetAddress{
static_cast<byte> (tmp[0]),
static_cast<byte> (tmp[1]),
static_cast<byte> (tmp[2]),
294 static_cast<byte> (tmp[3])};
297#elif qStroika_Foundation_Common_Platform_MacOS
314 pr.Run (
nullptr, useStdOut);
316 optional<String> forInterface;
317 optional<String> gateway;
319 if (line.size () == 2 and line[0] ==
"interface"sv) {
320 forInterface = line[1];
322 else if (line.size () == 2 and line[0] ==
"gateway"sv) {
335 if (not s.empty ()) {
340 DbgTrace (
"got exception converting gateway to address (dns): {}"_f, current_exception ());
350 if (
auto gw = getDefaultGateway (i->ifr_name)) {
352 if (not gws.Contains (*gw)) {
359#if qStroika_Foundation_Common_Platform_Linux
360 auto getSpeed = [] (
int sd,
const char* name) -> optional<uint64_t> {
362 CString::Copy (ifreq.ifr_name, NEltsOf (ifreq.ifr_name), name);
364 ifreq.ifr_data =
reinterpret_cast<caddr_t
> (&edata);
365 edata.cmd = ETHTOOL_GSET;
366 int r = ioctl (sd, SIOCETHTOOL, &ifreq);
368#if USE_NOISY_TRACE_IN_THIS_MODULE_
369 DbgTrace (
"No speed for interface {}, errno={}"_f, name, errno);
373 constexpr uint64_t kMegabit_ = 1000 * 1000;
374 switch (ethtool_cmd_speed (&edata)) {
376 return 10 * kMegabit_;
378 return 100 * kMegabit_;
380 return 1000 * kMegabit_;
382 return 2500 * kMegabit_;
384 return 10000 * kMegabit_;
395 if (flags & IFF_RUNNING) {
402#if qStroika_Foundation_Common_Platform_Linux
403 auto checkCarrierKnownSet = [] (
const char* id) ->
bool {
404#if !USE_NOISY_TRACE_IN_THIS_MODULE_
408 auto fs = FileInputStream::New (filesystem::path{
"/sys/class/net"} / id, IO::FileSystem::FileInputStream::eNotSeekable);
410 if (b.size () >= 1 and b[0] ==
static_cast<byte> (
'1')) {
418 if (checkCarrierKnownSet (i->ifr_name)) {
427 if (sa.IsInternetAddress ()) {
428#if qStroika_Foundation_Common_Platform_Linux || qStroika_Foundation_Common_Platform_MacOS
429 newInterface.
fBindings.fAddressRanges.Add (
CIDR{sa.GetInternetAddress (), getNetMaskAsPrefix (sd, i->ifr_name)});
431 newInterface.
fBindings.fAddressRanges.Add (sa.GetInternetAddress ());
433 newInterface.
fBindings.fAddresses.Add (sa.GetInternetAddress ());
436#if USE_NOISY_TRACE_IN_THIS_MODULE_
437 DbgTrace (
"GetInterfaces_POSIX_mkInterface_ returns {}"_f, newInterface);
441#if qMacUBSanitizerifreqAlignmentIssue_Buggy
442 Stroika_Foundation_Debug_ATTRIBUTE_NO_SANITIZE_UNDEFINED
445 GetInterfaces_POSIX_ ()
450 ifconf ifconf{
sizeof (ifreqs), {
reinterpret_cast<char*
> (ifreqs)}};
452 int sd = ::socket (PF_INET, SOCK_STREAM, 0);
454 [[maybe_unused]]
auto&& cleanup =
Execution::Finally ([sd] ()
noexcept { ::close (sd); });
456 [[maybe_unused]]
int r = ::ioctl (sd, SIOCGIFCONF, (
char*)&ifconf);
459 for (
const ifreq* i = std::begin (ifreqs);
460 reinterpret_cast<const char*
> (i) -
reinterpret_cast<const char*
> (std::begin (ifreqs)) < ifconf.ifc_len;) {
461#if USE_NOISY_TRACE_IN_THIS_MODULE_
462 DbgTrace (
"interface: ifr_name={}; ifr_addr.sa_family = {}"_f, i->ifr_name, i->ifr_addr.sa_family);
468 Interface newInterface = GetInterfaces_POSIX_mkInterface_ (sd, i, results.Lookup (interfaceName));
470 results.Add (newInterface);
478#if qStroika_Foundation_Common_Platform_Linux
479 size_t len =
sizeof (*i);
481 size_t len = IFNAMSIZ + i->ifr_addr.sa_len;
483 i =
reinterpret_cast<const ifreq*
> (
reinterpret_cast<const byte*
> (i) + len);
485 return move (results);
490#if qStroika_Foundation_Common_Platform_Windows
503 : fDLL{::LoadLibrary (_T (
"wlanapi.dll"))}
506 fWlanOpenHandle = (DWORD (WINAPI*) (_In_ DWORD dwClientVersion, _Reserved_ PVOID pReserved, _Out_ PDWORD pdwNegotiatedVersion,
507 _Out_ PHANDLE phClientHandle)) (::GetProcAddress (fDLL,
"WlanOpenHandle"));
509 (DWORD (WINAPI*) (_In_ HANDLE hClientHandle, _Reserved_ PVOID pReserved)) (::GetProcAddress (fDLL,
"WlanCloseHandle"));
510 fWlanFreeMemory = (DWORD (WINAPI*) (_In_ PVOID pMemory)) (::GetProcAddress (fDLL,
"WlanFreeMemory"));
511 fWlanEnumInterfaces =
512 (DWORD (WINAPI*) (_In_ HANDLE hClientHandle, _Reserved_ PVOID pReserved,
513 _Outptr_ PWLAN_INTERFACE_INFO_LIST * ppInterfaceList)) (::GetProcAddress (fDLL,
"WlanEnumInterfaces"));
514 fWlanQueryInterface =
515 (DWORD (WINAPI*) (_In_ HANDLE hClientHandle, _In_ CONST ::GUID * pInterfaceGuid, _In_ WLAN_INTF_OPCODE OpCode,
516 _Reserved_ PVOID pReserved, _Out_ PDWORD pdwDataSize, _Outptr_result_bytebuffer_ (*pdwDataSize) PVOID * ppData,
517 _Out_opt_ PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType)) (::GetProcAddress (fDLL,
"WlanQueryInterface"));
519 WLANAPI_ (
const WLANAPI_&) =
delete;
522 if (fDLL !=
nullptr) {
523 Verify (::FreeLibrary (fDLL));
527 DWORD (WINAPI* fWlanOpenHandle)
528 (_In_ DWORD dwClientVersion, _Reserved_ PVOID pReserved, _Out_ PDWORD pdwNegotiatedVersion, _Out_ PHANDLE phClientHandle) =
nullptr;
529 DWORD (WINAPI* fWlanCloseHandle)
530 (_In_ HANDLE hClientHandle, _Reserved_ PVOID pReserved) =
nullptr;
531 DWORD (WINAPI* fWlanFreeMemory)
532 (_In_ PVOID pMemory) =
nullptr;
533 DWORD (WINAPI* fWlanEnumInterfaces)
534 (_In_ HANDLE hClientHandle, _Reserved_ PVOID pReserved, _Outptr_ PWLAN_INTERFACE_INFO_LIST* ppInterfaceList) =
nullptr;
535 DWORD (WINAPI* fWlanQueryInterface)
536 (_In_ HANDLE hClientHandle, _In_ CONST ::GUID* pInterfaceGuid, _In_ WLAN_INTF_OPCODE OpCode, _Reserved_ PVOID pReserved, _Out_ PDWORD pdwDataSize,
537 _Outptr_result_bytebuffer_ (*pdwDataSize) PVOID* ppData, _Out_opt_ PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType) =
nullptr;
541 optional<uint64_t> fTransmitSpeedBaud;
542 optional<uint64_t> fReceiveLinkSpeedBaud;
549 static unique_ptr<WLANAPI_> sWlanAPI_;
550 static once_flag sOnceFlag_;
551 call_once (sOnceFlag_, [&] () { IgnoreExceptionsForCall (sWlanAPI_ = make_unique<WLANAPI_> ()) });
554 HANDLE hClient =
nullptr;
556 DWORD dwCurVersion = 0;
560 if (hClient !=
nullptr) {
561 sWlanAPI_->fWlanCloseHandle (hClient,
nullptr);
565 PWLAN_INTERFACE_INFO_LIST pIfList =
nullptr;
568 if (pIfList !=
nullptr) {
569 sWlanAPI_->fWlanFreeMemory (pIfList);
582 PWLAN_CONNECTION_ATTRIBUTES pConnectInfo{};
584 if (pConnectInfo !=
nullptr) {
585 sWlanAPI_->fWlanFreeMemory (pConnectInfo);
589 for (DWORD i = 0; i < pIfList->dwNumberOfItems; ++i) {
590 PWLAN_INTERFACE_INFO pIfInfo = (WLAN_INTERFACE_INFO*)&pIfList->InterfaceInfo[i];
591 WirelessInfoPlus_ wInfo;
596 case wlan_interface_state_not_ready:
597 return WirelessInfo::State::eNotReady;
598 case wlan_interface_state_connected:
599 return WirelessInfo::State::eConnected;
600 case wlan_interface_state_ad_hoc_network_formed:
601 return WirelessInfo::State::eAdHocNetworkFormed;
602 case wlan_interface_state_disconnecting:
603 return WirelessInfo::State::eDisconnecting;
604 case wlan_interface_state_disconnected:
605 return WirelessInfo::State::eDisconnected;
606 case wlan_interface_state_associating:
607 return WirelessInfo::State::eAssociating;
608 case wlan_interface_state_discovering:
609 return WirelessInfo::State::eDiscovering;
610 case wlan_interface_state_authenticating:
611 return WirelessInfo::State::eAuthenticating;
613 DbgTrace (
"Unknown state {}"_f,
static_cast<int> (s));
614 return WirelessInfo::State::eUnknown;
618 wInfo.fState = mapState (pIfInfo->isState);
622 if (pIfInfo->isState == wlan_interface_state_connected) {
624 DWORD connectInfoSize =
sizeof (WLAN_CONNECTION_ATTRIBUTES);
625 WLAN_OPCODE_VALUE_TYPE opCode = wlan_opcode_value_type_invalid;
627 sWlanAPI_->fWlanQueryInterface (hClient, &pIfInfo->InterfaceGuid, wlan_intf_opcode_current_connection,
nullptr,
628 &connectInfoSize, (PVOID*)&pConnectInfo, &opCode));
631 if (pConnectInfo->isState != pIfInfo->isState) {
632 DbgTrace (
"Not sure how these can differ (except for race condition) - but if they do, maybe worth looking into"_f);
637 case wlan_connection_mode_profile:
638 return WirelessInfo::ConnectionMode::eProfile;
639 case wlan_connection_mode_temporary_profile:
640 return WirelessInfo::ConnectionMode::eTemporaryProfile;
641 case wlan_connection_mode_discovery_secure:
642 return WirelessInfo::ConnectionMode::eDiscoverSecrure;
643 case wlan_connection_mode_discovery_unsecure:
644 return WirelessInfo::ConnectionMode::eDiscoverInsecure;
645 case wlan_connection_mode_auto:
646 return WirelessInfo::ConnectionMode::eAuto;
647 case wlan_connection_mode_invalid:
648 return WirelessInfo::ConnectionMode::eInvalid;
650 DbgTrace (
"Unknown connection mode {}"_f,
static_cast<int> (s));
651 return WirelessInfo::ConnectionMode::eUnknown;
654 wInfo.fConnectionMode = mapConnectionMode (pConnectInfo->wlanConnectionMode);
655 wInfo.fProfileName = pConnectInfo->strProfileName;
658 if (pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength != 0) {
660 span{
reinterpret_cast<const char*
> (pConnectInfo->wlanAssociationAttributes.dot11Ssid.ucSSID),
661 pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength});
666 case dot11_BSS_type_infrastructure:
667 return WirelessInfo::BSSType::eInfrastructure;
668 case dot11_BSS_type_independent:
669 return WirelessInfo::BSSType::eIndependent;
670 case dot11_BSS_type_any:
671 return WirelessInfo::BSSType::eAny;
673 DbgTrace (
"Unknown BSS mode {}"_f,
static_cast<int> (s));
674 return WirelessInfo::BSSType::eUnknown;
677 wInfo.fBSSType = mapBSSType (pConnectInfo->wlanAssociationAttributes.dot11BssType);
679 wInfo.fMACAddress = PrintMacAddr_ (std::begin (pConnectInfo->wlanAssociationAttributes.dot11Bssid),
680 std::end (pConnectInfo->wlanAssociationAttributes.dot11Bssid));
684 case dot11_phy_type_unknown:
685 return WirelessInfo::PhysicalConnectionType::eUnknown;
686 case dot11_phy_type_fhss:
687 return WirelessInfo::PhysicalConnectionType::eFHSS;
688 case dot11_phy_type_dsss:
689 return WirelessInfo::PhysicalConnectionType::eDSSS;
690 case dot11_phy_type_irbaseband:
691 return WirelessInfo::PhysicalConnectionType::eIRBaseBand;
692 case dot11_phy_type_ofdm:
693 return WirelessInfo::PhysicalConnectionType::e80211a;
694 case dot11_phy_type_hrdsss:
695 return WirelessInfo::PhysicalConnectionType::e80211b;
696 case dot11_phy_type_erp:
697 return WirelessInfo::PhysicalConnectionType::e80211g;
698 case dot11_phy_type_ht:
699 return WirelessInfo::PhysicalConnectionType::e80211n;
700 case dot11_phy_type_vht:
701 return WirelessInfo::PhysicalConnectionType::e80211ac;
702 case dot11_phy_type_dmg:
703 return WirelessInfo::PhysicalConnectionType::e80211ad;
704 case dot11_phy_type_he:
705 return WirelessInfo::PhysicalConnectionType::e80211ax;
707 DbgTrace (L
"Unknown DOT11_PHY_TYPE {}"_f,
static_cast<int> (s));
708 return WirelessInfo::PhysicalConnectionType::eUnknown;
711 wInfo.fPhysicalConnectionType = mapPhysicalConnectionType (pConnectInfo->wlanAssociationAttributes.dot11PhyType);
713 wInfo.fSignalQuality = pConnectInfo->wlanAssociationAttributes.wlanSignalQuality;
716 const ULONG kMagicFactor_{1000};
717 wInfo.fTransmitSpeedBaud = pConnectInfo->wlanAssociationAttributes.ulTxRate * kMagicFactor_;
718 wInfo.fReceiveLinkSpeedBaud = pConnectInfo->wlanAssociationAttributes.ulRxRate * kMagicFactor_;
721 wInfo.fSecurityEnabled = pConnectInfo->wlanSecurityAttributes.bSecurityEnabled;
722 wInfo.f8021XEnabled = pConnectInfo->wlanSecurityAttributes.bOneXEnabled;
725 case DOT11_AUTH_ALGO_80211_OPEN:
726 return WirelessInfo::AuthAlgorithm::eOpen;
727 case DOT11_AUTH_ALGO_80211_SHARED_KEY:
728 return WirelessInfo::AuthAlgorithm::ePresharedKey;
729 case DOT11_AUTH_ALGO_WPA:
730 return WirelessInfo::AuthAlgorithm::eWPA;
731 case DOT11_AUTH_ALGO_WPA_PSK:
732 return WirelessInfo::AuthAlgorithm::eWPA_PSK;
733 case DOT11_AUTH_ALGO_WPA_NONE:
734 return WirelessInfo::AuthAlgorithm::eWPA_NONE;
735 case DOT11_AUTH_ALGO_RSNA:
736 return WirelessInfo::AuthAlgorithm::eRSNA;
737 case DOT11_AUTH_ALGO_RSNA_PSK:
738 return WirelessInfo::AuthAlgorithm::eRSNA_PSK;
740 DbgTrace (L
"Unknown AuthAlgorithm {}"_f,
static_cast<int> (s));
741 return WirelessInfo::AuthAlgorithm::eUnknown;
744 wInfo.fAuthAlgorithm = mapAuthAlgorithm (pConnectInfo->wlanSecurityAttributes.dot11AuthAlgorithm);
746 auto mapCipher = [] (DOT11_CIPHER_ALGORITHM s) ->
String {
748 case DOT11_CIPHER_ALGO_NONE:
750 case DOT11_CIPHER_ALGO_WEP40:
752 case DOT11_CIPHER_ALGO_TKIP:
754 case DOT11_CIPHER_ALGO_CCMP:
756 case DOT11_CIPHER_ALGO_WEP104:
758 case DOT11_CIPHER_ALGO_WEP:
761 return "{}"_f(
static_cast<int> (s));
764 wInfo.fCipher = mapCipher (pConnectInfo->wlanSecurityAttributes.dot11CipherAlgorithm);
765 results.
Add (interfaceGUID, wInfo);
777 wirelessInfo2Merge = GetInterfaces_Windows_WirelessInfo_ ();
779 catch (
const std::system_error& e) {
780 if (e.code () == error_code{ERROR_SERVICE_NOT_ACTIVE, system_category ()}) {
789 ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS;
790 ULONG family = AF_UNSPEC;
793 ULONG ulOutBufLen =
static_cast<ULONG
> (buf.
GetSize ());
794 PIP_ADAPTER_ADDRESSES pAddresses =
reinterpret_cast<PIP_ADAPTER_ADDRESSES
> (buf.begin ());
800 DWORD dwRetVal = ::GetAdaptersAddresses (family, flags,
nullptr, pAddresses, &ulOutBufLen);
801 if (dwRetVal == NO_ERROR) {
802 for (PIP_ADAPTER_ADDRESSES currAddresses = pAddresses; currAddresses !=
nullptr; currAddresses = currAddresses->Next) {
810 if (memcmp (&currAddresses->NetworkGuid, &kZeroGUID_, sizeof (kZeroGUID_)) != 0) {
813 switch (currAddresses->IfType) {
814 case IF_TYPE_SOFTWARE_LOOPBACK:
815 newInterface.fType = Interface::Type::eLoopback;
817 case IF_TYPE_IEEE80211:
818 newInterface.fType = Interface::Type::eWIFI;
820 case IF_TYPE_ETHERNET_CSMACD:
821 if (newInterface.
fDescription->Contains (
"VirtualBox Host-Only Ethernet Adapter"sv) or
822 newInterface.
fDescription->Contains (
"Hyper-V Virtual Ethernet Adapter"sv)) {
824 newInterface.fType = Interface::Type::eDeviceVirtualInternalNetwork;
827 newInterface.fType = Interface::Type::eWiredEthernet;
831 DbgTrace (
"Treating unknown currAddresses->IfType = {} type as eOther"_f, currAddresses->IfType);
832 newInterface.fType = Interface::Type::eOther;
835 if (currAddresses->TunnelType != TUNNEL_TYPE_NONE) {
836 if (newInterface.fType) {
837 DbgTrace (
"overwriting type {} with tunneltype"_f, newInterface.fType);
839 newInterface.fType = Interface::Type::eTunnel;
841 switch (currAddresses->OperStatus) {
843 newInterface.
fStatus = Memory::NullCoalesce (newInterface.
fStatus) +
846 case IfOperStatusDown:
847 newInterface.
fStatus = Memory::NullCoalesce (newInterface.
fStatus);
849 case IfOperStatusDormant:
850 case IfOperStatusLowerLayerDown:
856 DbgTrace (
"ignoring unrecognized status: {}"_f,
static_cast<int> (currAddresses->OperStatus));
859 for (PIP_ADAPTER_UNICAST_ADDRESS pu = currAddresses->FirstUnicastAddress; pu !=
nullptr; pu = pu->Next) {
861 if (sa.IsInternetAddress ()) {
862 newInterface.
fBindings.fAddressRanges.Add (
863 pu->OnLinkPrefixLength == 255 ? sa.GetInternetAddress () :
CIDR{sa.GetInternetAddress (), pu->OnLinkPrefixLength});
864 newInterface.
fBindings.fAddresses.Add (sa.GetInternetAddress ());
867 for (PIP_ADAPTER_ANYCAST_ADDRESS pa = currAddresses->FirstAnycastAddress; pa !=
nullptr; pa = pa->Next) {
869 if (sa.IsInternetAddress ()) {
870 newInterface.
fBindings.fAddressRanges.Add (sa.GetInternetAddress ());
871 newInterface.
fBindings.fAddresses.Add (sa.GetInternetAddress ());
874 for (PIP_ADAPTER_MULTICAST_ADDRESS pm = currAddresses->FirstMulticastAddress; pm !=
nullptr; pm = pm->Next) {
876 if (sa.IsInternetAddress ()) {
877 newInterface.
fBindings.fAddressRanges.Add (sa.GetInternetAddress ());
878 newInterface.
fBindings.fAddresses.Add (sa.GetInternetAddress ());
881 for (PIP_ADAPTER_GATEWAY_ADDRESS_LH pa = currAddresses->FirstGatewayAddress; pa !=
nullptr; pa = pa->Next) {
883 if (sa.IsInternetAddress ()) {
885 if (not gws.Contains (sa.GetInternetAddress ())) {
886 gws += sa.GetInternetAddress ();
891 for (PIP_ADAPTER_DNS_SERVER_ADDRESS_XP pa = currAddresses->FirstDnsServerAddress; pa !=
nullptr; pa = pa->Next) {
893 if (sa.IsInternetAddress ()) {
895 if (not ds.Contains (sa.GetInternetAddress ())) {
896 ds += sa.GetInternetAddress ();
901 if (currAddresses->PhysicalAddressLength == 6) {
902 newInterface.
fHardwareAddress = PrintMacAddr_ (currAddresses->PhysicalAddress, currAddresses->PhysicalAddress + 6);
905#if (NTDDI_VERSION >= NTDDI_WIN6)
910 if (newInterface.fType == Interface::Type::eWIFI) {
912 newInterface.fWirelessInfo = *owinfo;
927#if USE_NOISY_TRACE_IN_THIS_MODULE_
928 DbgTrace (L
"newInterface={}"_f, newInterface);
930 results.
Add (newInterface);
933 else if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
937 else if (dwRetVal == ERROR_NO_DATA) {
938 DbgTrace (
"There are no network adapters enabled on the local system"_f);
941 Execution::ThrowSystemErrNo (dwRetVal);
944#if USE_NOISY_TRACE_IN_THIS_MODULE_
959#if USE_NOISY_TRACE_IN_THIS_MODULE_
962#if qStroika_Foundation_Common_Platform_POSIX
964#elif qStroika_Foundation_Common_Platform_Windows
969#if USE_NOISY_TRACE_IN_THIS_MODULE_
970 DbgTrace (
"returning {}"_f, results);
978#if USE_NOISY_TRACE_IN_THIS_MODULE_
983 if (i.fInternalInterfaceID == internalInterfaceID) {
984#if USE_NOISY_TRACE_IN_THIS_MODULE_
985 DbgTrace (L
"found interface %s", internalInterfaceID.
c_str ());
990#if USE_NOISY_TRACE_IN_THIS_MODULE_
991 DbgTrace (L
"interface %s not found", internalInterfaceID.
c_str ());
998#if USE_NOISY_TRACE_IN_THIS_MODULE_
1003 if (i.fBindings.fAddressRanges.Any ([&ia] (
CIDR c) { return c.GetRange ().Contains (ia); })) {
1004#if USE_NOISY_TRACE_IN_THIS_MODULE_
1005 DbgTrace (L
"found interface %s", internalInterfaceID.c_str ());
1010#if USE_NOISY_TRACE_IN_THIS_MODULE_
1011 DbgTrace (L
"interface %s not found", internalInterfaceID.c_str ());
#define AssertNotImplemented()
#define WeakAssert(c)
A WeakAssert() is for things that aren't guaranteed to be true, but are overwhelmingly likely to be t...
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual tuple< const wchar_t *, wstring_view > c_str(Memory::StackBuffer< wchar_t > *possibleBackingStore) const
static String FromSDKString(const SDKChar *from)
static String FromNarrowSDKString(const char *from)
a cross between Mapping<KEY, T> and Collection<T> and Set<T>
nonvirtual bool Add(ArgByValueType< key_type > key, ArgByValueType< mapped_type > newElt, AddReplaceMode addReplaceMode=AddReplaceMode::eAddReplaces)
nonvirtual Iterable< mapped_type > MappedValues() const
nonvirtual bool ContainsKey(ArgByValueType< key_type > key) const
nonvirtual optional< mapped_type > Lookup(ArgByValueType< key_type > key) const
nonvirtual mapped_type LookupValue(ArgByValueType< key_type > key, ArgByValueType< mapped_type > defaultValue=mapped_type{}) const
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
nonvirtual void Add(ArgByValueType< value_type > item)
This COULD be easily used to read CSV files, or tab-delimited files, for example.
Run the given command, and optionally support stdin/stdout/stderr as streams (either sync with Run,...
nonvirtual Sequence< InternetAddress > GetHostAddresses(const String &hostNameOrAddress) const
simple wrapper on GetHostEntry - looking up the hostname/ip address and returning the list of associa...
nonvirtual optional< Interface > GetContainingAddress(const InternetAddress &ia)
nonvirtual Traversal::Iterable< Interface > GetAll()
nonvirtual optional< Interface > GetById(const Interface::SystemIDType &internalInterfaceID)
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
nonvirtual void GrowToSize_uninitialized(size_t nElements)
same as GrowToSize (), except leaves newly created elements uninitialized (requires is_trivially_copy...
nonvirtual size_t GetSize() const noexcept
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
void ThrowIfNull(const Private_::ConstVoidStar &p, const HRESULT &hr)
Template specialization for ThrowIfNull (), for thing being thrown HRESULT - really throw HRESULTErro...
auto Finally(FUNCTION &&f) -> Private_::FinallySentry< FUNCTION >
nonvirtual String ToString() const
optional< double > fSignalQuality
nonvirtual String ToString() const
optional< Containers::Set< Status > > fStatus
optional< Containers::Sequence< InternetAddress > > fDNSServers
optional< Containers::Sequence< InternetAddress > > fGateways
optional< uint64_t > fTransmitSpeedBaud
SystemIDType fInternalInterfaceID
optional< Common::GUID > fNetworkGUID
optional< String > fDescription
optional< uint64_t > fReceiveLinkSpeedBaud
optional< String > fHardwareAddress