Project

General

Profile

« Previous | Next » 

Revision feb1953e

Added by Phil Davis almost 11 years ago

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.

View differences:

usr/local/www/firewall_aliases_edit.php
63 63

  
64 64
$reserved_ifs = get_configured_interface_list(false, true);
65 65
$reserved_keywords = array_merge($reserved_keywords, $reserved_ifs, $reserved_table_names);
66
$max_alias_addresses = 5000;
66 67

  
67 68
if (!is_array($config['aliases']['alias']))
68 69
	$config['aliases']['alias'] = array();
......
202 203
		$desc_fmt_err_found = false;
203 204

  
204 205
		/* item is a url type */
205
		for($x=0; $x<4999; $x++) {
206
		for($x=0; $x<$max_alias_addresses-1; $x++) {
206 207
			$_POST['address' . $x] = trim($_POST['address' . $x]);
207 208
			if($_POST['address' . $x]) {
208 209
				/* fetch down and add in */
......
280 281
		/* item is a normal alias type */
281 282
		$wrongaliases = "";
282 283
		$desc_fmt_err_found = false;
284
		$alias_address_count = 0;
283 285

  
284 286
		// First trim and expand the input data. 
285 287
		// Users can paste strings like "10.1.2.0/24 10.3.0.0/16 9.10.11.0/24" into an address box.
286 288
		// They can also put an IP range.
287 289
		// This loop expands out that stuff so it can easily be validated.
288
		for($x=0; $x<4999; $x++) {
290
		for($x=0; $x<($max_alias_addresses-1); $x++) {
289 291
			if($_POST["address{$x}"] <> "") {
290 292
				if ($_POST["detail{$x}"] <> "") {
291 293
					if ((strpos($_POST["detail{$x}"], "||") === false) && (substr($_POST["detail{$x}"], 0, 1) != "|") && (substr($_POST["detail{$x}"], -1, 1) != "|")) {
......
304 306
				}
305 307
				$address_items = explode(" ", trim($_POST["address{$x}"]));
306 308
				foreach ($address_items as $address_item) {
307
					if (is_iprange($address_item)) {
309
					$iprange_type = is_iprange($address_item);
310
					if ($iprange_type == 4) {
308 311
						list($startip, $endip) = explode('-', $address_item);
309
						$rangesubnets = ip_range_to_subnet_array($startip, $endip);
310
						foreach ($rangesubnets as $rangesubnet) {
311
							list($address_part, $subnet_part) = explode("/", $rangesubnet);
312
							$input_addresses[] = $address_part;
313
							$input_address_subnet[] = $subnet_part;
314
							$final_address_details[] = $detail_text;
312
						if ($_POST['type'] == "network") {
313
							// For network type aliases, expand an IPv4 range into an array of subnets.
314
							$rangesubnets = ip_range_to_subnet_array($startip, $endip);
315
							foreach ($rangesubnets as $rangesubnet) {
316
								if ($alias_address_count > $max_alias_addresses) {
317
									break;
318
								}
319
								list($address_part, $subnet_part) = explode("/", $rangesubnet);
320
								$input_addresses[] = $address_part;
321
								$input_address_subnet[] = $subnet_part;
322
								$final_address_details[] = $detail_text;
323
								$alias_address_count++;
324
							}
325
						} else {
326
							// For host type aliases, expand an IPv4 range into a list of individual IPv4 addresses.
327
							$rangeaddresses = ip_range_to_address_array($startip, $endip, $max_alias_addresses - $alias_address_count);
328
							if (is_array($rangeaddresses)) {
329
								foreach ($rangeaddresses as $rangeaddress) {
330
									$input_addresses[] = $rangeaddress;
331
									$input_address_subnet[] = "";
332
									$final_address_details[] = $detail_text;
333
									$alias_address_count++;
334
								}
335
							} else {
336
								$input_errors[] = sprintf(gettext('Range is too large to expand into individual host IP addresses (%s)'), $address_item);
337
								$input_errors[] = sprintf(gettext('The maximum number of entries in an alias is %s'), $max_alias_addresses);
338
								// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
339
								$input_addresses[] = $address_item;
340
								$input_address_subnet[] = "";
341
								$final_address_details[] = $detail_text;
342
							}
315 343
						}
316
					} else {
317
						list($address_part, $subnet_part) = explode("/", $address_item);
318
						$input_addresses[] = $address_part;
319
						if (!empty($subnet_part))
320
							$input_address_subnet[] = $subnet_part;
321
						else
322
							$input_address_subnet[] = $_POST["address_subnet{$x}"];
344
					} else if ($iprange_type == 6) {
345
						$input_errors[] = sprintf(gettext('IPv6 address ranges are not supported (%s)'), $address_item);
346
						// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
347
						$input_addresses[] = $address_item;
348
						$input_address_subnet[] = "";
323 349
						$final_address_details[] = $detail_text;
350
					} else {
351
						$subnet_type = is_subnet($address_item);
352
						if (($_POST['type'] == "host") && $subnet_type) {
353
							if ($subnet_type == 4) {
354
								// For host type aliases, if the user enters an IPv4 subnet, expand it into a list of individual IPv4 addresses.
355
								if (subnet_size($address_item) <= ($max_alias_addresses - $alias_address_count)) {
356
									$rangeaddresses = subnetv4_expand($address_item);
357
									foreach ($rangeaddresses as $rangeaddress) {
358
										$input_addresses[] = $rangeaddress;
359
										$input_address_subnet[] = "";
360
										$final_address_details[] = $detail_text;
361
										$alias_address_count++;
362
									}
363
								} else {
364
									$input_errors[] = sprintf(gettext('Subnet is too large to expand into individual host IP addresses (%s)'), $address_item);
365
									$input_errors[] = sprintf(gettext('The maximum number of entries in an alias is %s'), $max_alias_addresses);
366
									// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
367
									$input_addresses[] = $address_item;
368
									$input_address_subnet[] = "";
369
									$final_address_details[] = $detail_text;
370
								}
371
							} else {
372
								$input_errors[] = sprintf(gettext('IPv6 subnets are not supported in host aliases (%s)'), $address_item);
373
								// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
374
								$input_addresses[] = $address_item;
375
								$input_address_subnet[] = "";
376
								$final_address_details[] = $detail_text;
377
							}
378
						} else {
379
							list($address_part, $subnet_part) = explode("/", $address_item);
380
							if (!empty($subnet_part)) {
381
								if (is_subnet($address_item)) {
382
									$input_addresses[] = $address_part;
383
									$input_address_subnet[] = $subnet_part;
384
								} else {
385
									// The user typed something like "1.2.3.444/24" or "1.2.3.0/36" or similar rubbish.
386
									// Feed it through without splitting it apart, then it will be caught by the validation loop below.
387
									$input_addresses[] = $address_item;
388
									$input_address_subnet[] = "";
389
								}
390
							} else {
391
								$input_addresses[] = $address_part;
392
								$input_address_subnet[] = $_POST["address_subnet{$x}"];
393
							}
394
							$final_address_details[] = $detail_text;
395
							$alias_address_count++;
396
						}
397
					}
398
					if ($alias_address_count > $max_alias_addresses) {
399
						$input_errors[] = sprintf(gettext('The maximum number of entries in an alias has been exceeded (%s)'), $max_alias_addresses);
400
						break;
324 401
					}
325 402
				}
326 403
			}
......
514 591
$update_freq_str = gettext("Update Freq. (days)");
515 592

  
516 593
$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.");
517
$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.");
594
$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.");
518 595
$ports_help = gettext("Enter as many ports as you wish.  Port ranges can be expressed by separating with a colon.");
519 596
$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']);
520 597
$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 803
						$addresses = explode(" ", $pconfig['address']);
727 804
						$details = explode("||", $pconfig['detail']);
728 805
						while ($counter < count($addresses)):
729
							if (is_subnet($addresses[$counter])) {
806
							if (($pconfig['type'] != "host") && is_subnet($addresses[$counter])) {
730 807
								list($address, $address_subnet) = explode("/", $addresses[$counter]);
731 808
							} else {
732 809
								$address = $addresses[$counter];

Also available in: Unified diff