/// <summary> /// Function to be called recursively for FewestConsecutiveSubnetsFor /// Works by verifying that passed subnet isn't bounded by head, tail /// if not breaks subnet in half and recursively tests, building in essence a binary tree of testable subnet paths /// </summary> /// <param name="headIP">the head IP</param> /// <param name="tailIP">the tail IP</param> /// <param name="subnet">The subnet found on success</param> /// <returns>true on success</returns> private static IEnumerable <Subnet> FilledSubnets([NotNull] IPAddress headIP, [NotNull] IPAddress tailIP, [NotNull] 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.ToUnsignedBigInteger() >= headIP.ToUnsignedBigInteger() && broadcastAddress.ToUnsignedBigInteger() <= tailIP.ToUnsignedBigInteger()) { 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 > 128) || (subnet.IsIPv4 && nextSmallestRoutePrefix > 32)) { 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 var tailStartingAddressBigInteger = headSubnet.BroadcastAddress.ToUnsignedBigInteger() + 1; IPAddress tailStartingAddress; if (!IPAddressUtilities.TryParse(tailStartingAddressBigInteger, headIP.AddressFamily, out tailStartingAddress)) { throw new ArgumentException(); } 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(headIP, tailIP, headSubnet) .Concat(FilledSubnets(headIP, tailIP, tailSubnet))); }