Exemple #1
0
        /// <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)));
        }
Exemple #2
0
        /// <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);
        }
Exemple #3
0
 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));
 }
Exemple #4
0
 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));
 }
Exemple #5
0
        public void Min_Test(IPAddress expected,
                             IPAddress left,
                             IPAddress right)
        {
            // Arrange
            // Act
            var result = IPAddressMath.Min(left, right);

            // Assert
            Assert.Equal(expected, result);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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);
            }
        }
Exemple #9
0
        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)));
            }
        }
Exemple #10
0
 public void MinNullBetaTest()
 {
     Assert.Throws <ArgumentNullException>(() => IPAddressMath.Min(IPAddress.Any, null));
 }
Exemple #11
0
 public void MinNullAlphaTest()
 {
     Assert.Throws <ArgumentNullException>(() => IPAddressMath.Min(null, IPAddress.Any));
 }
Exemple #12
0
 public void MinMissMatchedAddressFamilyTest()
 {
     Assert.Throws <InvalidOperationException>(() => IPAddressMath.Min(IPAddress.Any, IPAddress.IPv6Any));
     Assert.Throws <InvalidOperationException>(() => IPAddressMath.Min(IPAddress.IPv6Any, IPAddress.Any));
 }