From bb67ac32bc2a27321cc7c0b2d24f9adc9639584d Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Fri, 24 Oct 2014 20:17:04 +0545 Subject: Support converting an IP range to an array of addresses so that it can be used for expanding ranges in host alias input. --- etc/inc/util.inc | 64 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 12 deletions(-) (limited to 'etc') diff --git a/etc/inc/util.inc b/etc/inc/util.inc index bf77e95..683061c 100644 --- a/etc/inc/util.inc +++ b/etc/inc/util.inc @@ -384,8 +384,8 @@ function ip2ulong($ip) { /* Find out how many IPs are contained within a given IP range * e.g. 192.168.0.0 to 192.168.0.255 returns 256 */ -function ip_range_size($startip, $endip) { - if (is_ipaddr($startip) && is_ipaddr($endip)) { +function ip_range_size_v4($startip, $endip) { + if (is_ipaddrv4($startip) && is_ipaddrv4($endip)) { // Operate as unsigned long because otherwise it wouldn't work // when crossing over from 127.255.255.255 / 128.0.0.0 barrier return abs(ip2ulong($startip) - ip2ulong($endip)) + 1; @@ -396,7 +396,7 @@ function ip_range_size($startip, $endip) { /* Find the smallest possible subnet mask which can contain a given number of IPs * e.g. 512 IPs can fit in a /23, but 513 IPs need a /22 */ -function find_smallest_cidr($number) { +function find_smallest_cidr_v4($number) { $smallest = 1; for ($b=32; $b > 0; $b--) { $smallest = ($number <= pow(2,$b)) ? $b : $smallest; @@ -428,17 +428,52 @@ function ip_greater_than($ip1, $ip2) { return ip2ulong($ip1) > ip2ulong($ip2); } -/* Convert a range of IPs to an array of subnets which can contain the range. */ +/* Convert a range of IPv4 addresses to an array of individual addresses. */ +/* Note: IPv6 ranges are not yet supported here. */ +function ip_range_to_address_array($startip, $endip, $max_size = 5000) { + if (!is_ipaddrv4($startip) || !is_ipaddrv4($endip)) { + return false; + } + + if (ip_greater_than($startip, $endip)) { + // Swap start and end so we can process sensibly. + $temp = $startip; + $startip = $endip; + $endip = $temp; + } + + if (ip_range_size_v4($startip, $endip) > $max_size) + return false; + + // Container for IP addresses within this range. + $rangeaddresses = array(); + $end_int = ip2ulong($endip); + for ($ip_int = ip2ulong($startip); $ip_int <= $end_int; $ip_int++) { + $rangeaddresses[] = long2ip($ip_int); + } + + return $rangeaddresses; +} + +/* Convert a range of IPv4 addresses to an array of subnets which can contain the range. */ +/* Note: IPv6 ranges are not yet supported here. */ function ip_range_to_subnet_array($startip, $endip) { - if (!is_ipaddr($startip) || !is_ipaddr($endip)) { + if (!is_ipaddrv4($startip) || !is_ipaddrv4($endip)) { return array(); } + if (ip_greater_than($startip, $endip)) { + // Swap start and end so we can process sensibly. + $temp = $startip; + $startip = $endip; + $endip = $temp; + } + // Container for subnets within this range. $rangesubnets = array(); // Figure out what the smallest subnet is that holds the number of IPs in the given range. - $cidr = find_smallest_cidr(ip_range_size($startip, $endip)); + $cidr = find_smallest_cidr_v4(ip_range_size_v4($startip, $endip)); // Loop here to reduce subnet size and retest as needed. We need to make sure // that the target subnet is wholly contained between $startip and $endip. @@ -473,7 +508,7 @@ function ip_range_to_subnet_array($startip, $endip) { } } - // Some logic that will recursivly search from $startip to the first IP before the start of the subnet we just found. + // Some logic that will recursively search from $startip to the first IP before the start of the subnet we just found. // NOTE: This may never be hit, the way the above algo turned out, but is left for completeness. if ($startip != $targetsub_min) { $rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array($startip, ip_before($targetsub_min))); @@ -489,12 +524,19 @@ function ip_range_to_subnet_array($startip, $endip) { return $rangesubnets; } +/* returns true if $range is a valid pair of IPv4 or IPv6 addresses separated by a "-" + false - if not a valid pair + true (numeric 4 or 6) - if valid, gives type of addresses */ function is_iprange($range) { if (substr_count($range, '-') != 1) { return false; } list($ip1, $ip2) = explode ('-', $range); - return (is_ipaddr($ip1) && is_ipaddr($ip2)); + if (is_ipaddrv4($ip1) && is_ipaddrv4($ip2)) + return 4; + if (is_ipaddrv6($ip1) && is_ipaddrv6($ip2)) + return 6; + return false; } /* returns true if $ipaddr is a valid dotted IPv4 address or a IPv6 */ @@ -644,7 +686,7 @@ function is_domain($domain) { if (!is_string($domain)) return false; - if (preg_match('/^(?:(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])$/i', $domain)) + if (preg_match('/^(?:(?:[a-z_0-9]|[a-z_0-9][a-z_0-9\-]*[a-z_0-9])\.)*(?:[a-z_0-9]|[a-z_0-9][a-z_0-9\-]*[a-z_0-9\.])$/i', $domain)) return true; else return false; @@ -1710,9 +1752,7 @@ function is_interface_mismatch() { } } - if ($g['minimum_nic_count'] > $i) { - $do_assign = true; - } else if (file_exists("{$g['tmp_path']}/assign_complete")) + if (file_exists("{$g['tmp_path']}/assign_complete")) $do_assign = false; if (!empty($missing_interfaces) && $do_assign) -- cgit v1.1