diff options
Diffstat (limited to 'config/haproxy-devel')
-rw-r--r-- | config/haproxy-devel/haproxy.inc | 463 | ||||
-rw-r--r-- | config/haproxy-devel/haproxy.xml | 5 | ||||
-rw-r--r-- | config/haproxy-devel/haproxy_files.php | 176 | ||||
-rw-r--r-- | config/haproxy-devel/haproxy_htmllist.inc | 423 | ||||
-rw-r--r-- | config/haproxy-devel/haproxy_listeners.php | 35 | ||||
-rw-r--r-- | config/haproxy-devel/haproxy_listeners_edit.php | 139 | ||||
-rw-r--r-- | config/haproxy-devel/haproxy_pool_edit.php | 40 | ||||
-rw-r--r-- | config/haproxy-devel/pkg_haproxy_tabs.inc | 2 |
8 files changed, 948 insertions, 335 deletions
diff --git a/config/haproxy-devel/haproxy.inc b/config/haproxy-devel/haproxy.inc index 07086bd5..fd086cfc 100644 --- a/config/haproxy-devel/haproxy.inc +++ b/config/haproxy-devel/haproxy.inc @@ -38,6 +38,13 @@ require_once("haproxy_xmlrpcsyncclient.inc"); $d_haproxyconfdirty_path = $g['varrun_path'] . "/haproxy.conf.dirty"; +global $a_frontendmode; +$a_frontendmode = array(); +$a_frontendmode['http'] = array('name' => "http / https(offloading)", 'shortname' => "http/https"); +$a_frontendmode['https'] = array('name' => "ssl / https(TCP mode)", 'shortname' => "ssl/https"); +$a_frontendmode['tcp'] = array('name' => "tcp", 'shortname' => "tcp"); +$a_frontendmode['health'] = array('name' => "health", 'shortname' => "health"); + global $a_acltypes; $a_acltypes = array(); $a_acltypes["host_starts_with"] = array('name' => 'Host starts with:', @@ -84,6 +91,8 @@ $a_acltypes["ssl_sni_starts_with"] = array('name' => 'Server Name Indication TLS 'mode' => 'https', 'syntax' => 'req.ssl_sni -m beg -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }"); $a_acltypes["ssl_sni_ends_with"] = array('name' => 'Server Name Indication TLS extension ends with:', 'inspect-delay' => '5', 'mode' => 'https', 'syntax' => 'req.ssl_sni -m end -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }"); +$a_acltypes["ssl_sni_ends_with"] = array('name' => 'Server Name Indication TLS extension regex:', 'inspect-delay' => '5', + 'mode' => 'https', 'syntax' => 'req.ssl_sni -m reg -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }"); $a_acltypes["custom"] = array('name' => 'Custom acl:', 'mode' => '', 'syntax' => '%1$s'); @@ -187,6 +196,19 @@ $a_sticky_type['stick_rdp_cookie'] = array('name' => 'Stick on RDP-cookie', 'descr' => "Uses a RDP-Cookie send by the mstsc client, note that not all clients send this.", 'cookiedescr' => 'EXAMPLE: msts or mstshash'); + +global $a_error; +$a_error = array(); +$a_error['200'] = array('descr' => "stats or monitoring requests"); +$a_error['400'] = array('descr' => "request invalid or too large"); +$a_error['401'] = array('descr' => "authentication is required to perform the action"); +$a_error['403'] = array('descr' => "request is forbidden"); +$a_error['408'] = array('descr' => "timeout before the request is complete"); +$a_error['500'] = array('descr' => "internal error"); +$a_error['502'] = array('descr' => "server response invalid or blocked"); +$a_error['503'] = array('descr' => "no server was available to handle the request"); +$a_error['504'] = array('descr' => "timeout before the server responds"); + if(!function_exists('group_ports')){ // function group_ports() is present in pfSense 2.2 in util.inc /* create ranges of sequential port numbers (200:215) and remove duplicates */ @@ -237,10 +259,11 @@ function group_ports($ports) { return $result; } } - + function haproxy_portoralias_to_list($port_or_alias) { // input: a port or aliasname: 80 https MyPortAlias // returns: a array of ports and portranges 80 443 8000:8010 + global $aliastable; $portresult = array(); if (alias_get_type($port_or_alias) == "port") { @@ -253,15 +276,39 @@ function haproxy_portoralias_to_list($port_or_alias) { return $portresult; } else if (is_portrange($port_or_alias)) { return (array)$port_or_alias; - } else if (is_port($port_or_alias)) { - if (getservbyname($port_or_alias, "tcp")) - return (array)getservbyname($port_or_alias, "tcp"); - if (getservbyname($port_or_alias, "udp")) - return (array)getservbyname($port_or_alias, "udp"); - return (array)$port_or_alias; + } else { + $ports = explode(",", $port_or_alias); + foreach($ports as $port){ + if (is_port($port)) { + if (getservbyname($port, "tcp")) + $port = getservbyname($port, "tcp"); + if (getservbyname($port, "udp")) + $port = getservbyname($port, "udp"); + $portresult[] = $port; + } + } + return $portresult; + } +} +function haproxy_addressoralias_to_list($address_or_alias) { + global $aliastable; + $result = array(); + $alias_type = alias_get_type($address_or_alias); + if (!empty($alias_type)) { + $alias = $aliastable[$address_or_alias]; + if ($alias_type == "url") { + $result = explode(' ',$alias); + } else + if ($alias_type == "network") { + //$result = explode(' ',$alias); + } else + if ($alias_type == "host") { + $result = explode(' ',$alias); + } + } else { + $result[] = $address_or_alias; } - else - return null; + return $result; } function haproxy_hostoralias_to_list($host_or_alias) { @@ -274,6 +321,20 @@ function haproxy_hostoralias_to_list($host_or_alias) { return $result; } +function haproxy_get_fileslist() { + // returns the files array with 'keys'. + $result = array(); + global $config; + // create a copy to not modify the original 'keyless' array + $a_files = $config['installedpackages']['haproxy']['files']['item']; + if (!is_array($a_files)) $a_files = array(); + foreach($a_files as $file) { + $key = $file['name']; + $result[$key] = $file; + } + return $result; +} + function haproxy_custom_php_deinstall_command() { global $static_output; $static_output .= "HAProxy, running haproxy_custom_php_deinstall_command()\n"; @@ -365,107 +426,136 @@ EOD; $static_output .= "HAProxy, update configuration\n"; update_output_window($static_output); - $writeconfigupdate = false; - /* Do XML upgrade from haproxy 0.31 to haproxy-dev */ - if (is_array($config['installedpackages']['haproxy']['ha_servers'])) { - $static_output .= "HAProxy, Do XML upgrade from haproxy 0.31 to haproxy-dev\n"; - update_output_window($static_output); + // make sure the version stays 'comparable' + if (is_arrayset($config,'installedpackages','haproxy') && isset($config['installedpackages']['haproxy']['configversion'])) + $configversion = $config['installedpackages']['haproxy']['configversion']; + else + $configversion = "00.12"; - /* We have an old config */ - $config['installedpackages']['haproxy']['ha_pools']['item'] = array(); - $a_global = &$config['installedpackages']['haproxy']; - $a_backends = &$config['installedpackages']['haproxy']['ha_backends']['item']; - $a_oldservers = &$config['installedpackages']['haproxy']['ha_servers']['item']; - $a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; + $static_output .= "HAProxy, from version $configversion\n"; + update_output_window($static_output); + + $writeconfigupdate = false; + if ($configversion < "00.13") { + /* Do XML upgrade from haproxy 0.31 to haproxy-dev */ + if (is_array($config['installedpackages']['haproxy']['ha_servers'])) { + $static_output .= "HAProxy, Do XML upgrade from haproxy 0.31 to haproxy-dev\n"; + update_output_window($static_output); + + /* We have an old config */ + $config['installedpackages']['haproxy']['ha_pools']['item'] = array(); + $a_global = &$config['installedpackages']['haproxy']; + $a_backends = &$config['installedpackages']['haproxy']['ha_backends']['item']; + $a_oldservers = &$config['installedpackages']['haproxy']['ha_servers']['item']; + $a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; - foreach ($a_backends as $id => $be) { - $a_backends[$id]['status'] = 'active'; - } - $id = 0; - foreach ($a_oldservers as $oldserver) { - $pool=$oldserver; - /* make server sub array */ - $server=array(); - $server['name'] = $oldserver['name']; - $server['address'] = $oldserver['address']; - $server['port'] = $oldserver['port']; - $server['weight'] = $oldserver['weight']; - $a_servers=array(); - $a_servers[]=$server; - /* set new pool */ - $pool['name'] = "pool$id"; - $id++; - $pool['ha_servers']['item']=$a_servers; - /* link to frontend */ foreach ($a_backends as $id => $be) { - if ($a_backends[$id]['name'] == $oldserver['backend']) { - $a_backends[$id]['backend_serverpool'] = $pool['name']; - $pool['monitor_uri'] = $be['monitor_uri']; - unset($a_backends[$id]['monitor_uri']); - break; + $a_backends[$id]['status'] = 'active'; + } + $id = 0; + foreach ($a_oldservers as $oldserver) { + $pool=$oldserver; + /* make server sub array */ + $server=array(); + $server['name'] = $oldserver['name']; + $server['address'] = $oldserver['address']; + $server['port'] = $oldserver['port']; + $server['weight'] = $oldserver['weight']; + $a_servers=array(); + $a_servers[]=$server; + /* set new pool */ + $pool['name'] = "pool$id"; + $id++; + $pool['ha_servers']['item']=$a_servers; + /* link to frontend */ + foreach ($a_backends as $id => $be) { + if ($a_backends[$id]['name'] == $oldserver['backend']) { + $a_backends[$id]['backend_serverpool'] = $pool['name']; + $pool['monitor_uri'] = $be['monitor_uri']; + unset($a_backends[$id]['monitor_uri']); + break; + } } + unset($pool['backend']); + unset($pool['address']); + unset($pool['port']); + unset($pool['weight']); + $a_pools[] = $pool; } - unset($pool['backend']); - unset($pool['address']); - unset($pool['port']); - unset($pool['weight']); - $a_pools[] = $pool; + unset($config['installedpackages']['haproxy']['ha_servers']); + $writeconfigupdate = true; } - unset($config['installedpackages']['haproxy']['ha_servers']); - $writeconfigupdate = true; - } - - /* XML update to: pkg v1.3 and 'pool' changed to 'backend_serverpool' because 'pool' was added to listtags() in xmlparse.inc */ - if (is_arrayset($config,'installedpackages','haproxy','ha_backends','item',0,'pool')) { - $static_output .= "HAProxy, Do XML upgrade, change to backend_serverpool from pool array\n"; - update_output_window($static_output); - - foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) - { - $backend_serverpool = $frontend['pool'][0]; - $frontend['backend_serverpool'] = $backend_serverpool; - unset($frontend['pool']); + + /* XML update to: pkg v1.3 and 'pool' changed to 'backend_serverpool' because 'pool' was added to listtags() in xmlparse.inc */ + if (is_arrayset($config,'installedpackages','haproxy','ha_backends','item',0,'pool')) { + $static_output .= "HAProxy, Do XML upgrade, change to backend_serverpool from pool array\n"; + update_output_window($static_output); + + foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) + { + $backend_serverpool = $frontend['pool'][0]; + $frontend['backend_serverpool'] = $backend_serverpool; + unset($frontend['pool']); + } + $writeconfigupdate = true; } - $writeconfigupdate = true; - } - //also move setting for existing 2.0 installations as only the new variable is used - if (is_arrayset($config,'installedpackages','haproxy','ha_backends','item',0) && - isset($config['installedpackages']['haproxy']['ha_backends']['item'][0]['pool'])) { - $static_output .= "HAProxy, Do XML upgrade, change to backend_serverpool from pool\n"; - update_output_window($static_output); - foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) - { - $backend_serverpool = $frontend['pool']; - $frontend['backend_serverpool'] = $backend_serverpool; - unset($frontend['pool']); + //also move setting for existing 2.0 installations as only the new variable is used + if (is_arrayset($config,'installedpackages','haproxy','ha_backends','item',0) && + isset($config['installedpackages']['haproxy']['ha_backends']['item'][0]['pool'])) { + $static_output .= "HAProxy, Do XML upgrade, change to backend_serverpool from pool\n"; + update_output_window($static_output); + foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) + { + $backend_serverpool = $frontend['pool']; + $frontend['backend_serverpool'] = $backend_serverpool; + unset($frontend['pool']); + } + $writeconfigupdate = true; + } + // update config to "haproxy-devel 1.5-dev19 pkg v0.5" + if(is_arrayset($config,'installedpackages','haproxy','ha_backends','item')) { + $static_output .= "HAProxy, Do XML upgrade, update frontend options\n"; + update_output_window($static_output); + foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) { + if($bind['httpclose'] && $bind['httpclose'] == "yes" ) { + $bind['httpclose'] = "httpclose"; + $writeconfigupdate = true; + } + if (!$bind['extaddr']){ + $bind['extaddr'] = "wan_ipv4"; + $writeconfigupdate = true; + } + if ($bind['extaddr'] == "localhost"){ + $bind['extaddr'] = "localhost_ipv4"; + $writeconfigupdate = true; + } + if ($bind['extaddr'] == "any"){ + $bind['extaddr'] = "any_ipv4"; + $writeconfigupdate = true; + } + } } - $writeconfigupdate = true; } - // update config to "haproxy-devel 1.5-dev19 pkg v0.5" - if(is_arrayset($config,'installedpackages','haproxy','ha_backends','item')) { - $static_output .= "HAProxy, Do XML upgrade, update frontend options\n"; - update_output_window($static_output); + if ($configversion == "00.12") { + // update config to "haproxy-devel 1.5-dev19 pkg v0.13" foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) { - if($bind['httpclose'] && $bind['httpclose'] == "yes" ) { - $bind['httpclose'] = "httpclose"; - $writeconfigupdate = true; - } - if (!$bind['extaddr']){ - $bind['extaddr'] = "wan_ipv4"; - $writeconfigupdate = true; - } - if ($bind['extaddr'] == "localhost"){ - $bind['extaddr'] = "localhost_ipv4"; - $writeconfigupdate = true; - } - if ($bind['extaddr'] == "any"){ - $bind['extaddr'] = "any_ipv4"; - $writeconfigupdate = true; + if (isset($bind['extaddr'])) { + $new['extaddr'] = $bind['extaddr']; + $new['extaddr_port'] = $bind['port']; + $new['extaddr_ssl'] = $bind['ssloffload']; + $bind['a_extaddr']['item'][] = $new; } + unset($bind['extaddr']); + unset($bind['port']); + //unset($bind['ssloffload']); } + $configversion = "00.13"; } + + $writeconfigupdate = $config['installedpackages']['haproxy']['configversion'] <> $configversion; if ($writeconfigupdate) { - $static_output .= "HAProxy, write updated config\n"; + $config['installedpackages']['haproxy']['configversion'] = $configversion; + $static_output .= "HAProxy, write updated config to version: $configversion\n"; update_output_window($static_output); write_config("HAProxy, update xml config version"); } @@ -540,11 +630,10 @@ function haproxy_find_acl($name) { function write_backend($configpath, $fd, $name, $pool, $frontend) { if(!is_array($pool['ha_servers']['item']) && !$pool['stats_enabled']=='yes') return; - global $a_checktypes, $a_cookiemode; + global $a_checktypes, $a_cookiemode, $a_files, $a_error; $a_servers = &$pool['ha_servers']['item']; $frontendtype = $frontend['type']; - $frontend_ip = haproxy_interface_ip($frontend['extaddr']); fwrite ($fd, "backend " . $name . "\n"); // https is an alias for tcp for clarity purposes @@ -604,6 +693,23 @@ function write_backend($configpath, $fd, $name, $pool, $frontend) { fwrite ($fd, "\tstats\t\t\tscope " . $scope_item . "\n"); } } + + if (is_arrayset($pool,'errorfiles','item')) { + foreach($pool['errorfiles']['item'] as $errorfile) { + if (!is_array($a_files))// load only once + $a_files = haproxy_get_fileslist(); + $file = $errorfile['errorfile']; + $errorcodes = explode(",",$errorfile['errorcode']); + foreach($errorcodes as $errorcode) { + $filename = "$configpath/errorfile_{$name}_{$errorcode}_{$file}"; + $content = base64_decode($a_files[$file]['content']); + $content = str_replace('{errormsg}', $a_error[$errorcode]['descr'], $content); + $content = str_replace('{errorcode}', $errorcode, $content); + file_put_contents($filename, $content); + fwrite ($fd, "\terrorfile\t\t\t" . $errorcode ." " . $filename . "\n"); + } + } + } } switch($pool["persist_sticky_type"]) { @@ -678,11 +784,19 @@ function write_backend($configpath, $fd, $name, $pool, $frontend) { $pool['retries'] = 3; fwrite ($fd, "\tretries\t\t\t" . $pool['retries'] . "\n"); + $uses_ipv6 = false; + $ips = get_frontend_ipport($frontend); + foreach($ips as $ip){ + $uses_ipv6 = is_ipaddrv6($ip['addr']); + if ($uses_ipv6) + break; + } + if ($pool['transparent_clientip']) { - if (is_ipaddrv4($frontend_ip)) - fwrite ($fd, "\tsource 0.0.0.0 usesrc clientip\n"); - else + if ($uses_ipv6) fwrite ($fd, "\tsource ipv6@ usesrc clientip\n"); + else + fwrite ($fd, "\tsource 0.0.0.0 usesrc clientip\n"); } $uri = $pool['monitor_uri']; @@ -875,6 +989,9 @@ function haproxy_write_certificate_fullchain($filename, $certid, $append = false function haproxy_writeconf($configpath) { global $config; + global $aliastable; + if (!isset($aliastable)) + alias_make_table($config); $chroot_dir = "/tmp/haproxy_chroot"; // can contain socket to forward connection from backend to frontend. "/var/empty" make_dirs($chroot_dir); @@ -951,7 +1068,8 @@ function haproxy_writeconf($configpath) { if(!$frontend['backend_serverpool']) continue; $primaryfrontend = get_primaryfrontend($frontend); - $bname = get_frontend_ipport($frontend); + + $bname = $primaryfrontend['name']; if (!is_array($a_bind[$bname])) { $a_bind[$bname] = array(); $a_bind[$bname] = $primaryfrontend; @@ -959,12 +1077,14 @@ function haproxy_writeconf($configpath) { } //check ssl info - if (strtolower($primaryfrontend['type']) == "http" && $frontend['ssloffload']){ + $ssl = get_frontend_uses_ssl($frontend); + + if ($ssl) { //ssl crt ./server.pem ca-file ./ca.crt verify optional crt-ignore-err all crl-file ./ca_crl.pem - $filename = "$configpath/{$frontend['name']}.{$frontend['port']}.pem"; + $filename = "$configpath/{$frontend['name']}.pem"; $ssl_crt = " crt $filename"; haproxy_write_certificate_fullchain($filename, $frontend['ssloffloadcert']); - $subfolder = "$configpath/{$frontend['name']}.{$frontend['port']}"; + $subfolder = "$configpath/{$frontend['name']}"; $certs = $frontend['ha_certificates']['item']; if (is_array($certs)){ if (count($certs) > 0){ @@ -1032,8 +1152,8 @@ function haproxy_writeconf($configpath) { } // Prepare ports for processing by splitting - $portss = "{$bind['port']},"; - $ports = split(",", $portss); + //$portss = "{$bind['port']},"; + //$ports = split(",", $portss); if($bind['type'] == "http") { // ssl offloading is only possible in http mode. @@ -1043,25 +1163,41 @@ function haproxy_writeconf($configpath) { $ssl_info = ""; $advanced_bind = ""; } + + fwrite ($fd, "{$frontendinfo}"); + // Initialize variable $listenip = ""; // Process and add bind directives for ports - $ip = haproxy_interface_ip($bind['extaddr']); - if ($ip){ - foreach($ports as $alias_or_port) { - if($alias_or_port) { - $portsnumeric = group_ports(haproxy_portoralias_to_list($alias_or_port)); - foreach($portsnumeric as $portnumeric) { - $portnumeric = str_replace(":","-",$portnumeric); - $listenip .= "\tbind\t\t\t$ip:{$portnumeric} {$ssl_info} {$advanced_bind}\n"; + if (isset($bind['a_extaddr'])) { + foreach($bind['a_extaddr']['item'] as $extaddr) { + $a_ip = array(); + if (isset($extaddr['extaddr']) && $extaddr['extaddr'] != "custom") { + $a_ip[] = haproxy_interface_ip($extaddr['extaddr']); + } else { + $iporalias = $extaddr['extaddr_custom']; + $a_ip = haproxy_addressoralias_to_list($iporalias); + } + + if ($extaddr['extaddr_ssl'] == 'yes') + $ssl = $ssl_info; + else + $ssl = ""; + + foreach($a_ip as $ip) { + $portsnumeric = group_ports(haproxy_portoralias_to_list($extaddr['extaddr_port'])); + if (is_array($portsnumeric)) { + foreach($portsnumeric as $portnumeric) { + $portnumeric = str_replace(":","-",$portnumeric); + $listenip .= "\tbind\t\t\t$ip:{$portnumeric} {$ssl} {$advanced_bind} {$extaddr['extaddr_advanced']}\n"; + } } } } } - - fwrite ($fd, "{$frontendinfo}"); fwrite ($fd, "{$listenip}"); + if (use_frontend_as_unixsocket($bind['name'])){ fwrite ($fd, "\tbind /tmp/haproxy_chroot/{$bind['name']}.socket accept-proxy {$ssl_info} {$advanced_bind}\n"); } @@ -1106,10 +1242,9 @@ function haproxy_writeconf($configpath) { if($bind['forwardfor']) { fwrite ($fd, "\toption\t\t\tforwardfor\n"); - if($bind['ssloffload'] == "yes") - fwrite ($fd, "\treqadd X-Forwarded-Proto:\ https\n"); - else - fwrite ($fd, "\treqadd X-Forwarded-Proto:\ http\n"); + fwrite ($fd, "\tacl https ssl_fc\n"); + fwrite ($fd, "\treqadd X-Forwarded-Proto:\ http if !https\n"); + fwrite ($fd, "\treqadd X-Forwarded-Proto:\ https if https\n"); } } @@ -1392,8 +1527,7 @@ function haproxy_plugin_certificates($pluginparams) { $result['certificatelist'] = array(); // return a array of used certificates. foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) { - $mainfrontend = get_primaryfrontend($frontend); - if (strtolower($mainfrontend['type']) == "http" && $mainfrontend['ssloffload']) { + if (get_frontend_uses_ssl($frontend)) { if ($frontend['ssloffloadacl']){ $item = array(); $cert = $frontend['ssloffloadcert']; @@ -1581,12 +1715,30 @@ function get_primaryfrontend($frontend) { return $mainfrontend; } -function get_frontend_ipport($frontend,$userfriendly=false) { +function get_frontend_ipport($frontend, $userfriendly=false) { $mainfrontend = get_primaryfrontend($frontend); - $result = haproxy_interface_ip($mainfrontend['extaddr'], $userfriendly); - if ($userfriendly and is_ipaddrv6($result)) - $result = "[{$result}]"; - return $result . ":" . $mainfrontend['port']; + $newline = ""; + $result = array(); + if (!is_arrayset($mainfrontend,"a_extaddr","item")) + return $result; + foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { + if ($extaddr['extaddr'] == 'custom'){ + $addr = $extaddr['extaddr_custom']; + } else { + $addr = haproxy_interface_ip($extaddr['extaddr'], $userfriendly); + } + if ($userfriendly and is_ipaddrv6($addr)) + $addr = "[{$addr}]"; + + $port = $extaddr['extaddr_port']; + $newitem = array(); + $newitem['addr'] = $addr; + $newitem['port'] = $port; + $newitem['ssl'] = $extaddr['extaddr_ssl']; + $result[$addr.$port] = $newitem; + } + ksort($result); + return $result; } function haproxy_check_config() { @@ -1599,17 +1751,20 @@ function haproxy_check_config() { foreach($a_backends as $frontend) { if (($frontend['status'] != 'active') || ($frontend['secondary'] == 'yes')) continue; - $ipport = get_frontend_ipport($frontend); - if (isset($activefrontends[$ipport])) - $issues['P_'.$ipport] = "Multiple primary frontends with IP:Port \"$ipport\""; - else - $activefrontends[$ipport] = true; + $ipports = get_frontend_ipport($frontend); + foreach($ipports as $ipport) { + $id = "{$ipport['addr']}:{$ipport['port']}"; + if (isset($activefrontends[$id])) + $issues['P_'.$id] = "Multiple primary frontends with IP:Port \"$id\""; + else + $activefrontends[$id] = true; + } } foreach($a_backends as $frontend) { if (($frontend['status'] != 'active') || ($frontend['secondary'] != 'yes')) continue; - $ipport = get_frontend_ipport($frontend); - if (!isset($activefrontends[$ipport])) + $mainfrontend = get_primaryfrontend($frontend); + if (!isset($mainfrontend)) $issues['S_'.$frontend['name']] = "Secondary frontend \"{$frontend['name']}\" without active primary frontend."; } foreach ($issues as $item) @@ -1621,6 +1776,8 @@ function get_haproxy_frontends($excludeitem="") { global $config; $a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; $result = array(); + if(!is_array($a_frontend)) + return $result; foreach($a_frontend as &$frontend) { if ($frontend['secondary']) @@ -1628,17 +1785,43 @@ function get_haproxy_frontends($excludeitem="") { if ($frontend['name'] == $excludeitem) continue; - $serveradress = "{$frontend['extaddr']}:{$frontend['port']}"; - $result[$frontend['name']]['name'] = "{$frontend['name']} - {$frontend['type']} ({$serveradress})"; + $serveraddress = get_frontend_ipport($frontend, true); + $serveradresstext = null; + foreach($serveraddress as $addr) { + $serveradresstext .=($serveradresstext == null ? "" : ", ") . "{$addr['addr']}:{$addr['port']}"; + } + $result[$frontend['name']]['name'] = "{$frontend['name']} - {$frontend['type']} ({$serveradresstext})"; $result[$frontend['name']]['ref'] = &$frontend; } uasort($result, haproxy_compareByName); return $result; } -function generate_cert_acl($crt, $defaultport, $nondefaultport){ - // The host header send by a browser will contain the portnumber when a nondefault port is used for the server side. +function get_frontend_uses_ssl($frontend) { + $mainfrontend = get_primaryfrontend($frontend); + $ssl = false; + if (is_arrayset($mainfrontend,'a_extaddr','item')) { + foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { + if ($extaddr['extaddr_ssl'] == 'yes') { + $ssl = true; + break; + } + } + } + if ($mainfrontend['name'] != $frontend['name']) + $ssl = $ssl && $frontend['ssloffload'] == 'yes'; + return $ssl; +} +function get_frontend_uses_ssl_only($frontend) { + $mainfrontend = get_primaryfrontend($frontend); + if (is_arrayset($mainfrontend,'a_extaddr','item')) { + foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { + if ($extaddr['extaddr_ssl'] != 'yes') + return false; + } + } + return true; } function get_frontend_acls($frontend) { @@ -1664,7 +1847,7 @@ function get_frontend_acls($frontend) { } } - if (strtolower($mainfrontend['type']) == "http" && $mainfrontend['ssloffload']) { + if (get_frontend_uses_ssl($frontend)) { $a_acl = &$frontend['ha_acls']['item']; if(!is_array($a_acl)) $a_acl=array(); diff --git a/config/haproxy-devel/haproxy.xml b/config/haproxy-devel/haproxy.xml index acd934a7..6156c174 100644 --- a/config/haproxy-devel/haproxy.xml +++ b/config/haproxy-devel/haproxy.xml @@ -90,6 +90,11 @@ <additional_files_needed> <prefix>/usr/local/www/</prefix> <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy_files.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/</prefix> + <chmod>077</chmod> <item>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy_pools.php</item> </additional_files_needed> <additional_files_needed> diff --git a/config/haproxy-devel/haproxy_files.php b/config/haproxy-devel/haproxy_files.php new file mode 100644 index 00000000..4946a7be --- /dev/null +++ b/config/haproxy-devel/haproxy_files.php @@ -0,0 +1,176 @@ +<?php +/* $Id: load_balancer_virtual_server.php,v 1.6.2.1 2006/01/02 23:46:24 sullrich Exp $ */ +/* + haproxy_pools.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2014 PiBa-NL + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +$shortcut_section = "haproxy"; +require_once("guiconfig.inc"); +require_once("haproxy.inc"); +require_once("pkg_haproxy_tabs.inc"); +require_once("haproxy_htmllist.inc"); + +$a_files = &$config['installedpackages']['haproxy']['files']['item']; +if (!is_array($a_files)) $a_files = array(); +$a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; +if (!is_array($a_pools)) $a_pools = array(); + + +$fields_files = array(); +$fields_files[0]['name']="name"; +$fields_files[0]['columnheader']="Name"; +$fields_files[0]['colwidth']="30%"; +$fields_files[0]['type']="textbox"; +$fields_files[0]['size']="20"; + +$fields_files[1]['name']="content"; +$fields_files[1]['columnheader']="content"; +$fields_files[1]['colwidth']="70%"; +$fields_files[1]['type']="textarea"; +$fields_files[1]['size']="70"; + +$fileslist = new HaproxyHtmlList("table_files", $fields_files); +$fileslist->keyfield = "name"; + +if ($_POST) { + $pconfig = $_POST; + + if ($_POST['apply']) { + $result = haproxy_check_and_run($savemsg, true); + if ($result) + unlink_if_exists($d_haproxyconfdirty_path); + } else { + $a_files = $fileslist->haproxy_htmllist_get_values($fields_files); + $filedupcheck = array(); + + foreach($a_files as $key => $file) { + $name = $file['name']; + if (!preg_match("/^[a-zA-Z][a-zA-Z0-9\.\-_]*$/", $file['name'])) + $input_errors[] = "The field 'Name' (".htmlspecialchars($file['name']).") contains invalid characters. Use only: a-zA-Z0-9.-_ and start with a letter"; + if (isset($filedupcheck[$name])) + $input_errors[] = "Duplicate names are not allowed: " . htmlspecialchars($name); + $filedupcheck[$name] = true; + } + + // replace references in backends to renamed 'files' + foreach($a_pools as &$backend) { + if (is_arrayset($backend,'errorfiles','item')) + foreach($backend['errorfiles']['item'] as &$errorfile) { + $found = false; + foreach($a_files as $key => $file) { + if ($errorfile['errorfile'] == $key) { + $errorfile['errorfile'] = $file['name']; + $found = true; + } + } + if (!$found) + $input_errors[] = "Errorfile marked for deletion: " . $errorfile['errorfile'] . " which is used in backend " . $backend['name']; + } + } + if (!$input_errors) { + // save config when no errors found + touch($d_haproxyconfdirty_path); + write_config($changedesc); + header("Location: haproxy_files.php"); + exit; + } + } +} + +$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); + +$pgtitle = "Services: HAProxy: Files"; +include("head.inc"); + +?> +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> +<?php include("fbegin.inc"); ?> +<form action="haproxy_files.php" method="post"> +<?php if ($input_errors) print_input_errors($input_errors); ?> +<?php if ($savemsg) print_info_box($savemsg); ?> +<?php if (file_exists($d_haproxyconfdirty_path)): ?> +<?php print_info_box_np("The haproxy configuration has been changed.<br/>You must apply the changes in order for them to take effect.");?><br/> +<?php endif; ?> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr><td class="tabnavtbl"> + <?php + haproxy_display_top_tabs_active($haproxy_tab_array['haproxy'], "files"); + ?> + </td></tr> + <tr> + <td> + <div id="mainarea"> + <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td> + Files can be used for errorfiles, that can return custom error pages in + case haproxy reports a error (like no available backend). The content needs + to be less than the buffer size which is typically 8kb. + There are 2 possible variables to use inside the template: + Put these variables in the content of the errorfile templates and they will be replaced by the actual errorcode / message. (include the curly braces around the text)<br/> + <b>{errorcode}</b> this represents the errorcode<br/> + <b>{errormsg}</b> this represents the human readable error<br/> + </td> + </tr> + <tr> + <td> + + </td> + </tr> + <tr> + <td> + <? + $counter=0; + $fileslist->Draw($a_files); + ?> + </td> + </tr> + <tr> + <td> + + </td> + </tr> + <tr> + <td width="78%"> + <input name="Submit" type="submit" class="formbtn" value="Save" onClick="enable_change(true)" /> + </td> + </tr> + </table> + </div> + </table> + </form> +<script type="text/javascript"> + totalrows = <?php echo $counter; ?>; +<? + phparray_to_javascriptarray($fields_files,"fields_files",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); +?> +</script> + +<?php +haproxy_htmllist_js(); +include("fend.inc"); ?> +</body> +</html> diff --git a/config/haproxy-devel/haproxy_htmllist.inc b/config/haproxy-devel/haproxy_htmllist.inc index 404e9fab..f873028e 100644 --- a/config/haproxy-devel/haproxy_htmllist.inc +++ b/config/haproxy-devel/haproxy_htmllist.inc @@ -34,193 +34,267 @@ require_once("config.inc"); require_once("haproxy_utils.inc"); -function haproxy_htmllist_get_values($html_list){ - $values = array(); - for($x=0; $x<99; $x++) { - $value = array(); - $add_item = false; - foreach($html_list as $item){ - $itemname = $item['name']; - $value[$itemname] = $_POST[$itemname.$x]; - $add_item |= isset($_POST[$itemname.$x]); +class HaproxyHtmlList +{ + /* + javascript 'events': + <tableId>_row_added(tableId, rowNr) + <tableId>_field_changed(tableId, rowNr, fieldId, field) + */ + + private $tablename = ""; + private $fields = array(); + public $editmode = false; + public $fields_details = null; + public $keyfield = ""; + + public function HaproxyHtmlList($tablename, $fields){ + $this->tablename = $tablename; + $this->fields = $fields; + } + + public function Draw($data){ + $this->haproxy_htmllist($data, $this->fields, $this->editmode, $this->fields_details); + } + + function haproxy_htmllist_get_values(){ + $values = array(); + for($x=0; $x<99; $x++) { + $value = array(); + $add_item = false; + foreach($this->fields as $item){ + $itemname = $item['name']; + $value[$itemname] = $_POST[$itemname.$x]; + if ($item['type'] == 'textarea') + $value[$itemname] = base64_encode($value[$itemname]); + $add_item |= isset($_POST[$itemname.$x]); + } + if ($add_item) { + if ($this->keyfield != "") { + if (isset($_POST[$this->tablename."_key".$x])) + $key = $_POST[$this->tablename."_key".$x]; + else + $key = $_POST[$this->keyfield.$x]; + + } else + $key = ""; + + if (isset($values[$key])) + $values[] = $value; + else + $values[$key] = $value; + } } - if ($add_item) - $values[] = $value; + return $values; } - return $values; -} -function haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemnamenr = "") { - $itemtype = $item['type']; - if ($editable) { + private function haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemname, $counter) { + $itemnamenr = $itemname . $counter; $itemtype = $item['type']; - if ($itemtype == "select"){ - echo_html_select($itemnamenr, $item['items'], $itemvalue,"","updatevisibility();", "width:{$item['size']}"); - } else - if ($itemtype == "checkbox"){ - $checked = $itemvalue=='yes' ? " checked" : ""; - echo "<input name='$itemnamenr' id='$itemnamenr' type='checkbox'$checked value='yes' size='{$item['size']}' />"; - } else - echo "<input name='$itemnamenr' id='$itemnamenr' type='text' value='{$itemvalue}' size='{$item['size']}' />"; - } else { - if ($itemtype == "select"){ - echo $item['items'][$itemvalue]['name']; - } else - if ($itemtype == "checkbox"){ - echo $itemvalue=='yes' ? gettext('yes') : gettext('no'); - } else - echo $itemvalue; + if ($editable) { + $itemtype = $item['type']; + if ($itemtype == "select"){ + echo_html_select($itemnamenr, $item['items'], $itemvalue,"","html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);", "width:{$item['size']}"); + } else + if ($itemtype == "checkbox"){ + $checked = $itemvalue=='yes' ? " checked" : ""; + echo "<input onclick='html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);' name='$itemnamenr' id='$itemnamenr' type='checkbox'$checked value='yes' size='{$item['size']}' />"; + } else + if ($itemtype == "textarea"){ + echo "<textarea name='$itemnamenr' id='$itemnamenr' type='text' cols='{$item['size']}' rows='10'>"; + echo htmlspecialchars(base64_decode($itemvalue)); + echo "</textarea>"; + } else + echo "<input name='$itemnamenr' id='$itemnamenr' type='text' value='{$itemvalue}' size='{$item['size']}' />"; + } else { + if ($itemtype == "select"){ + echo $item['items'][$itemvalue]['name']; + } else + if ($itemtype == "checkbox"){ + echo $itemvalue=='yes' ? gettext('yes') : gettext('no'); + } else + if ($itemtype == "textarea"){ + echo htmlspecialchars(base64_decode($itemvalue)); + } else + echo htmlspecialchars($itemvalue); + } } -} -function haproxy_htmllist($tablename,$rowvalues,$items,$editstate=false,$itemdetails=null){ - global $g, $counter; - echo "<table class='' width='100%' cellpadding='0' cellspacing='0' id='$tablename'> - <tr>"; - foreach($items as $item){ - echo "<td width='{$item['colwidth']}' class='listhdrr'>{$item['columnheader']}</td>"; - } - echo "<td width='5%' class=''></td> - </tr>"; - if (is_array($rowvalues)){ - foreach($rowvalues as $value){ - if (!$editstate) { - echo "<tr id='tr_view_$counter' ondblclick='editRow($counter); return false;' >"; - $leftitem = true; - foreach($items as $item) { - $tdclass = $leftitem ? "vtable listlr" : "vtable listr"; - echo "<td class='$tdclass'>"; + function haproxy_htmllist($rowvalues,$items,$editstate=false,$itemdetails=null){ + $tablename = $this->tablename; + global $g, $counter; + echo "<table class='' width='100%' cellpadding='0' cellspacing='0' id='$tablename'> + <tr>"; + foreach($items as $item){ + echo "<td width='{$item['colwidth']}' class='listhdrr'>{$item['columnheader']}</td>"; + } + echo "<td width='5%' class=''></td> + </tr>"; + if (is_array($rowvalues)){ + foreach($rowvalues as $keyid => $value){ + if ($this->keyfield != "") { + if (preg_match("/[^0-9]/", $keyid)) + $itemvalue = $keyid; + else + $itemvalue = $value[$this->keyfield]; + $key = "<input name='{$tablename}_key{$counter}' id='{$tablename}_key{$counter}' type='hidden' value='{$itemvalue}'>"; + } else + $key = ""; + + if (!$editstate) { + echo "<tr id='tr_view_$counter' ondblclick='editRow($counter); return false;' >"; + $leftitem = true; + foreach($items as $item) { + $tdclass = $leftitem ? "vtable listlr" : "vtable listr"; + echo "<td class='$tdclass'>"; + $itemname = $item['name']; + $itemvalue = $value[$itemname]; + if (isset($item['customdrawcell'])) { + $item['customdrawcell']($item, $itemvalue, false); + } else + $this->haproxy_htmllist_drawcell($item, $itemvalue, false, $itemname, $counter); + echo "</td>"; + $leftitem = false; + + } + echo " + <td class='list'> + <table border='0' cellspacing='0' cellpadding='1'><tr> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_e.gif' title='edit entry' width='17' height='17' border='0' onclick='editRow($counter); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow($counter, \"$tablename\"); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' /> + </td></tr></table> + </td>"; + echo "</tr>"; + } + $displaystyle = $editstate ? "" : "display: none;"; + echo "<tr id='tr_edit_$counter' style='$displaystyle'>"; + foreach($items as $item){ $itemname = $item['name']; - $itemvalue = $value[$itemname]; + $itemvalue = $value[$itemname]; + echo "<td class='vtable'>".$key; if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, false); + $item['customdrawcell']($item, $itemvalue, true, $item['name'].$counter); } else - haproxy_htmllist_drawcell($item, $itemvalue, false); + $this->haproxy_htmllist_drawcell($item, $itemvalue, true, $itemname, $counter); echo "</td>"; - $leftitem = false; + $key = ""; } echo " <td class='list'> <table border='0' cellspacing='0' cellpadding='1'><tr> <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_e.gif' title='edit entry' width='17' height='17' border='0' onclick='editRow($counter); return false;' /> - </td> - <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow($counter, \"$tablename\"); return false;' /> + <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='removeRow(this); return false;' /> </td> <td valign='middle'> <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' /> </td></tr></table> </td>"; echo "</tr>"; - } - $displaystyle = $editstate ? "" : "display: none;"; - echo "<tr id='tr_edit_$counter' style='$displaystyle'>"; - foreach($items as $item){ - $itemname = $item['name']; - $itemvalue = $value[$itemname]; - $itemnamenr = $itemname . $counter; - echo "<td class='vtable'>"; - if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, true, $itemnamenr); - } else - haproxy_htmllist_drawcell($item, $itemvalue, true, $itemnamenr); - echo "</td>"; - } - echo " - <td class='list'> - <table border='0' cellspacing='0' cellpadding='1'><tr> - <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='removeRow(this); return false;' /> - </td> - <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' /> - </td></tr></table> - </td>"; - echo "</tr>"; - if (isset($itemdetails)) { - $colspan = count($items)-1; - echo "<tr id='tr_viewdetail_$counter'>"; - ?> - <td class='vtable listlr' style='border-bottom-width: medium;vertical-align:top;'> - <div style="position:relative;float:right;width:11px;height:11px;"> - <a onclick="htmltable_toggle_details('<?="htmltable_{$tablename}_{$counter}_details"?>')"> - <img id="htmltable_<?="{$tablename}_{$counter}"?>_details_off" alt="Expand advanced server settings" - src="tree/plus.gif" style="clip:rect(19px 13px 30px 2px); top:-19px;position:absolute;"/> - </a> - </div> - </td> - <? - echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>"; - $itemnr = 0; - echo "<div id='htmltable_{$tablename}_{$counter}_details_view'>"; - $itemcount = count($itemdetails); - foreach($itemdetails as $item) { - echo "<div style='float: left;padding-right: 2px;'>"; - $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr"; - echo $item['columnheader'] . ": "; - $itemname = $item['name']; - $itemvalue = $value[$itemname]; - if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, false); - } else - haproxy_htmllist_drawcell($item, $itemvalue, false); - $leftitem = false; - $itemnr++; - if ($itemcount != $itemnr) - echo ", "; + if (isset($itemdetails)) { + $colspan = count($items)-1; + echo "<tr id='tr_viewdetail_$counter'>"; + ?> + <td class='vtable listlr' style='border-bottom-width: medium;vertical-align:top;'> + <div style="position:relative;float:right;width:11px;height:11px;"> + <a onclick="htmltable_toggle_details('<?="htmltable_{$tablename}_{$counter}_details"?>')"> + <img id="htmltable_<?="{$tablename}_{$counter}"?>_details_off" alt="Expand advanced server settings" + src="tree/plus.gif" style="clip:rect(19px 13px 30px 2px); top:-19px;position:absolute;"/> + </a> + </div> + </td> + <? + echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>"; + $itemnr = 0; + echo "<div id='htmltable_{$tablename}_{$counter}_details_view'>"; + $itemcount = count($itemdetails); + foreach($itemdetails as $item) { + echo "<div style='float: left;padding-right: 2px;'>"; + $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr"; + echo $item['columnheader'] . ": "; + $itemname = $item['name']; + $itemvalue = $value[$itemname]; + if (isset($item['customdrawcell'])) { + $item['customdrawcell']($item, $itemvalue, false); + } else + $this->haproxy_htmllist_drawcell($item, $itemvalue, false, $itemname, $counter); + $leftitem = false; + $itemnr++; + if ($itemcount != $itemnr) + echo ", "; + echo "</div>"; + } + echo "</div>"; + echo "<div id='htmltable_{$tablename}_{$counter}_details_edit' style='display:none;'>"; + echo "<table class='tabcont' style='border-collapse:collapse' border='1' cellspacing='0' >"; + $leftitem = true; + foreach($itemdetails as $item) { + echo "<tr id='tr_edititemdetails_$counter' ondblclick='editRow($counter); return false;'>"; + $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr"; + echo "<td style='border-right:0' class='$tdclass'>"; + echo "{$item['columnheader']}: "; + echo "</td>"; + echo "<td style='border-left:0' class='$tdclass'>"; + $itemname = $item['name']; + $itemvalue = $value[$itemname]; + echo "{$item['description']}<br/>"; + if (isset($item['customdrawcell'])) { + $item['customdrawcell']($item, $itemvalue, true, $itemname . $counter); + } else + $this->haproxy_htmllist_drawcell($item, $itemvalue, true, $itemname, $counter); + echo "</td>"; + $leftitem = false; + echo "</tr>"; + } + echo "</table>"; echo "</div>"; - } - echo "</div>"; - echo "<div id='htmltable_{$tablename}_{$counter}_details_edit' style='display:none;'>"; - echo "<table class='tabcont' style='border-collapse:collapse' border='1' cellspacing='0' >"; - $leftitem = true; - foreach($itemdetails as $item) { - echo "<tr id='tr_edititemdetails_$counter' ondblclick='editRow($counter); return false;'>"; - $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr"; - echo "<td style='border-right:0' class='$tdclass'>"; - echo "{$item['columnheader']}: "; echo "</td>"; - echo "<td style='border-left:0' class='$tdclass'>"; - $itemname = $item['name']; - $itemvalue = $value[$itemname]; - $itemnamenr = $itemname . $counter; - echo "{$item['description']}<br/>"; - if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, true, $itemnamenr); - } else - haproxy_htmllist_drawcell($item, $itemvalue, true, $itemnamenr); + echo "</tr>"; + } + if (isset($itemdetails)) { + $colspan = count($items)-1; + echo "<tr id='htmltable_{$tablename}_{$counter}_details' style='$displaystyle' >"; + echo "<td class='vtable listlr' style='border-bottom-width: medium;'> </td>"; + echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>"; echo "</td>"; - $leftitem = false; - echo "</tr>"; + echo "</tr>"; } - echo "</table>"; - echo "</div>"; - echo "</td>"; - echo "</tr>"; - } - if (isset($itemdetails)) { - $colspan = count($items)-1; - echo "<tr id='htmltable_{$tablename}_{$counter}_details' style='$displaystyle' >"; - echo "<td class='vtable listlr' style='border-bottom-width: medium;'> </td>"; - echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>"; - echo "</td>"; - echo "</tr>"; - } - - - - $counter++; + + $counter++; + } } + echo "</table> + <a onclick='javascript:addRowTo(\"$tablename\"); return false;' href='#'> + <img border='0' src='/themes/{$g['theme']}/images/icons/icon_plus.gif' alt='' title='add another entry' /> + </a>"; } - echo "</table> - <a onclick='javascript:addRowTo(\"$tablename\"); return false;' href='#'> - <img border='0' src='/themes/{$g['theme']}/images/icons/icon_plus.gif' alt='' title='add another entry' /> - </a>"; +} + +function haproxy_htmllist($tablename,$rowvalues,$items,$editstate=false,$itemdetails=null){ + $list = new HaproxyHtmlList($tablename, $items); + $list->haproxy_htmllist($rowvalues, $items, $editstate, $itemdetails); +} + +function haproxy_htmllist_get_values($html_list){ + $list = new HaproxyHtmlList("-", $html_list); + return $list->haproxy_htmllist_get_values(); } function haproxy_htmllist_js(){ -?><script type="text/javascript"> +?><script type="text/javascript"> + function html_listitem_change(tableId, fieldId, rowNr, field) { + javascript_event = tableId + "_listitem_change"; + var fn = window[javascript_event]; + if (typeof fn === 'function'){ + fn(tableId, fieldId, rowNr, field); + } + } + function htmllist_get_select_items(prefix,tableId) { var items; var i = tableId.lastIndexOf('_'); @@ -248,14 +322,21 @@ function haproxy_htmllist_js(){ td.innerHTML="<input size='" + items[i]['size'] + "' name='" + items[i]['name'] + totalrows + "' id='" + items[i]['name'] + totalrows + "'><\/input> "; + } else if(items[i]['type'] == 'textarea') { + td.innerHTML="<textarea cols='" + items[i]['size'] + "' rows='30' name='" + items[i]['name'] + totalrows + + "' id='" + items[i]['name'] + totalrows + + "'><\/textarea> "; } else if(items[i]['type'] == 'select') { seltext = htmllist_get_select_options(tableId, items[i]['name']); td.innerHTML="<select style='width:" + items[i]['size'] + "' name='" + items[i]['name'] + totalrows + - "' id='" + items[i]['name'] + totalrows + - "'>" + seltext + "<\/select> "; + "' id='" + items[i]['name'] + totalrows + "' "+ + "onchange='html_listitem_change(\""+tableId+"\",\""+items[i]['name']+"\",\""+totalrows+"\",this);' " + + ">" + seltext + "<\/select> "; } else { - td.innerHTML="<input type='checkbox' name='" + items[i]['name'] + totalrows + - "' id='" + items[i]['name'] + totalrows + "' value='yes'><\/input> "; + td.innerHTML="<input type='checkbox' name='" + items[i]['name'] + totalrows +"'"+ + "id='" + items[i]['name'] + totalrows + "' "+ + "onclick='html_listitem_change(\""+tableId+"\",\""+items[i]['name']+"\",\""+totalrows+"\",this);' " + + "value='yes'><\/input> "; } tr.appendChild(td); } @@ -290,6 +371,12 @@ function haproxy_htmllist_js(){ td.appendChild(btable); tr.appendChild(td); tbody.appendChild(tr); + + javascript_row_added = tableId + "_row_added"; + var fn = window[javascript_row_added]; + if (typeof fn === 'function'){ + fn(tableId, totalrows); + } }); })(); function dupRow(rowId, tableId) { @@ -316,6 +403,11 @@ function haproxy_htmllist_js(){ else newEl.value = dupEl.value; } + javascript_row_added = tableId + "_row_added"; + var fn = window[javascript_row_added]; + if (typeof fn === 'function'){ + fn(tableId, totalrows); + } } function editRow(num) { var trview = document.getElementById('tr_view_' + num); @@ -327,9 +419,12 @@ function haproxy_htmllist_js(){ var view = document.getElementById("tr_view_" + rowId); var viewdetail = document.getElementById("tr_viewdetail_" + rowId); var edit = document.getElementById("tr_edit_" + rowId); - view.parentNode.removeChild(view); - viewdetail.parentNode.removeChild(viewdetail); - edit.parentNode.removeChild(edit); + if (view) + view.parentNode.removeChild(view); + if (viewdetail) + viewdetail.parentNode.removeChild(viewdetail); + if (edit) + edit.parentNode.removeChild(edit); } function removeRow(el) { var cel; diff --git a/config/haproxy-devel/haproxy_listeners.php b/config/haproxy-devel/haproxy_listeners.php index 1deabdbb..8105345e 100644 --- a/config/haproxy-devel/haproxy_listeners.php +++ b/config/haproxy-devel/haproxy_listeners.php @@ -124,10 +124,11 @@ include("head.inc"); $a_frontend_grouped = array(); foreach($a_frontend as &$frontend2) { $mainfrontend = get_primaryfrontend($frontend2); + $mainname = $mainfrontend['name']; $ipport = get_frontend_ipport($frontend2, true); $frontend2['ipport'] = $ipport; $frontend2['type'] = $mainfrontend['type']; - $a_frontend_grouped[$ipport][] = $frontend2; + $a_frontend_grouped[$mainname][] = $frontend2; } ksort($a_frontend_grouped); @@ -142,6 +143,7 @@ include("head.inc"); if ((count($a_frontend) > 1 || $last_frontend_shared) && !$first) { ?> <tr class="<?=$textgray?>"><td colspan="7"> </td></tr> <? } + $first = false; $last_frontend_shared = count($a_frontend) > 1; foreach ($a_frontend as $frontend) { $frontendname = $frontend['name']; @@ -161,7 +163,7 @@ include("head.inc"); if ($isaclset) echo "<img src=\"$img_acl\" title=\"" . gettext("acl's used") . ": {$isaclset}\" border=\"0\" />"; - if (strtolower($frontend['type']) == "http" && $frontend['ssloffload']) { + if (get_frontend_uses_ssl($frontend)) { $cert = lookup_cert($frontend['ssloffloadcert']); $descr = htmlspecialchars($cert['descr']); if (is_array($frontend['ha_certificates']) && is_array($frontend['ha_certificates']['item'])) { @@ -205,10 +207,35 @@ include("head.inc"); <?=$frontend['desc'];?> </td> <td class="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> - <?=str_replace(" "," ",$frontend['ipport']);?> + <? + $first = true; + foreach($frontend['ipport'] as $addr) { + if (!$first) + print "<br/>"; + print "<div style='white-space:nowrap;'>"; + print "{$addr['addr']}:{$addr['port']}"; + if ($addr['ssl'] == 'yes') { + echo '<img src="'.$img_cert.'" title="SSL offloading" alt="SSL" border="0" height="11" width="11" />'; + } + print "</div"; + $first = false; + } + ?> </td> <td class="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> - <?=$frontend['type']?> + <? + if ($frontend['type'] == 'http') { + $mainfrontend = get_primaryfrontend($frontend); + $sslused = get_frontend_uses_ssl($mainfrontend); + $httpused = !get_frontend_uses_ssl_only($frontend); + if ($httpused) + echo "http"; + if ($sslused) { + echo ($httpused ? "/" : "") . "https"; + } + } else + echo $a_frontendmode[$frontend['type']]['shortname']; + ?> </td> <td class="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> <div title='<?=$backend_serverpool_hint;?>'> diff --git a/config/haproxy-devel/haproxy_listeners_edit.php b/config/haproxy-devel/haproxy_listeners_edit.php index d243ffb1..a818fcfb 100644 --- a/config/haproxy-devel/haproxy_listeners_edit.php +++ b/config/haproxy-devel/haproxy_listeners_edit.php @@ -63,6 +63,8 @@ if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { $a_backend = &$config['installedpackages']['haproxy']['ha_backends']['item']; $a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; +if (!is_array($a_pools)) + $a_pools = array(); uasort($a_pools, haproxy_compareByName); global $simplefields; @@ -85,6 +87,10 @@ if (!is_numeric($id)) { //default value for new items. $pconfig['ssloffloadacl'] = "yes"; + $new_item = array(); + $new_item['extaddr'] = "wan_ipv4"; + $new_item['extaddr_port'] = "80"; + $pconfig['a_extaddr'][] = $new_item; } $servercerts = haproxy_get_certificates('server,user'); @@ -138,11 +144,44 @@ $fields_aclSelectionList[2]['colwidth']="35%"; $fields_aclSelectionList[2]['type']="textbox"; $fields_aclSelectionList[2]['size']="35"; +$interfaces = haproxy_get_bindable_interfaces(); +$interfaces_custom['custom']['name']="Use custom address:"; +$interfaces = $interfaces_custom + $interfaces; + +$fields_externalAddress=array(); +$fields_externalAddress[0]['name']="extaddr"; +$fields_externalAddress[0]['columnheader']="Listen address"; +$fields_externalAddress[0]['colwidth']="25%"; +$fields_externalAddress[0]['type']="select"; +$fields_externalAddress[0]['size']="200px"; +$fields_externalAddress[0]['items']=&$interfaces; +$fields_externalAddress[1]['name']="extaddr_custom"; +$fields_externalAddress[1]['columnheader']="Custom address"; +$fields_externalAddress[1]['colwidth']="25%"; +$fields_externalAddress[1]['type']="textbox"; +$fields_externalAddress[1]['size']="30"; +$fields_externalAddress[2]['name']="extaddr_port"; +$fields_externalAddress[2]['columnheader']="Port"; +$fields_externalAddress[2]['colwidth']="5%"; +$fields_externalAddress[2]['type']="textbox"; +$fields_externalAddress[2]['size']="5"; +$fields_externalAddress[3]['name']="extaddr_ssl"; +$fields_externalAddress[3]['columnheader']="SSL Offloading"; +$fields_externalAddress[3]['colwidth']="10%"; +$fields_externalAddress[3]['type']="checkbox"; +$fields_externalAddress[3]['size']="50px"; +$fields_externalAddress[4]['name']="extaddr_advanced"; +$fields_externalAddress[4]['columnheader']="Advanced"; +$fields_externalAddress[4]['colwidth']="20%"; +$fields_externalAddress[4]['type']="textbox"; +$fields_externalAddress[4]['size']="30"; + if (isset($id) && $a_backend[$id]) { $pconfig['a_acl']=&$a_backend[$id]['ha_acls']['item']; $pconfig['a_certificates']=&$a_backend[$id]['ha_certificates']['item']; $pconfig['clientcert_ca']=&$a_backend[$id]['clientcert_ca']['item']; $pconfig['clientcert_crl']=&$a_backend[$id]['clientcert_crl']['item']; + $pconfig['a_extaddr']=&$a_backend[$id]['a_extaddr']['item']; $pconfig['advanced'] = base64_decode($a_backend[$id]['advanced']); foreach($simplefields as $stat) $pconfig[$stat] = $a_backend[$id][$stat]; @@ -164,8 +203,8 @@ if ($_POST) { $pconfig = $_POST; if ($pconfig['secondary'] != "yes") { - $reqdfields = explode(" ", "name type port"); - $reqdfieldsn = explode(",", "Name,Type,Port"); + $reqdfields = explode(" ", "name type"); + $reqdfieldsn = explode(",", "Name,Type"); } else { $reqdfields = explode(" ", "name"); $reqdfieldsn = explode(",", "Name"); @@ -208,6 +247,10 @@ if ($_POST) { $a_acl = haproxy_htmllist_get_values($fields_aclSelectionList); $pconfig['a_acl'] = $a_acl; + $a_extaddr = haproxy_htmllist_get_values($fields_externalAddress); + $pconfig['a_extaddr'] = $a_extaddr; + + foreach($a_acl as $acl) { $acl_name = $acl['name']; $acl_value = $acl['value']; @@ -247,6 +290,7 @@ if ($_POST) { $backend['ha_certificates']['item'] = $a_certificates; $backend['clientcert_ca']['item'] = $a_clientcert_ca; $backend['clientcert_crl']['item'] = $a_clientcert_crl; + $backend['a_extaddr']['item'] = $a_extaddr; if (isset($id) && $a_backend[$id]) { $a_backend[$id] = $backend; @@ -275,7 +319,6 @@ include("head.inc"); if (!isset($_GET['dup'])) $excludefrontend = $pconfig['name']; $primaryfrontends = get_haproxy_frontends($excludefrontend); -$interfaces = haproxy_get_bindable_interfaces(); ?> <style type="text/css"> @@ -329,6 +372,9 @@ $interfaces = haproxy_get_bindable_interfaces(); if (tableId == 'table_clientcert_crl'){ seltext = "<?=haproxy_js_select_options($certs_crl);?>"; } + if (tableId == 'table_extaddr'){ + seltext = "<?=haproxy_js_select_options($interfaces);?>"; + } return seltext; } @@ -343,20 +389,26 @@ $interfaces = haproxy_get_bindable_interfaces(); } } } - function updatevisibility() { d = document; + ssl = false; ssloffload = d.getElementById("ssloffload"); + for (i = 0; i < 99; i++) { + customEdit = document.getElementById("extaddr_ssl"+i); + if (customEdit && customEdit.checked) + ssl = true; + } var type; var secondary = d.getElementById("secondary"); var primary_frontend = d.getElementById("primary_frontend"); - if ((secondary !== null) && (secondary.checked)) + if ((secondary !== null) && (secondary.checked)) { type = primaryfrontends[primary_frontend.value]['ref']['type']; - else + ssl = ssloffload.checked; + } else type = d.getElementById("type").value; - setCSSdisplay(".haproxy_ssloffloading_enabled", ssloffload.checked); + setCSSdisplay(".haproxy_ssloffloading_enabled", ssl); setCSSdisplay(".haproxy_mode_http", type == "http"); if (secondary !== null) { setCSSdisplay(".haproxy_primary", !secondary.checked); @@ -481,25 +533,45 @@ $interfaces = haproxy_get_bindable_interfaces(); <tr class="haproxy_primary"> <td width="22%" valign="top" class="vncellreq">External address</td> <td width="78%" class="vtable"> - <? - echo_html_select('extaddr', $interfaces, $pconfig['extaddr']); - ?> + <? + $counter=0; + $a_extaddr = $pconfig['a_extaddr']; + $htmllist_extadd = new HaproxyHtmlList("table_extaddr", $fields_externalAddress); + $htmllist_extadd->editmode = true; + $htmllist_extadd->Draw($a_extaddr); + ?> + <script type="text/javascript"> + function table_extaddr_row_added(tableid, rowid){ + new AutoSuggestControl(document.getElementById("extaddr_custom"+rowid), new StateSuggestions(address_array)); + new AutoSuggestControl(document.getElementById("extaddr_port"+rowid), new StateSuggestions(port_array)); + table_extaddr_listitem_change(tableid,"",rowid, null);//disables address when not set to custom. + } + + function table_extaddr_listitem_change(tableId, fieldId, rowNr, field) { + if (fieldId == "extaddr" || fieldId == "") { + field = field || document.getElementById("extaddr"+rowNr); + customEdit = document.getElementById("extaddr_custom"+rowNr); + customdisabled = field.value == "custom" ? 0 : 1; + customEdit.disabled = customdisabled; + } + if (fieldId == "extaddr_ssl") { + updatevisibility(); + } + } + + </script> <br /> <span class="vexpl"> If you want this rule to apply to another IP address than the IP address of the interface chosen above, select it here (you need to define <a href="firewall_virtual_ip.php">Virtual IP</a> addresses on the first). Also note that if you are trying to redirect connections on the LAN select the "any" option. + + In the port to listen to, if you want to specify multiple ports, separate them with a comma (,). EXAMPLE: 80,8000 + Or to listen on both 80 and 443 create 2 rows in the table. </span> </td> </tr> <tr class="haproxy_primary" align="left"> - <td width="22%" valign="top" class="vncellreq">External port</td> - <td width="78%" class="vtable" colspan="2"> - <input name="port" id="port" type="text" <?if(isset($pconfig['port'])) echo "value=\"{$pconfig['port']}\"";?> size="10" maxlength="500" /> - <div>The port to listen to. To specify multiple ports, separate with a comma (,). EXAMPLE: 80,8000</div> - </td> - </tr> - <tr class="haproxy_primary" align="left"> <td width="22%" valign="top" class="vncell">Max connections</td> <td width="78%" class="vtable" colspan="2"> <input name="max_connections" type="text" <?if(isset($pconfig['max_connections'])) echo "value=\"{$pconfig['max_connections']}\"";?> size="10" maxlength="10" /> @@ -526,8 +598,8 @@ $interfaces = haproxy_get_bindable_interfaces(); <td width="22%" valign="top" class="vncellreq">Type</td> <td width="78%" class="vtable" colspan="2"> <select name="type" id="type" onchange="updatevisibility();"> - <option value="http"<?php if($pconfig['type'] == "http") echo " SELECTED"; ?>>HTTP</option> - <option value="https"<?php if($pconfig['type'] == "https") echo " SELECTED"; ?>>HTTPS</option> + <option value="http"<?php if($pconfig['type'] == "http") echo " SELECTED"; ?>>HTTP / HTTPS(offloading)</option> + <option value="https"<?php if($pconfig['type'] == "https") echo " SELECTED"; ?>>SSL / HTTPS(TCP mode)</option> <option value="tcp"<?php if($pconfig['type'] == "tcp") echo " SELECTED"; ?>>TCP</option> <option value="health"<?php if($pconfig['type'] == "health") echo " SELECTED"; ?>>Health</option> </select><br/> @@ -541,7 +613,6 @@ $interfaces = haproxy_get_bindable_interfaces(); <td width="22%" valign="top" class="vncell">Access Control lists</td> <td width="78%" class="vtable" colspan="2" valign="top"> <? - $counter=0; $a_acl = $pconfig['a_acl']; haproxy_htmllist("tableA_acltable", $a_acl, $fields_aclSelectionList, true); ?> @@ -654,16 +725,19 @@ $interfaces = haproxy_get_bindable_interfaces(); <td colspan="2" valign="top" class="listtopic">SSL Offloading</td> </tr> <tr align="left"> - <td width="22%" valign="top" class="vncell">Use Offloading</td> <td width="78%" class="vtable" colspan="2"> - <input id="ssloffload" name="ssloffload" type="checkbox" value="yes" <?php if ($pconfig['ssloffload']=='yes') echo "checked";?> onclick="updatevisibility();" /><strong>Use Offloading</strong> - <br/> SSL Offloading will reduce web servers load by maintaining and encrypting connection with users on internet while sending and retrieving data without encrytion to internal servers. Also more ACL rules and http logging may be configured when this option is used. Certificates can be imported into the <a href="/system_camanager.php" target="_blank">pfSense "Certificate Authority Manager"</a> Please be aware this possibly will not work with all web applications. Some applications will require setting the SSL checkbox on the backend server configurations so the connection to the webserver will also be a encrypted connection, in that case there will be a slight overall performance loss. </td> </tr> + <tr align="left" class="haproxy_secondary" > + <td width="22%" valign="top" class="vncell">Use Offloading</td> + <td width="78%" class="vtable" colspan="2"> + <input id="ssloffload" name="ssloffload" type="checkbox" value="yes" <?php if ($pconfig['ssloffload']=='yes') echo "checked";?> onclick="updatevisibility();" /><strong>Use Offloading</strong> + </td> + </tr> <tr class="haproxy_ssloffloading_enabled" align="left"> <td width="22%" valign="top" class="vncell">Certificate</td> <td width="78%" class="vtable" colspan="2"> @@ -700,7 +774,8 @@ $interfaces = haproxy_get_bindable_interfaces(); </td> </tr> <tr class="haproxy_ssloffloading_enabled haproxy_primary"> - <td class="vncell" colspan="2"><b>Client certificate verification options, leave this empty if you do want to ask for a client certificate</b></td> + <td class="vncell" colspan="2"><b>Client certificate verification options, leave this empty if you do not want to ask for a client certificate</b><br/> + The users that visit this site will need to load the client cert signed by the ca's listed below imported into their browser.</td> </tr> <tr class="haproxy_ssloffloading_enabled haproxy_primary"> <td width="22%" valign="top" class="vncell">Client verification CA certificates</td> @@ -754,14 +829,24 @@ $interfaces = haproxy_get_bindable_interfaces(); phparray_to_javascriptarray($fields_caCertificates,"fields_ca",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); phparray_to_javascriptarray($fields_crlCertificates,"fields_crl",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); phparray_to_javascriptarray($fields_aclSelectionList,"fields_acltable",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + phparray_to_javascriptarray($fields_externalAddress,"fields_extaddr",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); ?> </script> <script type="text/javascript"> totalrows = <?php echo $counter; ?>; - updatevisibility(); - var customarray = <?= json_encode(get_alias_list(array("port", "url_ports", "urltable_ports"))) ?>; - var oTextbox1 = new AutoSuggestControl(document.getElementById("port"), new StateSuggestions(customarray)); + var port_array = <?= json_encode(get_alias_list(array("port", "url_ports", "urltable_ports"))) ?>; + var address_array = <?= json_encode(get_alias_list(array("host", "network", "openvpn", "urltable"))) ?>; + + + for(i=0;i < <?=count($a_extaddr)?>;i++){ + new AutoSuggestControl(document.getElementById('extaddr_custom'+i), new StateSuggestions(address_array)); + new AutoSuggestControl(document.getElementById('extaddr_port'+i), new StateSuggestions(port_array)); + // Initially set fields disabled where needed + table_extaddr_listitem_change('table_extaddr','',i,null); + } + + updatevisibility(); </script> <?php haproxy_htmllist_js(); diff --git a/config/haproxy-devel/haproxy_pool_edit.php b/config/haproxy-devel/haproxy_pool_edit.php index 30079847..5c7f66b9 100644 --- a/config/haproxy-devel/haproxy_pool_edit.php +++ b/config/haproxy-devel/haproxy_pool_edit.php @@ -42,6 +42,8 @@ if (!is_array($config['installedpackages']['haproxy']['ha_pools']['item'])) { $a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; +$a_files = haproxy_get_fileslist(); + if (isset($_POST['id'])) $id = $_POST['id']; else @@ -172,6 +174,19 @@ $fields_servers_details[7]['colwidth']="15%"; $fields_servers_details[7]['type']="textbox"; $fields_servers_details[7]['size']="80"; +$fields_errorfile = array(); +$fields_errorfile[0]['name']="errorcode"; +$fields_errorfile[0]['columnheader']="errorcode(s)"; +$fields_errorfile[0]['colwidth']="15%"; +$fields_errorfile[0]['type']="textbox"; +$fields_errorfile[0]['size']="70px"; +$fields_errorfile[1]['name']="errorfile"; +$fields_errorfile[1]['columnheader']="Error Page"; +$fields_errorfile[1]['colwidth']="30%"; +$fields_errorfile[1]['type']="select"; +$fields_errorfile[1]['size']="170px"; +$fields_errorfile[1]['items']=&$a_files; + if (isset($id) && $a_pools[$id]) { $pconfig['advanced'] = base64_decode($a_pools[$id]['advanced']); $pconfig['advanced_backend'] = base64_decode($a_pools[$id]['advanced_backend']); @@ -179,6 +194,9 @@ if (isset($id) && $a_pools[$id]) { foreach($simplefields as $stat) $pconfig[$stat] = $a_pools[$id][$stat]; + + $a_errorfiles = &$a_pools[$id]['errorfiles']['item']; + if (!is_array($a_errorfiles)) $a_errorfiles = array(); } if (isset($_GET['dup'])) @@ -269,6 +287,8 @@ if ($_POST) { $input_errors[] = "The field 'Port' value is not a number."; } + $a_errorfiles = haproxy_htmllist_get_values($fields_errorfile); + if ($_POST['strict_transport_security'] !== "" && !is_numeric($_POST['strict_transport_security'])) $input_errors[] = "The field 'Strict-Transport-Security' is not empty or a number."; @@ -356,6 +376,9 @@ foreach($simplefields as $field){ if (fieldname == 'forwardto') return "<?=haproxy_js_select_options($primaryfrontends);?>"; else + if (fieldname == 'errorfile') + return "<?=haproxy_js_select_options($a_files);?>"; + else return "<?=haproxy_js_select_options($a_servermodes);?>"; } @@ -920,6 +943,21 @@ set by the 'retries' parameter.</div> </tr> <tr><td> </td></tr> <tr> + <td colspan="2" valign="top" class="listtopic">Error files</td> + </tr> + <tr class="" align="left" id='errorfiles'> + <td colspan="2" valign="top" class="vtable"> + Use these to replace the error pages that haproxy can generate by custom pages created on the files tab. + For example haproxy will generate a 503 error page when no backend is available, you can replace that page here. + <br/> + <br/> + <? + haproxy_htmllist("table_errorfile", $a_errorfiles, $fields_errorfile); + ?> + </td> + </tr> + <tr><td> </td></tr> + <tr> <td colspan="2" valign="top" class="listtopic">Advanced</td> </tr> <tr class="" align="left" id='Strict-Transport-Security'> @@ -961,9 +999,11 @@ set by the 'retries' parameter.</div> <? phparray_to_javascriptarray($fields_servers,"fields_servers",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); phparray_to_javascriptarray($fields_servers_details,"fields_details_servers",Array('/*','/*/name','/*/type')); + phparray_to_javascriptarray($fields_errorfile,"fields_errorfile",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); phparray_to_javascriptarray($a_checktypes,"checktypes",Array('/*','/*/name','/*/descr')); phparray_to_javascriptarray($a_cookiemode,"cookiemode",Array('/*','/*/name','/*/descr')); phparray_to_javascriptarray($a_sticky_type,"sticky_type",Array('/*','/*/descr','/*/cookiedescr')); + phparray_to_javascriptarray($a_files,"a_files",Array('/*','/*/name','/*/descr')); ?> browser_InnerText_support = (document.getElementsByTagName("body")[0].innerText != undefined) ? true : false; diff --git a/config/haproxy-devel/pkg_haproxy_tabs.inc b/config/haproxy-devel/pkg_haproxy_tabs.inc index 8cb280f8..f49d2b67 100644 --- a/config/haproxy-devel/pkg_haproxy_tabs.inc +++ b/config/haproxy-devel/pkg_haproxy_tabs.inc @@ -12,7 +12,9 @@ $haproxy_tab_array['haproxy'] = array(); $haproxy_tab_array['haproxy']['settings'] = Array(name => "Settings", url => "haproxy_global.php"); $haproxy_tab_array['haproxy']['frontend'] = Array(name => "Frontend", url => "haproxy_listeners.php"); $haproxy_tab_array['haproxy']['backend'] = Array(name => "Backend", url => "haproxy_pools.php"); +$haproxy_tab_array['haproxy']['files'] = Array(name => "Files", url => "haproxy_files.php"); $haproxy_tab_array['haproxy']['stats'] = Array(name => "Stats", url => "haproxy_stats.php"); +$haproxy_tab_array['haproxy']['statsfs'] = Array(name => "Stats FS", url => "haproxy_stats.php?haproxystats=1"); function haproxy_display_top_tabs_active($top_tabs, $activetab) { $tab_array = array(); |