/// <summary> /// Get The fewest consecutive subnets that would fill the range between the given addresses (inclusive) /// </summary> /// <param name="alpha">lowest order IP Address</param> /// <param name="beta">highest order IP Address</param> /// <returns>an enumerable of Subnet</returns> /// <exception cref="ArgumentNullException"><paramref name="alpha" /> is <see langword="null" />.</exception> /// <exception cref="ArgumentNullException"><paramref name="beta" /> is <see langword="null" />.</exception> /// <exception cref="InvalidOperationException">Address families must match</exception> /// <exception cref="InvalidOperationException">Address families must be InterNetwork or InternetworkV6</exception> public static IEnumerable <Subnet> FewestConsecutiveSubnetsFor([NotNull] IPAddress alpha, [NotNull] IPAddress beta) { if (alpha == null) { throw new ArgumentNullException(nameof(alpha)); } if (beta == null) { throw new ArgumentNullException(nameof(beta)); } if (beta.AddressFamily != alpha.AddressFamily) { throw new InvalidOperationException("Address families must match"); } if (!beta.IsIPv4() && !beta.IsIPv6()) { throw new InvalidOperationException("Address families must be InterNetwork or InternetworkV6"); } var ipHead = IPAddressMath.Min(alpha, beta); var ipTail = IPAddressMath.Max(alpha, beta); return(FilledSubnets(ipHead, ipTail, new Subnet(ipHead, ipTail))); }
/// <summary> /// Merge two touching or overlapiing address ranges /// </summary> /// <param name="alpha"></param> /// <param name="beta"></param> /// <param name="mergedRange"></param> /// <returns></returns> public static bool TryMerge([CanBeNull] IPAddressRange alpha, [CanBeNull] IPAddressRange beta, out IPAddressRange mergedRange) { if (alpha == null || beta == null || !alpha.IsValid || !beta.IsValid || !alpha.AddressFamily.Equals(beta.AddressFamily)) { mergedRange = null; return(false); } if (alpha.Overlaps(beta) || alpha.Touches(beta)) { Debug.Assert(alpha.Head != null, "alpha.Head != null"); Debug.Assert(beta.Head != null, "beta.Head != null"); var newHead = IPAddressMath.Min(alpha.Head, beta.Head); Debug.Assert(alpha.Tail != null, "alpha.Tail != null"); Debug.Assert(beta.Tail != null, "beta.Tail != null"); var newTail = IPAddressMath.Max(alpha.Tail, beta.Tail); mergedRange = new IPAddressRange(newHead, newTail); return(true); } mergedRange = null; return(false); }
public void Min_MismatchedAddressFamily_Throws_InvalidOperationException_Test() { // Arrange // Act // Assert Assert.Throws <InvalidOperationException>(() => IPAddressMath.Min(IPAddress.Any, IPAddress.IPv6Any)); Assert.Throws <InvalidOperationException>(() => IPAddressMath.Min(IPAddress.IPv6Any, IPAddress.Any)); }
public void Min_NullInput_Throws_ArgumentNullException_Test() { // Arrange // Act // Assert // ReSharper disable AssignNullToNotNullAttribute Assert.Throws <ArgumentNullException>(() => IPAddressMath.Min(null, IPAddress.Any)); Assert.Throws <ArgumentNullException>(() => IPAddressMath.Min(IPAddress.Any, null)); Assert.Throws <ArgumentNullException>(() => IPAddressMath.Min(null, null)); }
public void Min_Test(IPAddress expected, IPAddress left, IPAddress right) { // Arrange // Act var result = IPAddressMath.Min(left, right); // Assert Assert.Equal(expected, result); }
public void TryIncrement_Test(bool expectedSuccess, string expectedResultString, string inputString, long delta) { // Arrange _ = IPAddress.TryParse(inputString, out var input); // Act var successResult = IPAddressMath.TryIncrement(input, out var result, delta); // Assert Assert.Equal(expectedSuccess, successResult); _ = IPAddress.TryParse(expectedResultString, out var expectResultAddress); Assert.Equal(expectResultAddress, result); }
public string MinTest(string alpha, string beta) { // Arrange IPAddress alphaAddress; IPAddress.TryParse(alpha, out alphaAddress); IPAddress betaAddress; IPAddress.TryParse(beta, out betaAddress); // Act var result = IPAddressMath.Min(alphaAddress, betaAddress) .ToString(); // Assert return(result); }
/// <inheritdoc /> public IEnumerator <IPAddress> GetEnumerator() { // determine maximum possible address for iteration var addressLimit = IPAddressMath.Min(this.Tail, this.IsIPv4 ? IPAddressUtilities.IPv4MaxAddress : IPAddressUtilities.IPv6MaxAddress) .GetAddressBytes(); // determine the width of the bye array for the address address var addressByteWidth = this.IsIPv4 ? IPAddressUtilities.IPv4ByteCount : IPAddressUtilities.IPv6ByteCount; var currentAddressBytes = this.Head.GetAddressBytes(); // iterate appropriately as long as the current address isn't beyond the limit while (ByteArrayUtils.CompareUnsignedBigEndian(currentAddressBytes, addressLimit) <= 0) { yield return(new IPAddress(currentAddressBytes)); // determine next address if (!ByteArrayUtils.TrySumBigEndian(currentAddressBytes, 1, out var nextAddressBytes)) { break; } var nextAddressByteWidth = nextAddressBytes.Length; if (nextAddressByteWidth > addressByteWidth) { break; } // copy appropriate portion of next address with prefixed 0x00 bytes currentAddressBytes = new byte[addressByteWidth]; Array.Copy(nextAddressBytes, 0, currentAddressBytes, addressByteWidth - nextAddressByteWidth, nextAddressByteWidth); } }
public static IEnumerable <Subnet> FewestConsecutiveSubnetsFor([NotNull] IPAddress left, [NotNull] IPAddress right) { #region defense if (left == null) { throw new ArgumentNullException(nameof(left)); } if (right == null) { throw new ArgumentNullException(nameof(right)); } if (!IPAddressUtilities.ValidAddressFamilies.Contains(left.AddressFamily)) { throw new ArgumentException($"{nameof(left)} must have an address family equal to {string.Join(", ", IPAddressUtilities.ValidAddressFamilies)}", nameof(left)); } if (!IPAddressUtilities.ValidAddressFamilies.Contains(right.AddressFamily)) { throw new ArgumentException($"{nameof(right)} must have an address family equal to {string.Join(", ", IPAddressUtilities.ValidAddressFamilies)}", nameof(right)); } if (left.AddressFamily != right.AddressFamily) { throw new InvalidOperationException($"{nameof(left)} and {nameof(right)} must have matching address families"); } #endregion // end: defense var minHead = IPAddressMath.Min(left, right); var maxTail = IPAddressMath.Max(left, right); return(FilledSubnets(minHead, maxTail, new Subnet(minHead, maxTail))); // recursive function call // Works by verifying that passed subnet isn't bounded by head, tail IP Addresses // if not breaks subnet in half and recursively tests, building in essence a binary tree of testable subnet paths IEnumerable <Subnet> FilledSubnets(IPAddress head, IPAddress tail, Subnet subnet) { var networkPrefixAddress = subnet.NetworkPrefixAddress; var broadcastAddress = subnet.BroadcastAddress; // the given subnet is the perfect size for the head/tail (not papa bear, not mama bear, but just right with baby bear) if (networkPrefixAddress.IsGreaterThanOrEqualTo(head) && broadcastAddress.IsLessThanOrEqualTo(tail)) { return(new[] { subnet }); } // increasing the route prefix by 1 creates a subnet of half the initial size (due 2^(max-n) route prefix sizing) var nextSmallestRoutePrefix = subnet.RoutingPrefix + 1; // over-iterated route prefix, no valid subnet beyond this point; end search on this branch if ((subnet.IsIPv6 && nextSmallestRoutePrefix > IPAddressUtilities.IPv6BitCount) || (subnet.IsIPv4 && nextSmallestRoutePrefix > IPAddressUtilities.IPv4BitCount)) { return(Enumerable.Empty <Subnet>()); // no subnets to be found here, stop investigating branch of tree } // build head subnet var headSubnet = new Subnet(networkPrefixAddress, nextSmallestRoutePrefix); // use the next address after the end of the head subnet as the first address for the tail subnet if (!IPAddressMath.TryIncrement(headSubnet.BroadcastAddress, out var tailStartingAddress)) { throw new InvalidOperationException($"unable to increment {headSubnet.BroadcastAddress}"); } // ReSharper disable once AssignNullToNotNullAttribute var tailSubnet = new Subnet(tailStartingAddress, nextSmallestRoutePrefix); // break into binary search tree, searching both head subnet and tail subnet for ownership of head and tail ip return(FilledSubnets(head, tail, headSubnet) .Concat(FilledSubnets(head, tail, tailSubnet))); } }
public void MinNullBetaTest() { Assert.Throws <ArgumentNullException>(() => IPAddressMath.Min(IPAddress.Any, null)); }
public void MinNullAlphaTest() { Assert.Throws <ArgumentNullException>(() => IPAddressMath.Min(null, IPAddress.Any)); }
public void MinMissMatchedAddressFamilyTest() { Assert.Throws <InvalidOperationException>(() => IPAddressMath.Min(IPAddress.Any, IPAddress.IPv6Any)); Assert.Throws <InvalidOperationException>(() => IPAddressMath.Min(IPAddress.IPv6Any, IPAddress.Any)); }