using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using Microsoft.AspNetCore.HttpOverrides;
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 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.
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();
}
}
///
/// Parses a CIDR network definition.
///
/// The network in CIDR.
/// The or null.
public static IPNetwork ParseNetwork(string network)
{
TryParseNetwork(network, out var ipNetwork);
return ipNetwork;
}
///
/// Tries to parse a CIDR network definition.
///
/// The network in CIDR.
/// The parsed .
/// true on success, otherwise false.
public static bool TryParseNetwork(string network, out IPNetwork ipNetwork)
{
try
{
string[] parts = network.Split('/');
if (parts.Length != 2)
throw new ArgumentException($"Invalid network type");
var prefix = IPAddress.Parse(parts.First());
int prefixLength = int.Parse(parts.Last());
ipNetwork = new IPNetwork(prefix, prefixLength);
return true;
}
catch
{
ipNetwork = null;
return false;
}
}
///
/// 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();
var ipAddress = network.Prefix;
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);
}
}
}