using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; namespace AMWD.Common.Utilities { /// /// Provides some network utils. /// 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 new(); 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 new() { ipAddress }; try { return Dns.GetHostAddresses(hostname) .FilterAddressFamily(addressFamily) .ToList(); } catch { return new(); } } /// /// 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. [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] // not possible to define interfaces on unit tests public static List ResolveInterface(string interfaceName, AddressFamily addressFamily = default) { if (string.IsNullOrWhiteSpace(interfaceName)) return new(); 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 new() { 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 new(); } } 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; } 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); } } }