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 DISABLE_COMPILER_GCC_WARNING_START (
"GCC diagnostic ignored \"-Wfree-nonheap-object\"");
430 newInterface.
fBindings.fAddressRanges.Add (
CIDR{sa.GetInternetAddress (), getNetMaskAsPrefix (sd, i->ifr_name)});
431 DISABLE_COMPILER_GCC_WARNING_END (
"GCC diagnostic ignored \"-Wfree-nonheap-object\"");
433 newInterface.
fBindings.fAddressRanges.Add (sa.GetInternetAddress ());
435 newInterface.
fBindings.fAddresses.Add (sa.GetInternetAddress ());
438#if USE_NOISY_TRACE_IN_THIS_MODULE_
439 DbgTrace (
"GetInterfaces_POSIX_mkInterface_ returns {}"_f, newInterface);
443#if qMacUBSanitizerifreqAlignmentIssue_Buggy
444 Stroika_Foundation_Debug_ATTRIBUTE_NO_SANITIZE_UNDEFINED
447 GetInterfaces_POSIX_ ()
452 ifconf ifconf{
sizeof (ifreqs), {
reinterpret_cast<char*
> (ifreqs)}};
454 int sd = ::socket (PF_INET, SOCK_STREAM, 0);
456 [[maybe_unused]]
auto&& cleanup =
Execution::Finally ([sd] ()
noexcept { ::close (sd); });
458 [[maybe_unused]]
int r = ::ioctl (sd, SIOCGIFCONF, (
char*)&ifconf);
461 for (
const ifreq* i = std::begin (ifreqs);
462 reinterpret_cast<const char*
> (i) -
reinterpret_cast<const char*
> (std::begin (ifreqs)) < ifconf.ifc_len;) {
463#if USE_NOISY_TRACE_IN_THIS_MODULE_
464 DbgTrace (
"interface: ifr_name={}; ifr_addr.sa_family = {}"_f, i->ifr_name, i->ifr_addr.sa_family);
470 Interface newInterface = GetInterfaces_POSIX_mkInterface_ (sd, i, results.Lookup (interfaceName));
472 results.Add (newInterface);
480#if qStroika_Foundation_Common_Platform_Linux
481 size_t len =
sizeof (*i);
483 size_t len = IFNAMSIZ + i->ifr_addr.sa_len;
485 i =
reinterpret_cast<const ifreq*
> (
reinterpret_cast<const byte*
> (i) + len);
487 return move (results);
492#if qStroika_Foundation_Common_Platform_Windows
505 : fDLL{::LoadLibrary (_T (
"wlanapi.dll"))}
507 Execution::ThrowIfNull (fDLL);
508 fWlanOpenHandle = (DWORD (WINAPI*) (_In_ DWORD dwClientVersion, _Reserved_ PVOID pReserved, _Out_ PDWORD pdwNegotiatedVersion,
509 _Out_ PHANDLE phClientHandle)) (::GetProcAddress (fDLL,
"WlanOpenHandle"));
511 (DWORD (WINAPI*) (_In_ HANDLE hClientHandle, _Reserved_ PVOID pReserved)) (::GetProcAddress (fDLL,
"WlanCloseHandle"));
512 fWlanFreeMemory = (DWORD (WINAPI*) (_In_ PVOID pMemory)) (::GetProcAddress (fDLL,
"WlanFreeMemory"));
513 fWlanEnumInterfaces =
514 (DWORD (WINAPI*) (_In_ HANDLE hClientHandle, _Reserved_ PVOID pReserved,
515 _Outptr_ PWLAN_INTERFACE_INFO_LIST * ppInterfaceList)) (::GetProcAddress (fDLL,
"WlanEnumInterfaces"));
516 fWlanQueryInterface =
517 (DWORD (WINAPI*) (_In_ HANDLE hClientHandle, _In_ CONST ::GUID * pInterfaceGuid, _In_ WLAN_INTF_OPCODE OpCode,
518 _Reserved_ PVOID pReserved, _Out_ PDWORD pdwDataSize, _Outptr_result_bytebuffer_ (*pdwDataSize) PVOID * ppData,
519 _Out_opt_ PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType)) (::GetProcAddress (fDLL,
"WlanQueryInterface"));
521 WLANAPI_ (
const WLANAPI_&) =
delete;
524 if (fDLL !=
nullptr) {
525 Verify (::FreeLibrary (fDLL));
529 DWORD (WINAPI* fWlanOpenHandle)
530 (_In_ DWORD dwClientVersion, _Reserved_ PVOID pReserved, _Out_ PDWORD pdwNegotiatedVersion, _Out_ PHANDLE phClientHandle) =
nullptr;
531 DWORD (WINAPI* fWlanCloseHandle)
532 (_In_ HANDLE hClientHandle, _Reserved_ PVOID pReserved) =
nullptr;
533 DWORD (WINAPI* fWlanFreeMemory)
534 (_In_ PVOID pMemory) =
nullptr;
535 DWORD (WINAPI* fWlanEnumInterfaces)
536 (_In_ HANDLE hClientHandle, _Reserved_ PVOID pReserved, _Outptr_ PWLAN_INTERFACE_INFO_LIST* ppInterfaceList) =
nullptr;
537 DWORD (WINAPI* fWlanQueryInterface)
538 (_In_ HANDLE hClientHandle, _In_ CONST ::GUID* pInterfaceGuid, _In_ WLAN_INTF_OPCODE OpCode, _Reserved_ PVOID pReserved, _Out_ PDWORD pdwDataSize,
539 _Outptr_result_bytebuffer_ (*pdwDataSize) PVOID* ppData, _Out_opt_ PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType) =
nullptr;
543 optional<uint64_t> fTransmitSpeedBaud;
544 optional<uint64_t> fReceiveLinkSpeedBaud;
551 static unique_ptr<WLANAPI_> sWlanAPI_;
552 static once_flag sOnceFlag_;
553 call_once (sOnceFlag_, [&] () { IgnoreExceptionsForCall (sWlanAPI_ = make_unique<WLANAPI_> ()) });
556 HANDLE hClient =
nullptr;
558 DWORD dwCurVersion = 0;
562 if (hClient !=
nullptr) {
563 sWlanAPI_->fWlanCloseHandle (hClient,
nullptr);
567 PWLAN_INTERFACE_INFO_LIST pIfList =
nullptr;
570 if (pIfList !=
nullptr) {
571 sWlanAPI_->fWlanFreeMemory (pIfList);
584 PWLAN_CONNECTION_ATTRIBUTES pConnectInfo{};
586 if (pConnectInfo !=
nullptr) {
587 sWlanAPI_->fWlanFreeMemory (pConnectInfo);
591 for (DWORD i = 0; i < pIfList->dwNumberOfItems; ++i) {
592 PWLAN_INTERFACE_INFO pIfInfo = (WLAN_INTERFACE_INFO*)&pIfList->InterfaceInfo[i];
593 WirelessInfoPlus_ wInfo;
598 case wlan_interface_state_not_ready:
599 return WirelessInfo::State::eNotReady;
600 case wlan_interface_state_connected:
601 return WirelessInfo::State::eConnected;
602 case wlan_interface_state_ad_hoc_network_formed:
603 return WirelessInfo::State::eAdHocNetworkFormed;
604 case wlan_interface_state_disconnecting:
605 return WirelessInfo::State::eDisconnecting;
606 case wlan_interface_state_disconnected:
607 return WirelessInfo::State::eDisconnected;
608 case wlan_interface_state_associating:
609 return WirelessInfo::State::eAssociating;
610 case wlan_interface_state_discovering:
611 return WirelessInfo::State::eDiscovering;
612 case wlan_interface_state_authenticating:
613 return WirelessInfo::State::eAuthenticating;
615 DbgTrace (
"Unknown state {}"_f,
static_cast<int> (s));
616 return WirelessInfo::State::eUnknown;
620 wInfo.fState = mapState (pIfInfo->isState);
624 if (pIfInfo->isState == wlan_interface_state_connected) {
626 DWORD connectInfoSize =
sizeof (WLAN_CONNECTION_ATTRIBUTES);
627 WLAN_OPCODE_VALUE_TYPE opCode = wlan_opcode_value_type_invalid;
629 sWlanAPI_->fWlanQueryInterface (hClient, &pIfInfo->InterfaceGuid, wlan_intf_opcode_current_connection,
nullptr,
630 &connectInfoSize, (PVOID*)&pConnectInfo, &opCode));
633 if (pConnectInfo->isState != pIfInfo->isState) {
634 DbgTrace (
"Not sure how these can differ (except for race condition) - but if they do, maybe worth looking into"_f);
639 case wlan_connection_mode_profile:
640 return WirelessInfo::ConnectionMode::eProfile;
641 case wlan_connection_mode_temporary_profile:
642 return WirelessInfo::ConnectionMode::eTemporaryProfile;
643 case wlan_connection_mode_discovery_secure:
644 return WirelessInfo::ConnectionMode::eDiscoverSecrure;
645 case wlan_connection_mode_discovery_unsecure:
646 return WirelessInfo::ConnectionMode::eDiscoverInsecure;
647 case wlan_connection_mode_auto:
648 return WirelessInfo::ConnectionMode::eAuto;
649 case wlan_connection_mode_invalid:
650 return WirelessInfo::ConnectionMode::eInvalid;
652 DbgTrace (
"Unknown connection mode {}"_f,
static_cast<int> (s));
653 return WirelessInfo::ConnectionMode::eUnknown;
656 wInfo.fConnectionMode = mapConnectionMode (pConnectInfo->wlanConnectionMode);
657 wInfo.fProfileName = pConnectInfo->strProfileName;
660 if (pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength != 0) {
662 span{
reinterpret_cast<const char*
> (pConnectInfo->wlanAssociationAttributes.dot11Ssid.ucSSID),
663 pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength});
668 case dot11_BSS_type_infrastructure:
669 return WirelessInfo::BSSType::eInfrastructure;
670 case dot11_BSS_type_independent:
671 return WirelessInfo::BSSType::eIndependent;
672 case dot11_BSS_type_any:
673 return WirelessInfo::BSSType::eAny;
675 DbgTrace (
"Unknown BSS mode {}"_f,
static_cast<int> (s));
676 return WirelessInfo::BSSType::eUnknown;
679 wInfo.fBSSType = mapBSSType (pConnectInfo->wlanAssociationAttributes.dot11BssType);
681 wInfo.fMACAddress = PrintMacAddr_ (std::begin (pConnectInfo->wlanAssociationAttributes.dot11Bssid),
682 std::end (pConnectInfo->wlanAssociationAttributes.dot11Bssid));
686 case dot11_phy_type_unknown:
687 return WirelessInfo::PhysicalConnectionType::eUnknown;
688 case dot11_phy_type_fhss:
689 return WirelessInfo::PhysicalConnectionType::eFHSS;
690 case dot11_phy_type_dsss:
691 return WirelessInfo::PhysicalConnectionType::eDSSS;
692 case dot11_phy_type_irbaseband:
693 return WirelessInfo::PhysicalConnectionType::eIRBaseBand;
694 case dot11_phy_type_ofdm:
695 return WirelessInfo::PhysicalConnectionType::e80211a;
696 case dot11_phy_type_hrdsss:
697 return WirelessInfo::PhysicalConnectionType::e80211b;
698 case dot11_phy_type_erp:
699 return WirelessInfo::PhysicalConnectionType::e80211g;
700 case dot11_phy_type_ht:
701 return WirelessInfo::PhysicalConnectionType::e80211n;
702 case dot11_phy_type_vht:
703 return WirelessInfo::PhysicalConnectionType::e80211ac;
704 case dot11_phy_type_dmg:
705 return WirelessInfo::PhysicalConnectionType::e80211ad;
706 case dot11_phy_type_he:
707 return WirelessInfo::PhysicalConnectionType::e80211ax;
709 DbgTrace (L
"Unknown DOT11_PHY_TYPE {}"_f,
static_cast<int> (s));
710 return WirelessInfo::PhysicalConnectionType::eUnknown;
713 wInfo.fPhysicalConnectionType = mapPhysicalConnectionType (pConnectInfo->wlanAssociationAttributes.dot11PhyType);
715 wInfo.fSignalQuality = pConnectInfo->wlanAssociationAttributes.wlanSignalQuality;
718 const ULONG kMagicFactor_{1000};
719 wInfo.fTransmitSpeedBaud = pConnectInfo->wlanAssociationAttributes.ulTxRate * kMagicFactor_;
720 wInfo.fReceiveLinkSpeedBaud = pConnectInfo->wlanAssociationAttributes.ulRxRate * kMagicFactor_;
723 wInfo.fSecurityEnabled = pConnectInfo->wlanSecurityAttributes.bSecurityEnabled;
724 wInfo.f8021XEnabled = pConnectInfo->wlanSecurityAttributes.bOneXEnabled;
727 case DOT11_AUTH_ALGO_80211_OPEN:
728 return WirelessInfo::AuthAlgorithm::eOpen;
729 case DOT11_AUTH_ALGO_80211_SHARED_KEY:
730 return WirelessInfo::AuthAlgorithm::ePresharedKey;
731 case DOT11_AUTH_ALGO_WPA:
732 return WirelessInfo::AuthAlgorithm::eWPA;
733 case DOT11_AUTH_ALGO_WPA_PSK:
734 return WirelessInfo::AuthAlgorithm::eWPA_PSK;
735 case DOT11_AUTH_ALGO_WPA_NONE:
736 return WirelessInfo::AuthAlgorithm::eWPA_NONE;
737 case DOT11_AUTH_ALGO_RSNA:
738 return WirelessInfo::AuthAlgorithm::eRSNA;
739 case DOT11_AUTH_ALGO_RSNA_PSK:
740 return WirelessInfo::AuthAlgorithm::eRSNA_PSK;
742 DbgTrace (L
"Unknown AuthAlgorithm {}"_f,
static_cast<int> (s));
743 return WirelessInfo::AuthAlgorithm::eUnknown;
746 wInfo.fAuthAlgorithm = mapAuthAlgorithm (pConnectInfo->wlanSecurityAttributes.dot11AuthAlgorithm);
748 auto mapCipher = [] (DOT11_CIPHER_ALGORITHM s) ->
String {
750 case DOT11_CIPHER_ALGO_NONE:
752 case DOT11_CIPHER_ALGO_WEP40:
754 case DOT11_CIPHER_ALGO_TKIP:
756 case DOT11_CIPHER_ALGO_CCMP:
758 case DOT11_CIPHER_ALGO_WEP104:
760 case DOT11_CIPHER_ALGO_WEP:
763 return "{}"_f(
static_cast<int> (s));
766 wInfo.fCipher = mapCipher (pConnectInfo->wlanSecurityAttributes.dot11CipherAlgorithm);
767 results.
Add (interfaceGUID, wInfo);
779 wirelessInfo2Merge = GetInterfaces_Windows_WirelessInfo_ ();
781 catch (
const std::system_error& e) {
782 if (e.code () == error_code{ERROR_SERVICE_NOT_ACTIVE, system_category ()}) {
791 ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS;
792 ULONG family = AF_UNSPEC;
795 ULONG ulOutBufLen =
static_cast<ULONG
> (buf.
GetSize ());
796 PIP_ADAPTER_ADDRESSES pAddresses =
reinterpret_cast<PIP_ADAPTER_ADDRESSES
> (buf.begin ());
802 DWORD dwRetVal = ::GetAdaptersAddresses (family, flags,
nullptr, pAddresses, &ulOutBufLen);
803 if (dwRetVal == NO_ERROR) {
804 for (PIP_ADAPTER_ADDRESSES currAddresses = pAddresses; currAddresses !=
nullptr; currAddresses = currAddresses->Next) {
812 if (memcmp (&currAddresses->NetworkGuid, &kZeroGUID_, sizeof (kZeroGUID_)) != 0) {
815 switch (currAddresses->IfType) {
816 case IF_TYPE_SOFTWARE_LOOPBACK:
817 newInterface.fType = Interface::Type::eLoopback;
819 case IF_TYPE_IEEE80211:
820 newInterface.fType = Interface::Type::eWIFI;
822 case IF_TYPE_ETHERNET_CSMACD:
823 if (newInterface.
fDescription->Contains (
"VirtualBox Host-Only Ethernet Adapter"sv) or
824 newInterface.
fDescription->Contains (
"Hyper-V Virtual Ethernet Adapter"sv)) {
826 newInterface.fType = Interface::Type::eDeviceVirtualInternalNetwork;
829 newInterface.fType = Interface::Type::eWiredEthernet;
833 DbgTrace (
"Treating unknown currAddresses->IfType = {} type as eOther"_f, currAddresses->IfType);
834 newInterface.fType = Interface::Type::eOther;
837 if (currAddresses->TunnelType != TUNNEL_TYPE_NONE) {
838 if (newInterface.fType) {
839 DbgTrace (
"overwriting type {} with tunneltype"_f, newInterface.fType);
841 newInterface.fType = Interface::Type::eTunnel;
843 switch (currAddresses->OperStatus) {
845 newInterface.
fStatus = Memory::NullCoalesce (newInterface.
fStatus) +
848 case IfOperStatusDown:
849 newInterface.
fStatus = Memory::NullCoalesce (newInterface.
fStatus);
851 case IfOperStatusDormant:
852 case IfOperStatusLowerLayerDown:
858 DbgTrace (
"ignoring unrecognized status: {}"_f,
static_cast<int> (currAddresses->OperStatus));
861 for (PIP_ADAPTER_UNICAST_ADDRESS pu = currAddresses->FirstUnicastAddress; pu !=
nullptr; pu = pu->Next) {
863 if (sa.IsInternetAddress ()) {
864 newInterface.
fBindings.fAddressRanges.Add (
865 pu->OnLinkPrefixLength == 255 ? sa.GetInternetAddress () :
CIDR{sa.GetInternetAddress (), pu->OnLinkPrefixLength});
866 newInterface.
fBindings.fAddresses.Add (sa.GetInternetAddress ());
869 for (PIP_ADAPTER_ANYCAST_ADDRESS pa = currAddresses->FirstAnycastAddress; pa !=
nullptr; pa = pa->Next) {
871 if (sa.IsInternetAddress ()) {
872 newInterface.
fBindings.fAddressRanges.Add (sa.GetInternetAddress ());
873 newInterface.
fBindings.fAddresses.Add (sa.GetInternetAddress ());
876 for (PIP_ADAPTER_MULTICAST_ADDRESS pm = currAddresses->FirstMulticastAddress; pm !=
nullptr; pm = pm->Next) {
878 if (sa.IsInternetAddress ()) {
879 newInterface.
fBindings.fAddressRanges.Add (sa.GetInternetAddress ());
880 newInterface.
fBindings.fAddresses.Add (sa.GetInternetAddress ());
883 for (PIP_ADAPTER_GATEWAY_ADDRESS_LH pa = currAddresses->FirstGatewayAddress; pa !=
nullptr; pa = pa->Next) {
885 if (sa.IsInternetAddress ()) {
887 if (not gws.Contains (sa.GetInternetAddress ())) {
888 gws += sa.GetInternetAddress ();
893 for (PIP_ADAPTER_DNS_SERVER_ADDRESS_XP pa = currAddresses->FirstDnsServerAddress; pa !=
nullptr; pa = pa->Next) {
895 if (sa.IsInternetAddress ()) {
897 if (not ds.Contains (sa.GetInternetAddress ())) {
898 ds += sa.GetInternetAddress ();
903 if (currAddresses->PhysicalAddressLength == 6) {
904 newInterface.
fHardwareAddress = PrintMacAddr_ (currAddresses->PhysicalAddress, currAddresses->PhysicalAddress + 6);
907#if (NTDDI_VERSION >= NTDDI_WIN6)
912 if (newInterface.fType == Interface::Type::eWIFI) {
914 newInterface.fWirelessInfo = *owinfo;
929#if USE_NOISY_TRACE_IN_THIS_MODULE_
930 DbgTrace (L
"newInterface={}"_f, newInterface);
932 results.
Add (newInterface);
935 else if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
939 else if (dwRetVal == ERROR_NO_DATA) {
940 DbgTrace (
"There are no network adapters enabled on the local system"_f);
943 Execution::ThrowSystemErrNo (dwRetVal);
946#if USE_NOISY_TRACE_IN_THIS_MODULE_
961#if USE_NOISY_TRACE_IN_THIS_MODULE_
964#if qStroika_Foundation_Common_Platform_POSIX
966#elif qStroika_Foundation_Common_Platform_Windows
971#if USE_NOISY_TRACE_IN_THIS_MODULE_
972 DbgTrace (
"returning {}"_f, results);
980#if USE_NOISY_TRACE_IN_THIS_MODULE_
985 if (i.fInternalInterfaceID == internalInterfaceID) {
986#if USE_NOISY_TRACE_IN_THIS_MODULE_
987 DbgTrace (L
"found interface %s", internalInterfaceID.
c_str ());
992#if USE_NOISY_TRACE_IN_THIS_MODULE_
993 DbgTrace (L
"interface %s not found", internalInterfaceID.
c_str ());
1000#if USE_NOISY_TRACE_IN_THIS_MODULE_
1005 if (i.fBindings.fAddressRanges.Any ([&ia] (
CIDR c) { return c.GetRange ().Contains (ia); })) {
1006#if USE_NOISY_TRACE_IN_THIS_MODULE_
1007 DbgTrace (L
"found interface %s", internalInterfaceID.c_str ());
1012#if USE_NOISY_TRACE_IN_THIS_MODULE_
1013 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.
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