Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Interface.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_IO_Network_Interface_h_
5#define _Stroika_Foundation_IO_Network_Interface_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <optional>
10
12#include "Stroika/Foundation/Common/Common.h"
14#include "Stroika/Foundation/Common/GUID.h"
15#include "Stroika/Foundation/Containers/Collection.h"
16#include "Stroika/Foundation/Containers/Set.h"
19
20/**
21 * \file
22 *
23 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
24 *
25 * TODO:
26 * @todo Use http://stackoverflow.com/questions/14264371/how-to-get-nic-details-from-a-c-program to grab ethernet speed
27 * for inteface (bandwidth of network interface)
28 *
29 * @todo Handle case of multiple address bindings to a single interface (groupby).
30 *
31 * @todo Incomplete POSIX IMPL
32 * IPV6 compat for POSIX (already done for windows)
33 *
34 * @todo Fix use of assert - SB exceptions mostly...
35 */
36
38
39 using Characters::String;
40
41 /**
42 * Capture details describing a network interface.
43 */
44 struct Interface {
45 /**
46 * This is a somewhat artificial concept - which is introduced in Stroika. This is only guaranteed
47 * unique or the life of one program lifetime (@todo - not even sure we can do that much).
48 *
49 * UNIX:
50 * interface name - e.g. eth0 - in the first column reported in ifconfig.
51 *
52 * WINDOWS:
53 * IP_ADAPTER_ADDRESSES::fAdapterName
54 *
55 * This is interface AdapterName, which is not particularly printable (usualy a GUID)
56 */
58
59 /**
60 * @see SystemIDType
61 */
63
64#if qStroika_Foundation_Common_Platform_POSIX
65 /**
66 * On unix, its the interface name, e.g. eth0, eth1, etc.
67 * On Windows, this is concept doesn't really exist.
68 */
69 nonvirtual String GetInterfaceName () const;
70#endif
71
72 /**
73 * This is a generally good display name to describe a network interface.
74 *
75 * WINDOWS:
76 * IP_ADAPTER_ADDRESSES::FriendlyName
77 *
78 * A user-friendly name for the adapter. For example: "Local Area Connection 1." This name appears
79 * in contexts such as the ipconfig command line program and the Connection folder.
80 *
81 * Note this name is often user-editable
82 */
84
85 /**
86 * This description of the adpapter is typically a short string describing the hardware, such as
87 * "Intel(R) Dual Band Wireless-AC 7260"
88 */
89 optional<String> fDescription;
90
91 /**
92 * Network GUID
93 * @see https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh "NetworkGuid"
94 *
95 * I can find no documentation on what this means, and all the network interfaces appear to have the same value (e.g. fake networks and real ones).
96 * VERGING on deprecating this. It doesn't appear to have any use. But leave for now... -- LGP 2018-12-16
97 */
98 optional<Common::GUID> fNetworkGUID;
99
100 /**
101 *
102 * \note Common::DefaultNames<> supported
103 *
104 * Most of these types are obvious, but eDeviceVirtualInternalNetwork is for special internal networks, like for virtualbox, Docker, or other purposes.
105 * They will generally (always) have private IP Addresses distinct from the main real external IP address of the machine in question. It may not always
106 * be possible to identify such networks.
107 */
108 enum class Type {
109 eLoopback,
110 eWiredEthernet,
111 eWIFI,
112 eTunnel,
113 eDeviceVirtualInternalNetwork,
114 eOther,
115
116 Stroika_Define_Enum_Bounds (eLoopback, eOther)
117 };
118
119 /**
120 */
121 optional<Type> fType;
122
123 /**
124 * This - if present - is typically an ethernet macaddr (6 bytes in hex separated by :)
125 */
126 optional<String> fHardwareAddress;
127
128 /**
129 * bits per second
130 */
131 optional<uint64_t> fTransmitSpeedBaud;
132
133 /**
134 * bits per second
135 */
136 optional<uint64_t> fReceiveLinkSpeedBaud;
137
138 /**
139 * \note intentionally omitted fields 'Description' because included in parent object, connectionInfo state (cuz same as wireless adapater info state),
140 * and....
141 */
143 optional<String> fSSID;
144
145 /**
146 *
147 * \note Common::DefaultNames<> supported
148 */
149 enum class State {
150 eNotReady, // WLAN_INTERFACE_STATE::wlan_interface_state_not_ready,
151 eConnected, // WLAN_INTERFACE_STATE::wlan_interface_state_connected,
152 eAdHocNetworkFormed, // WLAN_INTERFACE_STATE::wlan_interface_state_ad_hoc_network_formed - First node in a ad hoc network
153 eDisconnecting, // WLAN_INTERFACE_STATE::wlan_interface_state_disconnecting,
154 eDisconnected, // WLAN_INTERFACE_STATE::wlan_interface_state_disconnected,
155 eAssociating, // WLAN_INTERFACE_STATE::wlan_interface_state_associating - Attempting to associate with a network
156 eDiscovering, // WLAN_INTERFACE_STATE::wlan_interface_state_discovering - Auto configuration is discovering settings for the network
157 eAuthenticating, // WLAN_INTERFACE_STATE::wlan_interface_state_authenticating
158 eUnknown,
159
160 Stroika_Define_Enum_Bounds (eNotReady, eUnknown)
161 };
162 optional<State> fState;
163
164 /**
165 *
166 * \note Common::DefaultNames<> supported
167 */
168 enum class ConnectionMode {
169 eProfile, // _WLAN_CONNECTION_MODE::wlan_connection_mode_profile- A profile is used to make the connection
170 eTemporaryProfile, // _WLAN_CONNECTION_MODE::wlan_connection_mode_temporary_profile - A temporary profile is used to make the connection
171 eDiscoverSecrure, // _WLAN_CONNECTION_MODE::wlan_connection_mode_discovery_secure - Secure discovery is used to make the connection
172 eDiscoverInsecure, // _WLAN_CONNECTION_MODE::wlan_connection_mode_discovery_unsecure,
173 eAuto, // _WLAN_CONNECTION_MODE::wlan_connection_mode_auto - connection initiated by wireless service automatically using a persistent profile
174 eInvalid, // _WLAN_CONNECTION_MODE::wlan_connection_mode_invalid
175 eUnknown,
176
177 Stroika_Define_Enum_Bounds (eProfile, eUnknown)
178 };
179 optional<ConnectionMode> fConnectionMode;
180
181 optional<String> fProfileName;
182
183 /**
184 *
185 * \note Common::DefaultNames<> supported
186 */
187 enum class BSSType {
188 eInfrastructure, // DOT11_BSS_TYPE::dot11_BSS_type_infrastructure
189 eIndependent, // DOT11_BSS_TYPE::dot11_BSS_type_independent
190 eAny, // DOT11_BSS_TYPE::dot11_BSS_type_any
191 eUnknown,
192
193 Stroika_Define_Enum_Bounds (eInfrastructure, eUnknown)
194 };
195 optional<BSSType> fBSSType;
196
197 optional<String> fMACAddress;
198
199 /**
200 *
201 * \note Common::DefaultNames<> supported
202 */
204 eFHSS, // DOT11_PHY_TYPE::dot11_phy_type_fhss = 1, Frequency-hopping spread-spectrum
205 eDSSS, // DOT11_PHY_TYPE:: dot11_phy_type_dsss = 2, Direct sequence spread spectrum
206 eIRBaseBand, // DOT11_PHY_TYPE::dot11_phy_type_irbaseband = 3,Infrared (IR) baseband
207 e80211a, // DOT11_PHY_TYPE::dot11_phy_type_ofdm = 4, // 11a
208 e80211b, // DOT11_PHY_TYPE::dot11_phy_type_hrdsss = 5, // 11b
209 e80211g, // DOT11_PHY_TYPE::dot11_phy_type_erp = 6, // 11g
210 e80211n, // DOT11_PHY_TYPE:: dot11_phy_type_ht = 7, // 11n
211 e80211ac, // DOT11_PHY_TYPE::dot11_phy_type_vht = 8, // 11ac
212 e80211ad, // DOT11_PHY_TYPE::dot11_phy_type_dmg = 9, // 11ad
213 e80211ax, // DOT11_PHY_TYPE::dot11_phy_type_he = 10, // 11ax
214 eUnknown, // DOT11_PHY_TYPE::dot11_phy_type_unknown = 0,
215
216 Stroika_Define_Enum_Bounds (eFHSS, eUnknown)
217 };
218 optional<PhysicalConnectionType> fPhysicalConnectionType;
219
220 /**
221 * A percentage value that represents the signal quality of the network.
222 * This member contains a value between 0 and 100. A value of 0 implies an actual RSSI signal strength of -100 dbm.
223 * A value of 100 implies an actual RSSI signal strength of -50 dbm. You can calculate the RSSI signal
224 * strength value for wlanSignalQuality values between 1 and 99 using linear interpolation.
225 *
226 * https://stackoverflow.com/questions/15797920/how-to-convert-wifi-signal-strength-from-quality-percent-to-rssi-dbm
227 */
228 optional<double> fSignalQuality;
229
230 optional<bool> fSecurityEnabled; // any wireless security enabled (versus open) // NOT SURE HOW DIFFERS FROM _DOT11_AUTH_ALGORITHM::DOT11_AUTH_ALGO_80211_OPEN
231 optional<bool> f8021XEnabled; // 802.1X
232
233 /**
234 *
235 * \note Common::DefaultNames<> supported
236 */
237 enum class AuthAlgorithm {
238 eOpen, // DOT11_AUTH_ALGORITHM::DOT11_AUTH_ALGO_80211_OPEN = 1,
239 ePresharedKey, // DOT11_AUTH_ALGORITHM::DOT11_AUTH_ALGO_80211_SHARED_KEY = 2,
240 eWPA, // DOT11_AUTH_ALGORITHM:: DOT11_AUTH_ALGO_WPA = 3,
241 eWPA_PSK, // DOT11_AUTH_ALGORITHM::DOT11_AUTH_ALGO_WPA_PSK = 4,
242 eWPA_NONE, // DOT11_AUTH_ALGORITHM::DOT11_AUTH_ALGO_WPA_NONE = 5, // used in NatSTA only
243 eRSNA, // DOT11_AUTH_ALGORITHM::DOT11_AUTH_ALGO_RSNA = 6,
244 eRSNA_PSK, // DOT11_AUTH_ALGORITHM::DOT11_AUTH_ALGO_RSNA_PSK = 7,
245 eUnknown,
246
247 Stroika_Define_Enum_Bounds (eOpen, eUnknown)
248 };
249 optional<AuthAlgorithm> fAuthAlgorithm;
250
251 optional<String> fCipher;
252
253 /**
254 * @see Characters::ToString ();
255 */
256 nonvirtual String ToString () const;
257 };
258
259 optional<WirelessInfo> fWirelessInfo; // has_value () if-and-only-if type fType == eWIFI
260
261 /**
262 */
263 struct Bindings {
264 /**
265 * until Stroika 2.1b9, this was called Network::fBindings
266 * These are the ranges of addresses (bindings?) associated with this network interface.
267 * Except for special cases (e.g. promiscuous mode) these are the only addreses expected to be one hop away on this
268 * network interface
269 */
270 Containers::Collection<CIDR> fAddressRanges; // can be IPv4 or IPv6
271
272 /**
273 * Very similar to fAddressRanges, but these addresses are the ones we listen to, as targetted for this
274 * machine.
275 */
276 Containers::Collection<InternetAddress> fAddresses; // can be IPv4 or IPv6
277
278 /**
279 * @see Characters::ToString ();
280 */
281 nonvirtual String ToString () const;
282 };
283
284 /**
285 * until Stroika 2.1b9, this was Containers::Collection<CIDR>: now fBindings.fAddressRanges
286 */
287 Bindings fBindings;
288
289 /**
290 * Typically there will be zero or one, and if one, this is the default gateway. This maybe missing if it couldn't be retrieved from the operating system.
291 */
292 optional<Containers::Sequence<InternetAddress>> fGateways;
293
294 /**
295 * The default set of (per adapter) dns servers. This maybe missing if it couldn't be retrieved from the operating system.
296 */
297 optional<Containers::Sequence<InternetAddress>> fDNSServers;
298
299 /**
300 * \note Common::DefaultNames<> supported
301 */
302 enum class Status {
303
304 /**
305 * This tells if the low level network interface is powered on, and physically connected (e.g. cable plugged in).
306 *
307 * This is always present if eRunning, but may also be present in the set of states if it can be determed that the interface is plugged in but disabled
308 * for reasons of software state (e.g. disabled interface, or testing mode).
309 */
311
312 /**
313 * This tells if the network interface is ready to send and recieve packets.
314 *
315 * \note see https://tools.ietf.org/html/rfc2020 and https://tools.ietf.org/html/rfc2863 - IfAdminStatus and IfOperStatus
316 * Corresponds to IfOperStatus==IfOperStatusUp
317 */
318 eRunning,
319
321 };
322
323 /**
324 * The state of the interface (@see Status) if known.
325 *
326 * \note not has_value () if IfOperStatusUnknown
327 */
328 optional<Containers::Set<Status>> fStatus;
329
330 /**
331 * @see Characters::ToString ();
332 */
333 nonvirtual String ToString () const;
334 };
335
336 /**
337 * \todo @todo http://stroika-bugs.sophists.com/browse/STK-710
338 * add some level of caching to this object, possible with arguments to CTOR saying
339 * allowed latency for fetch from OS
340 *
341 * IF I can do with netlink or something similar, probably at least optionally do this statically so that
342 * all instances can easily leverage the cache.
343 */
345 public:
346 /**
347 * Collect all the interfaces (and their status) from the operating system.
348 */
350
351 public:
352 /**
353 * Find the interface object with the given ID.
354 *
355 * @see Interface::fInternalInterfaceID
356 */
357 nonvirtual optional<Interface> GetById (const Interface::SystemIDType& internalInterfaceID);
358
359 public:
360 /**
361 * A given address should be found in at most one interface.
362 * Note this doesnt check fBoundAddresses, but fBoundAddressRanges, so what addresses are listened for, not
363 * actually associated with the interface
364 */
365 nonvirtual optional<Interface> GetContainingAddress (const InternetAddress& ia);
366 };
367
368}
369
370/*
371 ********************************************************************************
372 ***************************** Implementation Details ***************************
373 ********************************************************************************
374 */
375#include "Interface.inl"
376
377#endif /*_Stroika_Foundation_IO_Network_Interface_h_*/
#define Stroika_Define_Enum_Bounds(FIRST_ITEM, LAST_ITEM)
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
A Collection<T> is a container to manage an un-ordered collection of items, without equality defined ...
Definition Collection.h:102
nonvirtual optional< Interface > GetContainingAddress(const InternetAddress &ia)
nonvirtual Traversal::Iterable< Interface > GetAll()
nonvirtual optional< Interface > GetById(const Interface::SystemIDType &internalInterfaceID)
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237
optional< Containers::Set< Status > > fStatus
Definition Interface.h:328
optional< Containers::Sequence< InternetAddress > > fDNSServers
Definition Interface.h:297
optional< Containers::Sequence< InternetAddress > > fGateways
Definition Interface.h:292
optional< Common::GUID > fNetworkGUID
Definition Interface.h:98