summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarren Embry <dse@webonastick.com>2012-04-05 13:07:20 -0400
committerDarren Embry <dse@webonastick.com>2012-04-05 13:10:41 -0400
commit0917cb214b2bbf7f4b374c901c642987fc4ac63b (patch)
treed38a8193c7e25ea677442ff4cec1af752ea1642c
parent9859b2b5538192e64e650fc84e2a12ba4491d47c (diff)
downloadpfsense-0917cb214b2bbf7f4b374c901c642987fc4ac63b.zip
pfsense-0917cb214b2bbf7f4b374c901c642987fc4ac63b.tar.gz
load balancer: allow IPv4 subnets up to 64 addresses in Pools and Virtual Servers (PEV-394754)
-rw-r--r--etc/inc/util.inc37
-rw-r--r--etc/inc/vslb.inc92
-rwxr-xr-xusr/local/www/load_balancer_pool_edit.php14
-rwxr-xr-xusr/local/www/load_balancer_virtual_server_edit.php6
4 files changed, 108 insertions, 41 deletions
diff --git a/etc/inc/util.inc b/etc/inc/util.inc
index 434862d..3660572 100644
--- a/etc/inc/util.inc
+++ b/etc/inc/util.inc
@@ -1048,6 +1048,43 @@ function alias_expand_urltable($name) {
return null;
}
+function subnet_size ($subnet) {
+ if (is_subnetv4($subnet)) {
+ list ($ip, $bits) = explode("/", $subnet);
+ return round(exp(log(2) * (32 - $bits)));
+ }
+ else if (is_subnetv6($subnet)) {
+ list ($ip, $bits) = explode("/", $subnet);
+ return round(exp(log(2) * (128 - $bits)));
+ }
+ else {
+ return 0;
+ }
+}
+
+function subnet_expand ($subnet) {
+ if (is_subnetv4($subnet)) {
+ return subnetv4_expand($subnet);
+ } else if (is_subnetv6($subnet)) {
+ return subnetv6_expand($subnet);
+ } else {
+ return $subnet;
+ }
+}
+
+function subnetv4_expand ($subnet) {
+ $result = array();
+ list ($ip, $bits) = explode("/", $subnet);
+ $net = ip2long($ip);
+ $mask = (0xffffffff << (32 - $bits));
+ $net &= $mask;
+ $size = round(exp(log(2) * (32 - $bits)));
+ for ($i = 0; $i < $size; $i += 1) {
+ $result[] = long2ip($net | $i);
+ }
+ return $result;
+}
+
/* find out whether two subnets overlap */
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
diff --git a/etc/inc/vslb.inc b/etc/inc/vslb.inc
index 1fd9f77..d6d9931 100644
--- a/etc/inc/vslb.inc
+++ b/etc/inc/vslb.inc
@@ -217,11 +217,21 @@ function relayd_configure($kill_first=false) {
if(is_array($pool_a[$i]['servers'])) {
if (!empty($pool_a[$i]['retry'])) {
$retrytext = " retry {$pool_a[$i]['retry']}";
- $srvtxt = implode("{$retrytext}, ", $pool_a[$i]['servers']) . "{$retrytext}";
} else {
- $srvtxt = implode(", ", $pool_a[$i]['servers']);
+ $retrytext = "";
}
- $conf .= "table <{$pool_a[$i]['name']}> { $srvtxt }\n";
+ $conf .= "table <{$pool_a[$i]['name']}> {\n";
+ foreach ($pool_a[$i]['servers'] as $server) {
+ if (is_subnetv4($server)) {
+ foreach (subnetv4_expand($server) as $ip) {
+ $conf .= "\t{$ip}{$retrytext}\n";
+ }
+ }
+ else {
+ $conf .= "\t{$server}{$retrytext}\n";
+ }
+ }
+ $conf .= "}\n";
/* Index by name for easier fetching when we loop through the virtual servers */
$pools[$pool_a[$i]['name']] = $pool_a[$i];
}
@@ -244,43 +254,55 @@ function relayd_configure($kill_first=false) {
// }
$conf .= "dns protocol \"dnsproto\" {\n";
- $conf .= "\ttcp { nodelay, sack, socket buffer 1024, backlog 1000 }\n";
+ $conf .= "\t" . "tcp { nodelay, sack, socket buffer 1024, backlog 1000 }\n";
$conf .= "}\n";
if(is_array($vs_a)) {
for ($i = 0; isset($vs_a[$i]); $i++) {
- if (($vs_a[$i]['mode'] == 'relay') || ($vs_a[$i]['relay_protocol'] == 'dns')) {
- $conf .= "relay \"{$vs_a[$i]['name']}\" {\n";
- $conf .= " listen on {$vs_a[$i]['ipaddr']} port {$vs_a[$i]['port']}\n";
-
- if ($vs_a[$i]['relay_protocol'] == "dns") {
- $conf .= " protocol \"dnsproto\"\n";
- } else {
- $conf .= " protocol \"{$vs_a[$i]['relay_protocol']}\"\n";
- }
- $lbmode = "";
- if ( $pools[$vs_a[$i]['pool']]['mode'] == "loadbalance" ) {
- $lbmode = "mode loadbalance";
+ if (is_subnetv4($vs_a[$i]['ipaddr'])) {
+ $ip_list = subnetv4_expand($vs_a[$i]['ipaddr']);
+ $name_format = "%s_%d";
+ }
+ else {
+ $ip_list = array($vs_a[$i]['ipaddr']);
+ $name_format = "%s"; /* in which case the second arg of the sprintf call below will be silently ignored */
+ }
+ for ($j = 0; $j < count($ip_list); $j += 1) {
+ $ip = $ip_list[$j];
+ $name = sprintf($name_format, $vs_a[$i]['name'], $j);
+ if (($vs_a[$i]['mode'] == 'relay') || ($vs_a[$i]['relay_protocol'] == 'dns')) {
+ $conf .= "relay \"{$name}\" {\n";
+ $conf .= " listen on {$ip} port {$vs_a[$i]['port']}\n";
+
+ if ($vs_a[$i]['relay_protocol'] == "dns") {
+ $conf .= " protocol \"dnsproto\"\n";
+ } else {
+ $conf .= " protocol \"{$vs_a[$i]['relay_protocol']}\"\n";
+ }
+ $lbmode = "";
+ if ( $pools[$vs_a[$i]['pool']]['mode'] == "loadbalance" ) {
+ $lbmode = "mode loadbalance";
+ }
+
+ $conf .= " forward to <{$vs_a[$i]['pool']}> port {$pools[$vs_a[$i]['pool']]['port']} {$lbmode} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
+
+ if (isset($vs_a[$i]['sitedown']) && strlen($vs_a[$i]['sitedown']) > 0)
+ $conf .= " forward to <{$vs_a[$i]['sitedown']}> port {$pools[$vs_a[$i]['pool']]['port']} {$lbmode} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
+ $conf .= "}\n";
+ } else {
+ $conf .= "redirect \"{$name}\" {\n";
+ $conf .= " listen on {$ip} port {$vs_a[$i]['port']}\n";
+ $conf .= " forward to <{$vs_a[$i]['pool']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
+
+ if (isset($config['system']['lb_use_sticky']))
+ $conf .= " sticky-address\n";
+
+ /* sitedown MUST use the same port as the primary pool - sucks, but it's a relayd thing */
+ if (isset($vs_a[$i]['sitedown']) && strlen($vs_a[$i]['sitedown']) > 0)
+ $conf .= " forward to <{$vs_a[$i]['sitedown']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
+
+ $conf .= "}\n";
}
-
- $conf .= " forward to <{$vs_a[$i]['pool']}> port {$pools[$vs_a[$i]['pool']]['port']} {$lbmode} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
-
- if (isset($vs_a[$i]['sitedown']) && strlen($vs_a[$i]['sitedown']) > 0)
- $conf .= " forward to <{$vs_a[$i]['sitedown']}> port {$pools[$vs_a[$i]['pool']]['port']} {$lbmode} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
- $conf .= "}\n";
- } else {
- $conf .= "redirect \"{$vs_a[$i]['name']}\" {\n";
- $conf .= " listen on {$vs_a[$i]['ipaddr']} port {$vs_a[$i]['port']}\n";
- $conf .= " forward to <{$vs_a[$i]['pool']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
-
- if (isset($config['system']['lb_use_sticky']))
- $conf .= " sticky-address\n";
-
- /* sitedown MUST use the same port as the primary pool - sucks, but it's a relayd thing */
- if (isset($vs_a[$i]['sitedown']) && strlen($vs_a[$i]['sitedown']) > 0)
- $conf .= " forward to <{$vs_a[$i]['sitedown']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
-
- $conf .= "}\n";
}
}
}
diff --git a/usr/local/www/load_balancer_pool_edit.php b/usr/local/www/load_balancer_pool_edit.php
index d42e0b6..81a548c 100755
--- a/usr/local/www/load_balancer_pool_edit.php
+++ b/usr/local/www/load_balancer_pool_edit.php
@@ -94,15 +94,21 @@ if ($_POST) {
if (is_array($_POST['servers'])) {
foreach($pconfig['servers'] as $svrent) {
- if (!is_ipaddr($svrent)) {
- $input_errors[] = sprintf(gettext("%s is not a valid IP address (in \"enabled\" list)."), $svrent);
+ if (!is_ipaddr($svrent) && !is_subnetv4($svrent)) {
+ $input_errors[] = sprintf(gettext("%s is not a valid IP address or IPv4 subnet (in \"enabled\" list)."), $svrent);
+ }
+ else if (is_subnetv4($svrent) && subnet_size($svrent) > 64) {
+ $input_errors[] = sprintf(gettext("%s is a subnet containing more than 64 IP addresses (in \"enabled\" list)."), $svrent);
}
}
}
if (is_array($_POST['serversdisabled'])) {
foreach($pconfig['serversdisabled'] as $svrent) {
- if (!is_ipaddr($svrent)) {
- $input_errors[] = sprintf(gettext("%s is not a valid IP address (in \"disabled\" list)."), $svrent);
+ if (!is_ipaddr($svrent) && !is_subnetv4($svrent)) {
+ $input_errors[] = sprintf(gettext("%s is not a valid IP address or IPv4 subnet (in \"disabled\" list)."), $svrent);
+ }
+ else if (is_subnetv4($svrent) && subnet_size($svrent) > 64) {
+ $input_errors[] = sprintf(gettext("%s is a subnet containing more than 64 IP addresses (in \"disabled\" list)."), $svrent);
}
}
}
diff --git a/usr/local/www/load_balancer_virtual_server_edit.php b/usr/local/www/load_balancer_virtual_server_edit.php
index 7a2d792..ff59fd9 100755
--- a/usr/local/www/load_balancer_virtual_server_edit.php
+++ b/usr/local/www/load_balancer_virtual_server_edit.php
@@ -91,8 +91,10 @@ if ($_POST) {
if (!is_port($_POST['port']))
$input_errors[] = gettext("The port must be an integer between 1 and 65535.");
- if(!is_ipaddr($_POST['ipaddr']))
- $input_errors[] = sprintf(gettext("%s is not a valid IP address."), $_POST['ipaddr']);
+ if (!is_ipaddr($_POST['ipaddr']) && !is_subnetv4($_POST['ipaddr']))
+ $input_errors[] = sprintf(gettext("%s is not a valid IP address or IPv4 subnet."), $_POST['ipaddr']);
+ else if (is_subnetv4($_POST['ipaddr']) && subnet_size($_POST['ipaddr']) > 64)
+ $input_errors[] = sprintf(gettext("%s is a subnet containing more than 64 IP addresses."), $_POST['ipaddr']);
if (!$input_errors) {
$vsent = array();
OpenPOWER on IntegriCloud