From 055a43d23584f92d871e77a7337d8f6d0d6babf8 Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Sat, 27 Sep 2014 22:55:00 +0545 Subject: [PATCH 1/5] Allow extended alias inputs #3890 Currently if you enter a space-separated list of subnets in the IP address box when entering an alias, the code reports that the data is invalid. But it does actually expand the list of subnets into multiple rows, and enters the various subnet CIDRs into the CIDR column for the user. The user can press Save a second time and the data is now valid so the code saves it happily. This is rather odd, as reported in redmine #3890. Also, if you input an IP range (e.g. 192.168.20.0-192.168.20.30) plus description and in the 2nd row put some other subnet and description, the range is correctly expanded, but the description only appears against the 1st subnet of the range. The description from the 2nd row ends up as the description against the 2nd subnet of the range, and the rest of the descriptions are blank. i.e. the descriptions do not get copied and pushed down as the IP ranges are expanded. This change fixes all that stuff by first parsing the posted data and expanding any IP ranges and/or space-separated lists, building arrays that have all their entries lined up: $input_addresses[] $input_address_subnet[] $final_address_details[] which are then validated. This is for master (2.2) branch. Actually it was not too difficult to integrate. --- usr/local/www/firewall_aliases_edit.php | 93 +++++++++++++++---------- 1 file changed, 58 insertions(+), 35 deletions(-) diff --git a/usr/local/www/firewall_aliases_edit.php b/usr/local/www/firewall_aliases_edit.php index aa59497e54..8a87d91b54 100755 --- a/usr/local/www/firewall_aliases_edit.php +++ b/usr/local/www/firewall_aliases_edit.php @@ -280,54 +280,77 @@ if ($_POST) { /* item is a normal alias type */ $wrongaliases = ""; $desc_fmt_err_found = false; + + // First trim and expand the input data. + // Users can paste strings like "10.1.2.0/24 10.3.0.0/16 9.10.11.0/24" into an address box. + // They can also put an IP range. + // This loop expands out that stuff so it can easily be validated. for($x=0; $x<4999; $x++) { if($_POST["address{$x}"] <> "") { - $_POST["address{$x}"] = trim($_POST["address{$x}"]); - if (is_alias($_POST["address{$x}"])) { - if (!alias_same_type($_POST["address{$x}"], $_POST['type'])) - // But alias type network can include alias type urltable. Feature#1603. - if (!($_POST['type'] == 'network' && - preg_match("/urltable/i", alias_get_type($_POST["address{$x}"])))) - $wrongaliases .= " " . $_POST["address{$x}"]; - } else if ($_POST['type'] == "port") { - if (!is_port($_POST["address{$x}"]) && !is_portrange($_POST["address{$x}"])) - $input_errors[] = $_POST["address{$x}"] . " " . gettext("is not a valid port or alias."); - } else if ($_POST['type'] == "host" || $_POST['type'] == "network") { - if (is_subnet($_POST["address{$x}"]) || (!is_ipaddr($_POST["address{$x}"]) - && !is_hostname($_POST["address{$x}"]) - && !is_iprange($_POST["address{$x}"]))) - $input_errors[] = sprintf(gettext('%1$s is not a valid %2$s alias.'), $_POST["address{$x}"], $_POST['type']); - } - if (is_iprange($_POST["address{$x}"])) { - list($startip, $endip) = explode('-', $_POST["address{$x}"]); - $rangesubnets = ip_range_to_subnet_array($startip, $endip); - $address = array_merge($address, $rangesubnets); - } else { - $tmpaddress = $_POST["address{$x}"]; - if($_POST['type'] != "host" && is_ipaddr($_POST["address{$x}"]) && $_POST["address_subnet{$x}"] <> "") { - if (!is_subnet($_POST["address{$x}"] . "/" . $_POST["address_subnet{$x}"])) - $input_errors[] = sprintf(gettext('%s/%s is not a valid subnet.'), $_POST["address{$x}"], $_POST["address_subnet{$x}"]); - else - $tmpaddress .= "/" . $_POST["address_subnet{$x}"]; - } - $address[] = $tmpaddress; - } - if ($_POST["detail{$x}"] <> "") { + if ($_POST["detail{$x}"] <> "") if ((strpos($_POST["detail{$x}"], "||") === false) && (substr($_POST["detail{$x}"], 0, 1) != "|") && (substr($_POST["detail{$x}"], -1, 1) != "|")) { - $final_address_details[] = $_POST["detail{$x}"]; + $detail_text = $_POST["detail{$x}"]; } else { /* Remove leading and trailing vertical bars and replace multiple vertical bars with single, */ /* and put in the output array so the text is at least redisplayed for the user. */ - $final_address_details[] = preg_replace('/\|\|+/', '|', trim($_POST["detail{$x}"], "|")); + $detail_text = preg_replace('/\|\|+/', '|', trim($_POST["detail{$x}"], "|")); if (!$desc_fmt_err_found) { $input_errors[] = $vertical_bar_err_text; $desc_fmt_err_found = true; } } - } else - $final_address_details[] = sprintf(gettext("Entry added %s"), date('r')); + else { + $detail_text = sprintf(gettext("Entry added %s"), date('r')); + } + $address_items = explode(" ", trim($_POST["address{$x}"])); + foreach ($address_items as $address_item) { + if (is_iprange($address_item)) { + list($startip, $endip) = explode('-', $address_item); + $rangesubnets = ip_range_to_subnet_array($startip, $endip); + foreach ($rangesubnets as $rangesubnet) { + list($address_part, $subnet_part) = explode("/", $rangesubnet); + $input_addresses[] = $address_part; + $input_address_subnet[] = $subnet_part; + $final_address_details[] = $detail_text; + } + } else { + list($address_part, $subnet_part) = explode("/", $address_item); + $input_addresses[] = $address_part; + if (!empty($subnet_part)) + $input_address_subnet[] = $subnet_part; + else + $input_address_subnet[] = $_POST["address_subnet{$x}"]; + $final_address_details[] = $detail_text; + } + } } } + + // Validate the input data expanded above. + foreach($input_addresses as $idx => $input_address) { + if (is_alias($input_address)) { + if (!alias_same_type($input_address, $_POST['type'])) + // But alias type network can include alias type urltable. Feature#1603. + if (!($_POST['type'] == 'network' && + preg_match("/urltable/i", alias_get_type($input_address)))) + $wrongaliases .= " " . $input_address; + } else if ($_POST['type'] == "port") { + if (!is_port($input_address) && !is_portrange($input_address)) + $input_errors[] = $input_address . " " . gettext("is not a valid port or alias."); + } else if ($_POST['type'] == "host" || $_POST['type'] == "network") { + if (is_subnet($input_address) || + (!is_ipaddr($input_address) && !is_hostname($input_address))) + $input_errors[] = sprintf(gettext('%1$s is not a valid %2$s address, FQDN or alias.'), $input_address, $_POST['type']); + } + $tmpaddress = $input_address; + if ($_POST['type'] != "host" && is_ipaddr($input_address) && $input_address_subnet[$idx] <> "") { + if (!is_subnet($input_address . "/" . $input_address_subnet[$idx])) + $input_errors[] = sprintf(gettext('%s/%s is not a valid subnet.'), $input_address, $input_address_subnet[$idx]); + else + $tmpaddress .= "/" . $input_address_subnet[$idx]; + } + $address[] = $tmpaddress; + } unset($desc_fmt_err_found); if ($wrongaliases <> "") $input_errors[] = sprintf(gettext('The alias(es): %s cannot be nested because they are not of the same type.'), $wrongaliases); From 6b18c66b5128c0b1a6cb20edfee955a5d8caf1f7 Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Sat, 27 Sep 2014 23:04:02 +0545 Subject: [PATCH 2/5] Clarify bracketing to minimize risk of a problem when adding code here in the future. --- usr/local/www/firewall_aliases_edit.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/www/firewall_aliases_edit.php b/usr/local/www/firewall_aliases_edit.php index 8a87d91b54..965d644505 100755 --- a/usr/local/www/firewall_aliases_edit.php +++ b/usr/local/www/firewall_aliases_edit.php @@ -287,7 +287,7 @@ if ($_POST) { // This loop expands out that stuff so it can easily be validated. for($x=0; $x<4999; $x++) { if($_POST["address{$x}"] <> "") { - if ($_POST["detail{$x}"] <> "") + if ($_POST["detail{$x}"] <> "") { if ((strpos($_POST["detail{$x}"], "||") === false) && (substr($_POST["detail{$x}"], 0, 1) != "|") && (substr($_POST["detail{$x}"], -1, 1) != "|")) { $detail_text = $_POST["detail{$x}"]; } else { @@ -299,7 +299,7 @@ if ($_POST) { $desc_fmt_err_found = true; } } - else { + } else { $detail_text = sprintf(gettext("Entry added %s"), date('r')); } $address_items = explode(" ", trim($_POST["address{$x}"])); From feb1953e849e634a31c73fcb262734bd03362ef3 Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Fri, 24 Oct 2014 20:10:50 +0545 Subject: [PATCH 3/5] Expand range or subnet for host alias When entering a host alias, if the user put an IP range (like 192.168.0.10-192.168.0.20) or a subnet (like 192.168.1.200/29) then expand it into a list of individual IP addresses. Check that it will not make too many rows to exceed the existing 5000 row limit on the GUI. Note: expanding ranges and subnets like this is only for IPv4 for now. Entering an IPv6 range or subnet in a hosts alias will display a message telling the user that is not supported - it could be done in future but currently the routines that convert this stuff are only for IPv4. I have done as much validation as I can think of, and where there is a problem the original user-entered data is preserved for re-display, as well as the input errors being displayed. So IMO it should be self-documenting. --- usr/local/www/firewall_aliases_edit.php | 113 ++++++++++++++++++++---- 1 file changed, 95 insertions(+), 18 deletions(-) diff --git a/usr/local/www/firewall_aliases_edit.php b/usr/local/www/firewall_aliases_edit.php index 965d644505..08c6caaf9b 100755 --- a/usr/local/www/firewall_aliases_edit.php +++ b/usr/local/www/firewall_aliases_edit.php @@ -63,6 +63,7 @@ if (is_array($config['load_balancer']['lbpool'])) $reserved_ifs = get_configured_interface_list(false, true); $reserved_keywords = array_merge($reserved_keywords, $reserved_ifs, $reserved_table_names); +$max_alias_addresses = 5000; if (!is_array($config['aliases']['alias'])) $config['aliases']['alias'] = array(); @@ -202,7 +203,7 @@ if ($_POST) { $desc_fmt_err_found = false; /* item is a url type */ - for($x=0; $x<4999; $x++) { + for($x=0; $x<$max_alias_addresses-1; $x++) { $_POST['address' . $x] = trim($_POST['address' . $x]); if($_POST['address' . $x]) { /* fetch down and add in */ @@ -280,12 +281,13 @@ if ($_POST) { /* item is a normal alias type */ $wrongaliases = ""; $desc_fmt_err_found = false; + $alias_address_count = 0; // First trim and expand the input data. // Users can paste strings like "10.1.2.0/24 10.3.0.0/16 9.10.11.0/24" into an address box. // They can also put an IP range. // This loop expands out that stuff so it can easily be validated. - for($x=0; $x<4999; $x++) { + for($x=0; $x<($max_alias_addresses-1); $x++) { if($_POST["address{$x}"] <> "") { if ($_POST["detail{$x}"] <> "") { if ((strpos($_POST["detail{$x}"], "||") === false) && (substr($_POST["detail{$x}"], 0, 1) != "|") && (substr($_POST["detail{$x}"], -1, 1) != "|")) { @@ -304,23 +306,98 @@ if ($_POST) { } $address_items = explode(" ", trim($_POST["address{$x}"])); foreach ($address_items as $address_item) { - if (is_iprange($address_item)) { + $iprange_type = is_iprange($address_item); + if ($iprange_type == 4) { list($startip, $endip) = explode('-', $address_item); - $rangesubnets = ip_range_to_subnet_array($startip, $endip); - foreach ($rangesubnets as $rangesubnet) { - list($address_part, $subnet_part) = explode("/", $rangesubnet); - $input_addresses[] = $address_part; - $input_address_subnet[] = $subnet_part; - $final_address_details[] = $detail_text; + if ($_POST['type'] == "network") { + // For network type aliases, expand an IPv4 range into an array of subnets. + $rangesubnets = ip_range_to_subnet_array($startip, $endip); + foreach ($rangesubnets as $rangesubnet) { + if ($alias_address_count > $max_alias_addresses) { + break; + } + list($address_part, $subnet_part) = explode("/", $rangesubnet); + $input_addresses[] = $address_part; + $input_address_subnet[] = $subnet_part; + $final_address_details[] = $detail_text; + $alias_address_count++; + } + } else { + // For host type aliases, expand an IPv4 range into a list of individual IPv4 addresses. + $rangeaddresses = ip_range_to_address_array($startip, $endip, $max_alias_addresses - $alias_address_count); + if (is_array($rangeaddresses)) { + foreach ($rangeaddresses as $rangeaddress) { + $input_addresses[] = $rangeaddress; + $input_address_subnet[] = ""; + $final_address_details[] = $detail_text; + $alias_address_count++; + } + } else { + $input_errors[] = sprintf(gettext('Range is too large to expand into individual host IP addresses (%s)'), $address_item); + $input_errors[] = sprintf(gettext('The maximum number of entries in an alias is %s'), $max_alias_addresses); + // Put the user-entered data in the output anyway, so it will be re-displayed for correction. + $input_addresses[] = $address_item; + $input_address_subnet[] = ""; + $final_address_details[] = $detail_text; + } } - } else { - list($address_part, $subnet_part) = explode("/", $address_item); - $input_addresses[] = $address_part; - if (!empty($subnet_part)) - $input_address_subnet[] = $subnet_part; - else - $input_address_subnet[] = $_POST["address_subnet{$x}"]; + } else if ($iprange_type == 6) { + $input_errors[] = sprintf(gettext('IPv6 address ranges are not supported (%s)'), $address_item); + // Put the user-entered data in the output anyway, so it will be re-displayed for correction. + $input_addresses[] = $address_item; + $input_address_subnet[] = ""; $final_address_details[] = $detail_text; + } else { + $subnet_type = is_subnet($address_item); + if (($_POST['type'] == "host") && $subnet_type) { + if ($subnet_type == 4) { + // For host type aliases, if the user enters an IPv4 subnet, expand it into a list of individual IPv4 addresses. + if (subnet_size($address_item) <= ($max_alias_addresses - $alias_address_count)) { + $rangeaddresses = subnetv4_expand($address_item); + foreach ($rangeaddresses as $rangeaddress) { + $input_addresses[] = $rangeaddress; + $input_address_subnet[] = ""; + $final_address_details[] = $detail_text; + $alias_address_count++; + } + } else { + $input_errors[] = sprintf(gettext('Subnet is too large to expand into individual host IP addresses (%s)'), $address_item); + $input_errors[] = sprintf(gettext('The maximum number of entries in an alias is %s'), $max_alias_addresses); + // Put the user-entered data in the output anyway, so it will be re-displayed for correction. + $input_addresses[] = $address_item; + $input_address_subnet[] = ""; + $final_address_details[] = $detail_text; + } + } else { + $input_errors[] = sprintf(gettext('IPv6 subnets are not supported in host aliases (%s)'), $address_item); + // Put the user-entered data in the output anyway, so it will be re-displayed for correction. + $input_addresses[] = $address_item; + $input_address_subnet[] = ""; + $final_address_details[] = $detail_text; + } + } else { + list($address_part, $subnet_part) = explode("/", $address_item); + if (!empty($subnet_part)) { + if (is_subnet($address_item)) { + $input_addresses[] = $address_part; + $input_address_subnet[] = $subnet_part; + } else { + // The user typed something like "1.2.3.444/24" or "1.2.3.0/36" or similar rubbish. + // Feed it through without splitting it apart, then it will be caught by the validation loop below. + $input_addresses[] = $address_item; + $input_address_subnet[] = ""; + } + } else { + $input_addresses[] = $address_part; + $input_address_subnet[] = $_POST["address_subnet{$x}"]; + } + $final_address_details[] = $detail_text; + $alias_address_count++; + } + } + if ($alias_address_count > $max_alias_addresses) { + $input_errors[] = sprintf(gettext('The maximum number of entries in an alias has been exceeded (%s)'), $max_alias_addresses); + break; } } } @@ -514,7 +591,7 @@ $urltable_ports_str = gettext("URL Table (Ports)"); $update_freq_str = gettext("Update Freq. (days)"); $networks_help = gettext("Networks are specified in CIDR format. Select the CIDR mask that pertains to each entry. /32 specifies a single IPv4 host, /128 specifies a single IPv6 host, /24 specifies 255.255.255.0, /64 specifies a normal IPv6 network, etc. Hostnames (FQDNs) may also be specified, using a /32 mask for IPv4 or /128 for IPv6. You may also enter an IP range such as 192.168.1.1-192.168.1.254 and a list of CIDR networks will be derived to fill the range."); -$hosts_help = gettext("Enter as many hosts as you would like. Hosts must be specified by their IP address or fully qualified domain name (FQDN). FQDN hostnames are periodically re-resolved and updated. If multiple IPs are returned by a DNS query, all are used."); +$hosts_help = gettext("Enter as many hosts as you would like. Hosts must be specified by their IP address or fully qualified domain name (FQDN). FQDN hostnames are periodically re-resolved and updated. If multiple IPs are returned by a DNS query, all are used. You may also enter an IP range such as 192.168.1.1-192.168.1.10 or a small subnet such as 192.168.1.16/28 and a list of individual IP addresses will be generated."); $ports_help = gettext("Enter as many ports as you wish. Port ranges can be expressed by separating with a colon."); $url_help = sprintf(gettext("Enter as many URLs as you wish. After saving %s will download the URL and import the items into the alias. Use only with small sets of IP addresses (less than 3000)."), $g['product_name']); $url_ports_help = sprintf(gettext("Enter as many URLs as you wish. After saving %s will download the URL and import the items into the alias. Use only with small sets of Ports (less than 3000)."), $g['product_name']); @@ -726,7 +803,7 @@ if (empty($tab)) { $addresses = explode(" ", $pconfig['address']); $details = explode("||", $pconfig['detail']); while ($counter < count($addresses)): - if (is_subnet($addresses[$counter])) { + if (($pconfig['type'] != "host") && is_subnet($addresses[$counter])) { list($address, $address_subnet) = explode("/", $addresses[$counter]); } else { $address = $addresses[$counter]; From bb67ac32bc2a27321cc7c0b2d24f9adc9639584d Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Fri, 24 Oct 2014 20:17:04 +0545 Subject: [PATCH 4/5] 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(-) diff --git a/etc/inc/util.inc b/etc/inc/util.inc index bf77e95373..683061ce2d 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) From 577b776e556f68234d6657b210ec2d150a66d6e6 Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Fri, 24 Oct 2014 20:23:00 +0545 Subject: [PATCH 5/5] Warn if attempting to import IPv6 range There is currently no code to convert an IPv6 range to a set of corresponding IPv6 subnets, so warn the user if they attempt that from the alias bulk import GUI. --- usr/local/www/firewall_aliases_import.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/usr/local/www/firewall_aliases_import.php b/usr/local/www/firewall_aliases_import.php index f7444414f0..f7c259e8d9 100755 --- a/usr/local/www/firewall_aliases_import.php +++ b/usr/local/www/firewall_aliases_import.php @@ -101,12 +101,15 @@ if($_POST['aliasimport'] <> "") { $impdesc = trim($implinea[1]); if (strlen($impdesc) < 200) { if ((strpos($impdesc, "||") === false) && (substr($impdesc, 0, 1) != "|") && (substr($impdesc, -1, 1) != "|")) { - if (is_iprange($impip)) { + $iprange_type = is_iprange($impip); + if ($iprange_type == 4) { list($startip, $endip) = explode('-', $impip); $rangesubnets = ip_range_to_subnet_array($startip, $endip); $imported_ips = array_merge($imported_ips, $rangesubnets); $rangedescs = array_fill(0, count($rangesubnets), $impdesc); $imported_descs = array_merge($imported_descs, $rangedescs); + } else if ($iprange_type == 6) { + $input_errors[] = sprintf(gettext('IPv6 address ranges are not supported (%s)'), $impip); } else if (!is_ipaddr($impip) && !is_subnet($impip) && !is_hostname($impip) && !empty($impip)) { $input_errors[] = sprintf(gettext("%s is not an IP address. Please correct the error to continue"), $impip); } elseif (!empty($impip)) {