using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; #if NET8_0_OR_GREATER using IPNetwork = System.Net.IPNetwork; #else using Microsoft.AspNetCore.HttpOverrides; using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork; #endif namespace AMWD.Common.Utilities { /// /// Provides some network utils. /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public static class NetworkHelper { /// /// Tries to resolve a to its es. /// /// The hostname to resolve. /// An address family to use (available: and ). /// The resolved es or an empty list. public static List ResolveHost(string hostname, AddressFamily addressFamily = default) { if (string.IsNullOrWhiteSpace(hostname)) return []; if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) addressFamily = AddressFamily.Unspecified; var ipAddress = ResolveIpAddress(hostname, addressFamily); // the name was an ip address, should not happen but experience tells other stories if (ipAddress != null) return [ipAddress]; try { return Dns.GetHostAddresses(hostname) .FilterAddressFamily(addressFamily) .ToList(); } catch { return []; } } /// /// Tries to resolve an interface name to its v4 and v6 es. /// /// The interface name to resolve. /// An address family to use (available: and ). /// The resolved es or an empty list. public static List ResolveInterface(string interfaceName, AddressFamily addressFamily = default) { if (string.IsNullOrWhiteSpace(interfaceName)) return []; if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) addressFamily = AddressFamily.Unspecified; var ipAddress = ResolveIpAddress(interfaceName, addressFamily); // the name was an ip address, should not happen but experience tells other stories if (ipAddress != null) return [ipAddress]; try { return NetworkInterface.GetAllNetworkInterfaces() .Where(nic => nic.Name.Equals(interfaceName, StringComparison.OrdinalIgnoreCase)) .SelectMany(nic => nic.GetIPProperties().UnicastAddresses.Select(uai => uai.Address)) .FilterAddressFamily(addressFamily) .ToList(); } catch { return []; } } /// /// Uses the and expands the whole subnet. /// /// /// The network identifier and the broadcast address are included in the response list. /// /// The to expand. /// A list with all valid es. public static List ExpandNetwork(this IPNetwork network) { var list = new List(); #if NET8_0_OR_GREATER var ipAddress = network.BaseAddress; #else var ipAddress = network.Prefix; #endif while (network.Contains(ipAddress)) { list.Add(ipAddress); ipAddress = ipAddress.Increment(); } return list; } private static IPAddress ResolveIpAddress(string address, AddressFamily addressFamily) { if (IPAddress.TryParse(address, out var ipAddress)) { // the address is whether IPv4 nor IPv6 if (ipAddress.AddressFamily != AddressFamily.InterNetwork && ipAddress.AddressFamily != AddressFamily.InterNetworkV6) return null; // the address does not match the required address family if (addressFamily != AddressFamily.Unspecified && ipAddress.AddressFamily != addressFamily) return null; return ipAddress.IsIPv4MappedToIPv6 ? ipAddress.MapToIPv4() : ipAddress; } return null; } private static IEnumerable FilterAddressFamily(this IEnumerable source, AddressFamily addressFamily) { return source .Where(a => a.AddressFamily == AddressFamily.InterNetwork || a.AddressFamily == AddressFamily.InterNetworkV6) .Where(a => addressFamily == AddressFamily.Unspecified || a.AddressFamily == addressFamily) .OrderBy(a => a.AddressFamily); } internal static void SwapBigEndian(byte[] array) { if (BitConverter.IsLittleEndian) Array.Reverse(array); } } }