using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net.Sockets; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("System.Net.IPNetwork")] [assembly: AssemblyDescription("IPNetwork C# library take care of complex network, ip, ipv4, ipv6, netmask, cidr, subnet, subnetting, supernet and supernetting calculation for .Net developpers. It works with IPv4 and IPv6 as well. It is written in C# for .NetStandard and coreclr and has a light and clean API and is fully unit tested.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Luc Dvchosal")] [assembly: AssemblyProduct("System.Net.IPNetwork")] [assembly: AssemblyCopyright("Copyright © Luc Dvchosal 2017")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("2e650d19-7041-43bd-acab-48a0b2ff2524")] [assembly: AssemblyFileVersion("2.1.2.0")] [assembly: TargetFramework(".NETStandard,Version=v1.3", FrameworkDisplayName = "")] [assembly: AssemblyVersion("2.1.2.0")] namespace System.Net; public static class BigIntegerExtensions { public static string ToBinaryString(this BigInteger bigint) { byte[] array = bigint.ToByteArray(); int num = array.Length - 1; StringBuilder stringBuilder = new StringBuilder(array.Length * 8); string text = Convert.ToString(array[num], 2); if (text[0] != '0' && bigint.Sign == 1) { stringBuilder.Append('0'); } stringBuilder.Append(text); for (num--; num >= 0; num--) { stringBuilder.Append(Convert.ToString(array[num], 2).PadLeft(8, '0')); } return stringBuilder.ToString(); } public static string ToHexadecimalString(this BigInteger bigint) { return bigint.ToString("X"); } public static string ToOctalString(this BigInteger bigint) { byte[] array = bigint.ToByteArray(); int num = array.Length - 1; StringBuilder stringBuilder = new StringBuilder((array.Length / 3 + 1) * 8); int num2 = array.Length % 3; if (num2 == 0) { num2 = 3; } int num3 = 0; while (num2 != 0) { num3 <<= 8; num3 += array[num--]; num2--; } string text = Convert.ToString(num3, 8); if (text[0] != '0' && bigint.Sign == 1) { stringBuilder.Append('0'); } stringBuilder.Append(text); while (num >= 0) { num3 = (array[num] << 16) + (array[num - 1] << 8) + array[num - 2]; stringBuilder.Append(Convert.ToString(num3, 8).PadLeft(8, '0')); num -= 3; } return stringBuilder.ToString(); } public static BigInteger PositiveReverse(this BigInteger input, int width) { List list = new List(); byte[] array = input.ToByteArray(); byte[] array2 = new byte[width]; Array.Copy(array, 0, array2, 0, array.Length - 1); for (int i = 0; i < array2.Length; i++) { list.Add((byte)(~array2[i])); } list.Add(0); return new BigInteger(list.ToArray()); } } public class IPAddressCollection : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private IPNetwork _ipnetwork; private BigInteger _enumerator; public BigInteger Count => _ipnetwork.Total; public IPAddress this[BigInteger i] { get { if (i >= Count) { throw new ArgumentOutOfRangeException("i"); } byte cidr = (byte)((_ipnetwork.AddressFamily == AddressFamily.InterNetwork) ? 32 : 128); return _ipnetwork.Subnet(cidr)[i].Network; } } public IPAddress Current => this[_enumerator]; object IEnumerator.Current => Current; internal IPAddressCollection(IPNetwork ipnetwork) { _ipnetwork = ipnetwork; _enumerator = -1; } IEnumerator IEnumerable.GetEnumerator() { return this; } IEnumerator IEnumerable.GetEnumerator() { return this; } public void Dispose() { } public bool MoveNext() { ++_enumerator; if (_enumerator >= Count) { return false; } return true; } public void Reset() { _enumerator = -1; } } public class IPNetwork : IComparable { private BigInteger _ipaddress; private AddressFamily _family; private byte _cidr; private static readonly Lazy _iana_ablock_reserved = new Lazy(() => Parse("10.0.0.0/8")); private static readonly Lazy _iana_bblock_reserved = new Lazy(() => Parse("172.16.0.0/12")); private static readonly Lazy _iana_cblock_reserved = new Lazy(() => Parse("192.168.0.0/16")); private BigInteger _network => _ipaddress & _netmask; public IPAddress Network => ToIPAddress(_network, _family); public AddressFamily AddressFamily => _family; private BigInteger _netmask => ToUint(_cidr, _family); public IPAddress Netmask => ToIPAddress(_netmask, _family); private BigInteger _broadcast { get { int width = ((_family == AddressFamily.InterNetwork) ? 4 : 16); return _network + _netmask.PositiveReverse(width); } } public IPAddress Broadcast { get { if (_family == AddressFamily.InterNetworkV6) { return null; } return ToIPAddress(_broadcast, _family); } } public IPAddress FirstUsable => ToIPAddress((_family == AddressFamily.InterNetworkV6) ? _network : ((Usable <= 0L) ? _network : (_network + 1)), _family); public IPAddress LastUsable => ToIPAddress((_family == AddressFamily.InterNetworkV6) ? _broadcast : ((Usable <= 0L) ? _network : (_broadcast - 1)), _family); public BigInteger Usable { get { if (_family == AddressFamily.InterNetworkV6) { return Total; } byte[] value = new byte[5] { 255, 255, 255, 255, 0 }; BigInteger bigInteger = new BigInteger(value); if (_cidr <= 30) { return (bigInteger >> _cidr) - 1; } return 0; } } public BigInteger Total { get { int num = ((_family == AddressFamily.InterNetwork) ? 32 : 128); return BigInteger.Pow(2, num - _cidr); } } public byte Cidr => _cidr; public static IPNetwork IANA_ABLK_RESERVED1 => _iana_ablock_reserved.Value; public static IPNetwork IANA_BBLK_RESERVED1 => _iana_bblock_reserved.Value; public static IPNetwork IANA_CBLK_RESERVED1 => _iana_cblock_reserved.Value; internal IPNetwork(BigInteger ipaddress, AddressFamily family, byte cidr) { if (cidr > ((family == AddressFamily.InterNetwork) ? 32 : 128)) { throw new ArgumentOutOfRangeException("cidr"); } _ipaddress = ipaddress; _family = family; _cidr = cidr; } public static IPNetwork Parse(string ipaddress, string netmask) { IPNetwork ipnetwork = null; InternalParse(tryParse: false, ipaddress, netmask, out ipnetwork); return ipnetwork; } public static IPNetwork Parse(string ipaddress, byte cidr) { IPNetwork ipnetwork = null; InternalParse(tryParse: false, ipaddress, cidr, out ipnetwork); return ipnetwork; } public static IPNetwork Parse(IPAddress ipaddress, IPAddress netmask) { IPNetwork ipnetwork = null; InternalParse(tryParse: false, ipaddress, netmask, out ipnetwork); return ipnetwork; } public static IPNetwork Parse(string network) { IPNetwork ipnetwork = null; InternalParse(tryParse: false, network, out ipnetwork); return ipnetwork; } public static bool TryParse(string ipaddress, string netmask, out IPNetwork ipnetwork) { IPNetwork ipnetwork2 = null; InternalParse(tryParse: true, ipaddress, netmask, out ipnetwork2); bool result = ipnetwork2 != null; ipnetwork = ipnetwork2; return result; } public static bool TryParse(string ipaddress, byte cidr, out IPNetwork ipnetwork) { IPNetwork ipnetwork2 = null; InternalParse(tryParse: true, ipaddress, cidr, out ipnetwork2); bool result = ipnetwork2 != null; ipnetwork = ipnetwork2; return result; } public static bool TryParse(string network, out IPNetwork ipnetwork) { IPNetwork ipnetwork2 = null; InternalParse(tryParse: true, network, out ipnetwork2); bool result = ipnetwork2 != null; ipnetwork = ipnetwork2; return result; } public static bool TryParse(IPAddress ipaddress, IPAddress netmask, out IPNetwork ipnetwork) { IPNetwork ipnetwork2 = null; InternalParse(tryParse: true, ipaddress, netmask, out ipnetwork2); bool result = ipnetwork2 != null; ipnetwork = ipnetwork2; return result; } private static void InternalParse(bool tryParse, string ipaddress, string netmask, out IPNetwork ipnetwork) { if (string.IsNullOrEmpty(ipaddress)) { if (!tryParse) { throw new ArgumentNullException("ipaddress"); } ipnetwork = null; return; } if (string.IsNullOrEmpty(netmask)) { if (!tryParse) { throw new ArgumentNullException("netmask"); } ipnetwork = null; return; } IPAddress address = null; if (!IPAddress.TryParse(ipaddress, out address)) { if (!tryParse) { throw new ArgumentException("ipaddress"); } ipnetwork = null; return; } IPAddress address2 = null; if (!IPAddress.TryParse(netmask, out address2)) { if (!tryParse) { throw new ArgumentException("netmask"); } ipnetwork = null; } else { InternalParse(tryParse, address, address2, out ipnetwork); } } private static void InternalParse(bool tryParse, string network, out IPNetwork ipnetwork) { if (string.IsNullOrEmpty(network)) { if (!tryParse) { throw new ArgumentNullException("network"); } ipnetwork = null; return; } network = Regex.Replace(network, "[^0-9a-fA-F\\.\\/\\s\\:]+", ""); network = Regex.Replace(network, "\\s{2,}", " "); network = network.Trim(); string[] array = network.Split(' ', '/'); byte result = 0; if (array.Length == 1) { if (TryGuessCidr(array[0], out result)) { InternalParse(tryParse, array[0], result, out ipnetwork); return; } if (!tryParse) { throw new ArgumentException("network"); } ipnetwork = null; } else if (byte.TryParse(array[1], out result)) { InternalParse(tryParse, array[0], result, out ipnetwork); } else { InternalParse(tryParse, array[0], array[1], out ipnetwork); } } private static void InternalParse(bool tryParse, IPAddress ipaddress, IPAddress netmask, out IPNetwork ipnetwork) { if (ipaddress == null) { if (!tryParse) { throw new ArgumentNullException("ipaddress"); } ipnetwork = null; return; } if (netmask == null) { if (!tryParse) { throw new ArgumentNullException("netmask"); } ipnetwork = null; return; } BigInteger ipaddress2 = ToBigInteger(ipaddress); byte? cidr = null; if (!TryToCidr(netmask, out cidr)) { if (!tryParse) { throw new ArgumentException("netmask"); } ipnetwork = null; } else { byte value = cidr.Value; IPNetwork iPNetwork = new IPNetwork(ipaddress2, ipaddress.AddressFamily, value); ipnetwork = iPNetwork; } } private static void InternalParse(bool tryParse, string ipaddress, byte cidr, out IPNetwork ipnetwork) { if (string.IsNullOrEmpty(ipaddress)) { if (!tryParse) { throw new ArgumentNullException("ipaddress"); } ipnetwork = null; return; } IPAddress address = null; if (!IPAddress.TryParse(ipaddress, out address)) { if (!tryParse) { throw new ArgumentException("ipaddress"); } ipnetwork = null; return; } IPAddress netmask = null; if (!TryToNetmask(cidr, address.AddressFamily, out netmask)) { if (!tryParse) { throw new ArgumentException("cidr"); } ipnetwork = null; } else { InternalParse(tryParse, address, netmask, out ipnetwork); } } public static BigInteger ToBigInteger(IPAddress ipaddress) { BigInteger? uintIpAddress = null; InternalToBigInteger(tryParse: false, ipaddress, out uintIpAddress); return uintIpAddress.Value; } public static bool TryToBigInteger(IPAddress ipaddress, out BigInteger? uintIpAddress) { BigInteger? uintIpAddress2 = null; InternalToBigInteger(tryParse: true, ipaddress, out uintIpAddress2); bool hasValue = uintIpAddress2.HasValue; uintIpAddress = uintIpAddress2; return hasValue; } private static void InternalToBigInteger(bool tryParse, IPAddress ipaddress, out BigInteger? uintIpAddress) { if (ipaddress == null) { if (!tryParse) { throw new ArgumentNullException("ipaddress"); } uintIpAddress = null; return; } byte[] addressBytes = ipaddress.GetAddressBytes(); if (addressBytes.Length != 4 && addressBytes.Length != 16) { if (!tryParse) { throw new ArgumentException("bytes"); } uintIpAddress = null; } else { Array.Reverse((Array)addressBytes); List list = new List(addressBytes); list.Add(0); uintIpAddress = new BigInteger(list.ToArray()); } } public static BigInteger ToUint(byte cidr, AddressFamily family) { BigInteger? uintNetmask = null; InternalToBigInteger(tryParse: false, cidr, family, out uintNetmask); return uintNetmask.Value; } public static bool TryToUint(byte cidr, AddressFamily family, out BigInteger? uintNetmask) { BigInteger? uintNetmask2 = null; InternalToBigInteger(tryParse: true, cidr, family, out uintNetmask2); bool hasValue = uintNetmask2.HasValue; uintNetmask = uintNetmask2; return hasValue; } private static void InternalToBigInteger(bool tryParse, byte cidr, AddressFamily family, out BigInteger? uintNetmask) { if (family == AddressFamily.InterNetwork && cidr > 32) { if (!tryParse) { throw new ArgumentOutOfRangeException("cidr"); } uintNetmask = null; return; } if (family == AddressFamily.InterNetworkV6 && cidr > 128) { if (!tryParse) { throw new ArgumentOutOfRangeException("cidr"); } uintNetmask = null; return; } if (family != AddressFamily.InterNetwork && family != AddressFamily.InterNetworkV6) { throw new NotSupportedException(family.ToString()); } if (family == AddressFamily.InterNetwork) { uintNetmask = ((cidr != 0) ? ((uint)(-1 << 32 - cidr)) : 0u); return; } BigInteger bigInteger = new BigInteger(new byte[17] { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0 }); byte[] array = ((cidr == 0) ? ((BigInteger)0) : (bigInteger << 128 - cidr)).ToByteArray(); byte[] array2 = new byte[17]; int length = ((array.Length > 16) ? 16 : array.Length); Array.Copy(array, 0, array2, 0, length); uintNetmask = new BigInteger(array2); } private static byte ToCidr(BigInteger netmask, AddressFamily family) { byte? cidr = null; InternalToCidr(tryParse: false, netmask, family, out cidr); return cidr.Value; } private static void InternalToCidr(bool tryParse, BigInteger netmask, AddressFamily family, out byte? cidr) { if (!ValidNetmask(netmask, family)) { if (!tryParse) { throw new ArgumentException("netmask"); } cidr = null; } else { byte value = BitsSet(netmask, family); cidr = value; } } public static byte ToCidr(IPAddress netmask) { byte? cidr = null; InternalToCidr(tryParse: false, netmask, out cidr); return cidr.Value; } public static bool TryToCidr(IPAddress netmask, out byte? cidr) { byte? cidr2 = null; InternalToCidr(tryParse: true, netmask, out cidr2); bool hasValue = cidr2.HasValue; cidr = cidr2; return hasValue; } private static void InternalToCidr(bool tryParse, IPAddress netmask, out byte? cidr) { if (netmask == null) { if (!tryParse) { throw new ArgumentNullException("netmask"); } cidr = null; return; } BigInteger? uintIpAddress = null; if (!TryToBigInteger(netmask, out uintIpAddress)) { if (!tryParse) { throw new ArgumentException("netmask"); } cidr = null; } else { BigInteger value = uintIpAddress.Value; byte? cidr2 = null; InternalToCidr(tryParse, value, netmask.AddressFamily, out cidr2); cidr = cidr2; } } public static IPAddress ToNetmask(byte cidr, AddressFamily family) { IPAddress netmask = null; InternalToNetmask(tryParse: false, cidr, family, out netmask); return netmask; } public static bool TryToNetmask(byte cidr, AddressFamily family, out IPAddress netmask) { IPAddress netmask2 = null; InternalToNetmask(tryParse: true, cidr, family, out netmask2); bool result = netmask2 != null; netmask = netmask2; return result; } private static void InternalToNetmask(bool tryParse, byte cidr, AddressFamily family, out IPAddress netmask) { if (family != AddressFamily.InterNetwork && family != AddressFamily.InterNetworkV6) { if (!tryParse) { throw new ArgumentException("family"); } netmask = null; return; } if (cidr < 0) { if (!tryParse) { throw new ArgumentOutOfRangeException("cidr"); } netmask = null; return; } int num = ((family == AddressFamily.InterNetwork) ? 32 : 128); if (cidr > num) { if (!tryParse) { throw new ArgumentOutOfRangeException("cidr"); } netmask = null; } else { IPAddress iPAddress = ToIPAddress(ToUint(cidr, family), family); netmask = iPAddress; } } private static byte BitsSet(BigInteger netmask, AddressFamily family) { return (byte)netmask.ToBinaryString().Replace("0", "").ToCharArray() .Length; } private static BigInteger BigMask(byte b, int length) { List list = new List(length + 1); for (int i = 0; i < length; i++) { list.Add(b); } list.Add(0); return new BigInteger(list.ToArray()); } public static uint BitsSet(IPAddress netmask) { return BitsSet(ToBigInteger(netmask), netmask.AddressFamily); } public static bool ValidNetmask(IPAddress netmask) { if (netmask == null) { throw new ArgumentNullException("netmask"); } return ValidNetmask(ToBigInteger(netmask), netmask.AddressFamily); } private static bool ValidNetmask(BigInteger netmask, AddressFamily family) { if (family != AddressFamily.InterNetwork && family != AddressFamily.InterNetworkV6) { throw new ArgumentException("family"); } BigInteger bigInteger = ((family == AddressFamily.InterNetwork) ? new BigInteger(uint.MaxValue) : new BigInteger(new byte[17] { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0 })); BigInteger bigInteger2 = ~netmask & bigInteger; return ((bigInteger2 + 1) & bigInteger2) == 0L; } public static IPAddress ToIPAddress(BigInteger ipaddress, AddressFamily family) { int num = ((family == AddressFamily.InterNetwork) ? 4 : 16); byte[] array = ipaddress.ToByteArray(); byte[] array2 = new byte[num]; int length = ((array.Length > num) ? num : array.Length); Array.Copy(array, 0, array2, 0, length); Array.Reverse((Array)array2); return new IPAddress(Resize(array2, family)); } private static byte[] Resize(byte[] bytes, AddressFamily family) { if (family != AddressFamily.InterNetwork && family != AddressFamily.InterNetworkV6) { throw new ArgumentException("family"); } int num = ((family == AddressFamily.InterNetwork) ? 4 : 16); if (bytes.Length > num) { throw new ArgumentException("bytes"); } byte[] array = new byte[num]; Array.Copy(bytes, 0, array, 0, bytes.Length); return array; } public bool Contains(IPAddress ipaddress) { if (ipaddress == null) { throw new ArgumentNullException("ipaddress"); } if (AddressFamily != ipaddress.AddressFamily) { return false; } BigInteger network = _network; BigInteger broadcast = _broadcast; BigInteger bigInteger = ToBigInteger(ipaddress); if (bigInteger >= network) { return bigInteger <= broadcast; } return false; } [Obsolete("static Contains is deprecated, please use instance Contains.")] public static bool Contains(IPNetwork network, IPAddress ipaddress) { if (network == null) { throw new ArgumentNullException("network"); } return network.Contains(ipaddress); } public bool Contains(IPNetwork network2) { if (network2 == null) { throw new ArgumentNullException("network2"); } BigInteger network3 = _network; BigInteger broadcast = _broadcast; BigInteger network4 = network2._network; BigInteger broadcast2 = network2._broadcast; if (network4 >= network3) { return broadcast2 <= broadcast; } return false; } [Obsolete("static Contains is deprecated, please use instance Contains.")] public static bool Contains(IPNetwork network, IPNetwork network2) { if (network == null) { throw new ArgumentNullException("network"); } return network.Contains(network2); } public bool Overlap(IPNetwork network2) { if (network2 == null) { throw new ArgumentNullException("network2"); } BigInteger network3 = _network; BigInteger broadcast = _broadcast; BigInteger network4 = network2._network; BigInteger broadcast2 = network2._broadcast; if ((!(network4 >= network3) || !(network4 <= broadcast)) && (!(broadcast2 >= network3) || !(broadcast2 <= broadcast)) && (!(network4 <= network3) || !(broadcast2 >= broadcast))) { if (network4 >= network3) { return broadcast2 <= broadcast; } return false; } return true; } [Obsolete("static Overlap is deprecated, please use instance Overlap.")] public static bool Overlap(IPNetwork network, IPNetwork network2) { if (network == null) { throw new ArgumentNullException("network"); } return network.Overlap(network2); } public override string ToString() { return $"{Network}/{Cidr}"; } public static bool IsIANAReserved(IPAddress ipaddress) { if (ipaddress == null) { throw new ArgumentNullException("ipaddress"); } if (!IANA_ABLK_RESERVED1.Contains(ipaddress) && !IANA_BBLK_RESERVED1.Contains(ipaddress)) { return IANA_CBLK_RESERVED1.Contains(ipaddress); } return true; } public bool IsIANAReserved() { if (!IANA_ABLK_RESERVED1.Contains(this) && !IANA_BBLK_RESERVED1.Contains(this)) { return IANA_CBLK_RESERVED1.Contains(this); } return true; } [Obsolete("static IsIANAReserved is deprecated, please use instance IsIANAReserved.")] public static bool IsIANAReserved(IPNetwork ipnetwork) { if (ipnetwork == null) { throw new ArgumentNullException("ipnetwork"); } return ipnetwork.IsIANAReserved(); } public IPNetworkCollection Subnet(byte cidr) { IPNetworkCollection ipnetworkCollection = null; InternalSubnet(trySubnet: false, this, cidr, out ipnetworkCollection); return ipnetworkCollection; } [Obsolete("static Subnet is deprecated, please use instance Subnet.")] public static IPNetworkCollection Subnet(IPNetwork network, byte cidr) { if (network == null) { throw new ArgumentNullException("network"); } return network.Subnet(cidr); } public bool TrySubnet(byte cidr, out IPNetworkCollection ipnetworkCollection) { IPNetworkCollection ipnetworkCollection2 = null; InternalSubnet(trySubnet: true, this, cidr, out ipnetworkCollection2); if (ipnetworkCollection2 == null) { ipnetworkCollection = null; return false; } ipnetworkCollection = ipnetworkCollection2; return true; } [Obsolete("static TrySubnet is deprecated, please use instance TrySubnet.")] public static bool TrySubnet(IPNetwork network, byte cidr, out IPNetworkCollection ipnetworkCollection) { if (network == null) { throw new ArgumentNullException("network"); } return network.TrySubnet(cidr, out ipnetworkCollection); } private static void InternalSubnet(bool trySubnet, IPNetwork network, byte cidr, out IPNetworkCollection ipnetworkCollection) { if (network == null) { if (!trySubnet) { throw new ArgumentNullException("network"); } ipnetworkCollection = null; return; } int num = ((network._family == AddressFamily.InterNetwork) ? 32 : 128); if (cidr > num) { if (!trySubnet) { throw new ArgumentOutOfRangeException("cidr"); } ipnetworkCollection = null; } else if (cidr < network.Cidr) { if (!trySubnet) { throw new ArgumentException("cidr"); } ipnetworkCollection = null; } else { ipnetworkCollection = new IPNetworkCollection(network, cidr); } } public IPNetwork Supernet(IPNetwork network2) { IPNetwork supernet = null; InternalSupernet(trySupernet: false, this, network2, out supernet); return supernet; } [Obsolete("static Supernet is deprecated, please use instance Supernet.")] public static IPNetwork Supernet(IPNetwork network, IPNetwork network2) { return network.Supernet(network2); } public bool TrySupernet(IPNetwork network2, out IPNetwork supernet) { IPNetwork supernet2 = null; InternalSupernet(trySupernet: true, this, network2, out supernet2); bool result = supernet2 != null; supernet = supernet2; return result; } [Obsolete("static TrySupernet is deprecated, please use instance TrySupernet.")] public static bool TrySupernet(IPNetwork network, IPNetwork network2, out IPNetwork supernet) { if (network == null) { throw new ArgumentNullException("network"); } return network.TrySupernet(network2, out supernet); } private static void InternalSupernet(bool trySupernet, IPNetwork network1, IPNetwork network2, out IPNetwork supernet) { if (network1 == null) { if (!trySupernet) { throw new ArgumentNullException("network1"); } supernet = null; return; } if (network2 == null) { if (!trySupernet) { throw new ArgumentNullException("network2"); } supernet = null; return; } if (network1.Contains(network2)) { supernet = new IPNetwork(network1._network, network1._family, network1.Cidr); return; } if (network2.Contains(network1)) { supernet = new IPNetwork(network2._network, network2._family, network2.Cidr); return; } if (network1._cidr != network2._cidr) { if (!trySupernet) { throw new ArgumentException("cidr"); } supernet = null; return; } IPNetwork iPNetwork = ((network1._network < network2._network) ? network1 : network2); IPNetwork iPNetwork2 = ((network1._network > network2._network) ? network1 : network2); if (iPNetwork._broadcast + 1 != iPNetwork2._network) { if (!trySupernet) { throw new ArgumentOutOfRangeException("network"); } supernet = null; return; } IPNetwork iPNetwork3 = new IPNetwork(iPNetwork._network, cidr: (byte)(iPNetwork._cidr - 1), family: iPNetwork._family); if (iPNetwork3._network != iPNetwork._network) { if (!trySupernet) { throw new ArgumentException("network"); } supernet = null; } else { supernet = iPNetwork3; } } public override int GetHashCode() { return $"{_ipaddress.GetHashCode()}|{_network.GetHashCode()}|{_cidr.GetHashCode()}".GetHashCode(); } public static IPNetwork[] Supernet(IPNetwork[] ipnetworks) { InternalSupernet(trySupernet: false, ipnetworks, out var supernet); return supernet; } public static bool TrySupernet(IPNetwork[] ipnetworks, out IPNetwork[] supernet) { return InternalSupernet(trySupernet: true, ipnetworks, out supernet); } internal static bool InternalSupernet(bool trySupernet, IPNetwork[] ipnetworks, out IPNetwork[] supernet) { if (ipnetworks == null) { if (!trySupernet) { throw new ArgumentNullException("ipnetworks"); } supernet = null; return false; } if (ipnetworks.Length == 0) { supernet = new IPNetwork[0]; return true; } List list = new List(); Stack stack = List2Stack(Array2List(ipnetworks)); int num = 0; int count = stack.Count; while (num != count) { list.Clear(); while (stack.Count > 1) { IPNetwork iPNetwork = stack.Pop(); IPNetwork network = stack.Peek(); IPNetwork supernet2 = null; if (iPNetwork.TrySupernet(network, out supernet2)) { stack.Pop(); stack.Push(supernet2); } else { list.Add(iPNetwork); } } if (stack.Count == 1) { list.Add(stack.Pop()); } num = count; count = list.Count; stack = List2Stack(list); } supernet = list.ToArray(); return true; } private static Stack List2Stack(List list) { Stack stack = new Stack(); list.ForEach(delegate(IPNetwork ipn) { stack.Push(ipn); }); return stack; } private static List Array2List(IPNetwork[] array) { List list = new List(); list.AddRange(array); RemoveNull(list); list.Sort(delegate(IPNetwork ipn1, IPNetwork ipn2) { int num = ipn1._network.CompareTo(ipn2._network); return (num == 0) ? ipn1._cidr.CompareTo(ipn2._cidr) : num; }); list.Reverse(); return list; } private static void RemoveNull(List ipns) { ipns.RemoveAll((IPNetwork ipn) => (ipn == null) ? true : false); } public static IPNetwork WideSubnet(string start, string end) { if (string.IsNullOrEmpty(start)) { throw new ArgumentNullException("start"); } if (string.IsNullOrEmpty(end)) { throw new ArgumentNullException("end"); } if (!IPAddress.TryParse(start, out IPAddress address)) { throw new ArgumentException("start"); } if (!IPAddress.TryParse(end, out IPAddress address2)) { throw new ArgumentException("end"); } if (address.AddressFamily != address2.AddressFamily) { throw new NotSupportedException("MixedAddressFamily"); } IPNetwork result = new IPNetwork(0, address.AddressFamily, 0); for (byte b = 32; b >= 0; b--) { IPNetwork iPNetwork = Parse(start, b); if (iPNetwork.Contains(address2)) { result = iPNetwork; break; } } return result; } public static bool TryWideSubnet(IPNetwork[] ipnetworks, out IPNetwork ipnetwork) { IPNetwork ipnetwork2 = null; InternalWideSubnet(tryWide: true, ipnetworks, out ipnetwork2); if (ipnetwork2 == null) { ipnetwork = null; return false; } ipnetwork = ipnetwork2; return true; } public static IPNetwork WideSubnet(IPNetwork[] ipnetworks) { IPNetwork ipnetwork = null; InternalWideSubnet(tryWide: false, ipnetworks, out ipnetwork); return ipnetwork; } private static void InternalWideSubnet(bool tryWide, IPNetwork[] ipnetworks, out IPNetwork ipnetwork) { if (ipnetworks == null) { if (!tryWide) { throw new ArgumentNullException("ipnetworks"); } ipnetwork = null; return; } IPNetwork[] array = Array.FindAll(ipnetworks, (IPNetwork ipnet) => ipnet != null); if (array.Length == 0) { if (!tryWide) { throw new ArgumentException("ipnetworks"); } ipnetwork = null; return; } if (array.Length == 1) { IPNetwork iPNetwork = array[0]; ipnetwork = iPNetwork; return; } Array.Sort(array); IPNetwork iPNetwork2 = array[0]; BigInteger ipaddress = iPNetwork2._ipaddress; IPAddress broadcast = array[^1].Broadcast; AddressFamily family = ipnetworks[0]._family; for (int num = 0; num < ipnetworks.Length; num++) { if (ipnetworks[num]._family != family) { throw new ArgumentException("MixedAddressFamily"); } } IPNetwork iPNetwork3 = new IPNetwork(0, family, 0); for (byte b = iPNetwork2._cidr; b >= 0; b--) { IPNetwork iPNetwork4 = new IPNetwork(ipaddress, family, b); if (iPNetwork4.Contains(broadcast)) { iPNetwork3 = iPNetwork4; break; } } ipnetwork = iPNetwork3; } public string Print() { StringWriter stringWriter = new StringWriter(); stringWriter.WriteLine("IPNetwork : {0}", ToString()); stringWriter.WriteLine("Network : {0}", Network); stringWriter.WriteLine("Netmask : {0}", Netmask); stringWriter.WriteLine("Cidr : {0}", Cidr); stringWriter.WriteLine("Broadcast : {0}", Broadcast); stringWriter.WriteLine("FirstUsable : {0}", FirstUsable); stringWriter.WriteLine("LastUsable : {0}", LastUsable); stringWriter.WriteLine("Usable : {0}", Usable); return stringWriter.ToString(); } [Obsolete("static Print is deprecated, please use instance Print.")] public static string Print(IPNetwork ipnetwork) { if (ipnetwork == null) { throw new ArgumentNullException("ipnetwork"); } return ipnetwork.Print(); } public static bool TryGuessCidr(string ip, out byte cidr) { IPAddress address = null; if (!IPAddress.TryParse($"{ip}", out address)) { cidr = 0; return false; } if (address.AddressFamily == AddressFamily.InterNetworkV6) { cidr = 64; return true; } BigInteger bigInteger = ToBigInteger(address); bigInteger >>= 29; if (bigInteger <= 3L) { cidr = 8; return true; } if (bigInteger <= 5L) { cidr = 16; return true; } if (bigInteger <= 6L) { cidr = 24; return true; } cidr = 0; return false; } public static bool TryParseCidr(string sidr, AddressFamily family, out byte? cidr) { byte result = 0; if (!byte.TryParse(sidr, out result)) { cidr = null; return false; } IPAddress netmask = null; if (!TryToNetmask(result, family, out netmask)) { cidr = null; return false; } cidr = result; return true; } [Obsolete("static ListIPAddress is deprecated, please use instance ListIPAddress.")] public static IPAddressCollection ListIPAddress(IPNetwork ipnetwork) { return ipnetwork.ListIPAddress(); } public IPAddressCollection ListIPAddress() { return new IPAddressCollection(this); } public static int Compare(IPNetwork left, IPNetwork right) { if ((object)left == null && (object)right == null) { return 0; } if ((object)left == right) { return 0; } if ((object)left == null) { return -1; } if ((object)right == null) { return 1; } int num = left._network.CompareTo(right._network); if (num != 0) { return num; } return left._cidr.CompareTo(right._cidr); } public int CompareTo(IPNetwork other) { return Compare(this, other); } public int CompareTo(object obj) { if (obj == null) { return 1; } IPNetwork iPNetwork = obj as IPNetwork; if (iPNetwork == null) { throw new ArgumentException("The supplied parameter is an invalid type. Please supply an IPNetwork type.", "obj"); } return CompareTo(iPNetwork); } public static bool Equals(IPNetwork left, IPNetwork right) { return Compare(left, right) == 0; } public bool Equals(IPNetwork other) { return Equals(this, other); } public override bool Equals(object obj) { return Equals(this, obj as IPNetwork); } public static bool operator ==(IPNetwork left, IPNetwork right) { return Equals(left, right); } public static bool operator !=(IPNetwork left, IPNetwork right) { return !Equals(left, right); } public static bool operator <(IPNetwork left, IPNetwork right) { return Compare(left, right) < 0; } public static bool operator >(IPNetwork left, IPNetwork right) { return Compare(left, right) > 0; } } public class IPNetworkCollection : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private BigInteger _enumerator; private byte _cidrSubnet; private IPNetwork _ipnetwork; private byte _cidr => _ipnetwork.Cidr; private BigInteger _broadcast => IPNetwork.ToBigInteger(_ipnetwork.Broadcast); private BigInteger _lastUsable => IPNetwork.ToBigInteger(_ipnetwork.LastUsable); private BigInteger _network => IPNetwork.ToBigInteger(_ipnetwork.Network); public BigInteger Count => BigInteger.Pow(2, _cidrSubnet - _cidr); public IPNetwork this[BigInteger i] { get { if (i >= Count) { throw new ArgumentOutOfRangeException("i"); } BigInteger bigInteger = (((_ipnetwork.AddressFamily == AddressFamily.InterNetworkV6) ? _lastUsable : _broadcast) - _network) / Count; return new IPNetwork(_network + (bigInteger + 1) * i, _ipnetwork.AddressFamily, _cidrSubnet); } } public IPNetwork Current => this[_enumerator]; object IEnumerator.Current => Current; internal IPNetworkCollection(IPNetwork ipnetwork, byte cidrSubnet) { if (cidrSubnet > ((ipnetwork.AddressFamily == AddressFamily.InterNetwork) ? 32 : 128)) { throw new ArgumentOutOfRangeException("cidrSubnet"); } if (cidrSubnet < ipnetwork.Cidr) { throw new ArgumentException("cidr"); } _cidrSubnet = cidrSubnet; _ipnetwork = ipnetwork; _enumerator = -1; } IEnumerator IEnumerable.GetEnumerator() { return this; } IEnumerator IEnumerable.GetEnumerator() { return this; } public void Dispose() { } public bool MoveNext() { ++_enumerator; if (_enumerator >= Count) { return false; } return true; } public void Reset() { _enumerator = -1; } }