/// <summary> /// Initializes a new instance of the <see cref="IPAddressRange"/> class, /// representing a CIDR subnet. /// </summary> /// <param name="baseAddress">The base address of the subnet.</param> /// <param name="prefixLength">The prefix length of the subnet.</param> /// <exception cref="ArgumentNullException"><paramref name="baseAddress"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentException"> /// <para><paramref name="prefixLength"/> is zero.</para> /// <para>- or -</para> /// <para><paramref name="prefixLength"/> is greater than the number of bits in /// the binary representation of <paramref name="baseAddress"/> (32 for IPv4 addresses, /// 128 for IPv6 addresses.)</para> /// <para>- or -</para> /// <para><paramref name="baseAddress"/> cannot be the base address of a subnet with a prefix length /// equal to <paramref name="prefixLength"/>, because the remaining bits after the prefix /// are not all zeros.</para> /// </exception> public IPAddressRange(IPAddress baseAddress, byte prefixLength) { if (baseAddress == null) { throw new ArgumentNullException(nameof(baseAddress)); } byte maxPrefixLength; if (baseAddress.AddressFamily == AddressFamily.InterNetworkV6) { _isV6 = true; maxPrefixLength = 128; } else { _isV6 = false; maxPrefixLength = 32; } if (prefixLength < 1 || prefixLength > maxPrefixLength) { throw InvalidPrefixLength(nameof(prefixLength)); } _start = new IPAddressValue(baseAddress); if (!_start.IsStartOfSubnet(prefixLength)) { throw InvalidSubnetBaseAddress(nameof(baseAddress)); } _end = _start.GetEndOfSubnet(prefixLength); _prefixLength = prefixLength; }
private static Exception?TryParseCidrOrAddressNetmaskFormat(string str, int separatorPos, out IPAddressRange result) { result = None; var s = str.Substring(0, separatorPos).Trim(); if (!IPAddressUtility.TryParse(s, out var address)) { return(InvalidIPAddress()); } var addressValue = new IPAddressValue(address); s = str.Substring(separatorPos + 1).Trim(); if (byte.TryParse(s, NumberStyles.None, CultureInfo.InvariantCulture, out var prefixLength)) { var maxPrefixLength = address.AddressFamily == AddressFamily.InterNetworkV6 ? 128 : 32; if (prefixLength < 1 || prefixLength > maxPrefixLength) { return(InvalidPrefixLength()); } if (!addressValue.IsStartOfSubnet(prefixLength)) { return(InvalidSubnetBaseAddress()); } result = new IPAddressRange(addressValue, addressValue.GetEndOfSubnet(prefixLength), address.AddressFamily == AddressFamily.InterNetworkV6, prefixLength); return(null); } // Only accept a netmask for IPv4 if (address.AddressFamily != AddressFamily.InterNetwork) { return(InvalidPrefixLength()); } if (!IPAddressUtility.TryParse(s, out var netmask)) { return(InvalidPrefixLengthOrNetmask()); } var addressFamily = address.AddressFamily; if (netmask.AddressFamily != addressFamily) { return(MismatchedNetmaskAddressFamily()); } var netmaskBytes = netmask.GetAddressBytes(); if (!TryNetmaskToCidrPrefixLength(netmaskBytes, out prefixLength)) { return(InvalidNetmask()); } if (!addressValue.IsStartOfSubnet(prefixLength)) { return(InvalidSubnetBaseAddress()); } result = new IPAddressRange(addressValue, addressValue.GetEndOfSubnet(prefixLength), false, prefixLength); return(null); }