. * 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. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgment: * "This product includes software developed by the pfSense Project * for use in the pfSense® software distribution. (http://www.pfsense.org/). * * 4. The names "pfSense" and "pfSense Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * coreteam@pfsense.org. * * 5. Products derived from this software may not be called "pfSense" * nor may "pfSense" appear in their names without prior written * permission of the Electric Sheep Fencing, LLC. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * * "This product includes software developed by the pfSense Project * for use in the pfSense software distribution (http://www.pfsense.org/). * * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY * EXPRESSED 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 pfSense PROJECT OR * ITS CONTRIBUTORS 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. */ ##|+PRIV ##|*IDENT=page-services-dhcpserver ##|*NAME=Services: DHCP Server ##|*DESCR=Allow access to the 'Services: DHCP Server' page. ##|*MATCH=services_dhcp.php* ##|-PRIV require_once("guiconfig.inc"); require_once("filter.inc"); require_once('rrd.inc'); require_once("shaper.inc"); if (!$g['services_dhcp_server_enable']) { header("Location: /"); exit; } $if = $_GET['if']; if (!empty($_POST['if'])) { $if = $_POST['if']; } /* if OLSRD is enabled, allow WAN to house DHCP. */ if ($config['installedpackages']['olsrd']) { foreach ($config['installedpackages']['olsrd']['config'] as $olsrd) { if ($olsrd['enable']) { $is_olsr_enabled = true; break; } } } $iflist = get_configured_interface_with_descr(); /* set the starting interface */ if (!$if || !isset($iflist[$if])) { $found_starting_if = false; // First look for an interface with DHCP already enabled. foreach ($iflist as $ifent => $ifname) { $oc = $config['interfaces'][$ifent]; if (is_array($config['dhcpd'][$ifent]) && isset($config['dhcpd'][$ifent]['enable']) && (is_ipaddrv4($oc['ipaddr']))) { $if = $ifent; $found_starting_if = true; break; } } // If there is no DHCP-enabled interface and LAN is a candidate, then choose LAN. if (!$found_starting_if && isset($iflist['lan']) && is_ipaddrv4($config['interfaces']['lan']['ipaddr'])) { $if = 'lan'; $found_starting_if = true; } // At the last select whatever can be found. if (!$found_starting_if) { foreach ($iflist as $ifent => $ifname) { $oc = $config['interfaces'][$ifent]; if ((is_array($config['dhcpd'][$ifent]) && !isset($config['dhcpd'][$ifent]['enable']) && (!is_ipaddrv4($oc['ipaddr']))) || (!is_array($config['dhcpd'][$ifent]) && (!is_ipaddrv4($oc['ipaddr'])))) { continue; } $if = $ifent; break; } } } $act = $_GET['act']; if (!empty($_POST['act'])) { $act = $_POST['act']; } $a_pools = array(); if (is_array($config['dhcpd'][$if])) { $pool = $_GET['pool']; if (is_numeric($_POST['pool'])) { $pool = $_POST['pool']; } // If we have a pool but no interface name, that's not valid. Redirect away. if (is_numeric($pool) && empty($if)) { header("Location: services_dhcp.php"); exit; } if (!is_array($config['dhcpd'][$if]['pool'])) { $config['dhcpd'][$if]['pool'] = array(); } $a_pools = &$config['dhcpd'][$if]['pool']; if (is_numeric($pool) && $a_pools[$pool]) { $dhcpdconf = &$a_pools[$pool]; } elseif ($act == "newpool") { $dhcpdconf = array(); } else { $dhcpdconf = &$config['dhcpd'][$if]; } if (!is_array($config['dhcpd'][$if]['staticmap'])) { $dhcpdconf['staticmap'] = array(); } $a_maps = &$config['dhcpd'][$if]['staticmap']; } if (is_array($dhcpdconf)) { // Global Options if (!is_numeric($pool) && !($act == "newpool")) { $pconfig['enable'] = isset($dhcpdconf['enable']); $pconfig['staticarp'] = isset($dhcpdconf['staticarp']); // No reason to specify this per-pool, per the dhcpd.conf man page it needs to be in every // pool and should be specified in every pool both nodes share, so we'll treat it as global $pconfig['failover_peerip'] = $dhcpdconf['failover_peerip']; // dhcpleaseinlocaltime is global to all interfaces. So if it is selected on any interface, // then show it true/checked. foreach ($config['dhcpd'] as $dhcpdifitem) { $dhcpleaseinlocaltime = $dhcpdifitem['dhcpleaseinlocaltime']; if ($dhcpleaseinlocaltime) { break; } } $pconfig['dhcpleaseinlocaltime'] = $dhcpleaseinlocaltime; } else { // Options that exist only in pools $pconfig['descr'] = $dhcpdconf['descr']; } // Options that can be global or per-pool. if (is_array($dhcpdconf['range'])) { $pconfig['range_from'] = $dhcpdconf['range']['from']; $pconfig['range_to'] = $dhcpdconf['range']['to']; } $pconfig['deftime'] = $dhcpdconf['defaultleasetime']; $pconfig['maxtime'] = $dhcpdconf['maxleasetime']; $pconfig['gateway'] = $dhcpdconf['gateway']; $pconfig['domain'] = $dhcpdconf['domain']; $pconfig['domainsearchlist'] = $dhcpdconf['domainsearchlist']; list($pconfig['wins1'], $pconfig['wins2']) = $dhcpdconf['winsserver']; list($pconfig['dns1'], $pconfig['dns2'], $pconfig['dns3'], $pconfig['dns4']) = $dhcpdconf['dnsserver']; $pconfig['ignorebootp'] = isset($dhcpdconf['ignorebootp']); $pconfig['denyunknown'] = isset($dhcpdconf['denyunknown']); $pconfig['nonak'] = isset($dhcpdconf['nonak']); $pconfig['ddnsdomain'] = $dhcpdconf['ddnsdomain']; $pconfig['ddnsdomainprimary'] = $dhcpdconf['ddnsdomainprimary']; $pconfig['ddnsdomainkeyname'] = $dhcpdconf['ddnsdomainkeyname']; $pconfig['ddnsdomainkey'] = $dhcpdconf['ddnsdomainkey']; $pconfig['ddnsupdate'] = isset($dhcpdconf['ddnsupdate']); $pconfig['mac_allow'] = $dhcpdconf['mac_allow']; $pconfig['mac_deny'] = $dhcpdconf['mac_deny']; list($pconfig['ntp1'], $pconfig['ntp2']) = $dhcpdconf['ntpserver']; $pconfig['tftp'] = $dhcpdconf['tftp']; $pconfig['ldap'] = $dhcpdconf['ldap']; $pconfig['netboot'] = isset($dhcpdconf['netboot']); $pconfig['nextserver'] = $dhcpdconf['nextserver']; $pconfig['filename'] = $dhcpdconf['filename']; $pconfig['filename32'] = $dhcpdconf['filename32']; $pconfig['filename64'] = $dhcpdconf['filename64']; $pconfig['rootpath'] = $dhcpdconf['rootpath']; $pconfig['netmask'] = $dhcpdconf['netmask']; $pconfig['numberoptions'] = $dhcpdconf['numberoptions']; $pconfig['statsgraph'] = $dhcpdconf['statsgraph']; } $ifcfgip = $config['interfaces'][$if]['ipaddr']; $ifcfgsn = $config['interfaces'][$if]['subnet']; $subnet_start = gen_subnetv4($ifcfgip, $ifcfgsn); $subnet_end = gen_subnetv4_max($ifcfgip, $ifcfgsn); function validate_partial_mac_list($maclist) { $macs = explode(',', $maclist); // Loop through and look for invalid MACs. foreach ($macs as $mac) { if (!is_macaddr($mac, true)) { return false; } } return true; } if (isset($_POST['save'])) { unset($input_errors); $pconfig = $_POST; $numberoptions = array(); for ($x = 0; $x < 99; $x++) { if (isset($_POST["number{$x}"]) && ctype_digit($_POST["number{$x}"])) { $numbervalue = array(); $numbervalue['number'] = htmlspecialchars($_POST["number{$x}"]); $numbervalue['type'] = htmlspecialchars($_POST["itemtype{$x}"]); $numbervalue['value'] = base64_encode($_POST["value{$x}"]); $numberoptions['item'][] = $numbervalue; } } // Reload the new pconfig variable that the form uses. $pconfig['numberoptions'] = $numberoptions; /* input validation */ if ($_POST['enable'] || is_numeric($pool) || $act == "newpool") { $reqdfields = explode(" ", "range_from range_to"); $reqdfieldsn = array(gettext("Range begin"), gettext("Range end")); do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors); if (($_POST['nonak']) && !empty($_POST['failover_peerip'])) { $input_errors[] = gettext("Ignore Denied Clients may not be used when a Failover Peer IP is defined."); } if (($_POST['range_from'] && !is_ipaddrv4($_POST['range_from']))) { $input_errors[] = gettext("A valid range must be specified."); } if (($_POST['range_to'] && !is_ipaddrv4($_POST['range_to']))) { $input_errors[] = gettext("A valid range must be specified."); } if (($_POST['gateway'] && $_POST['gateway'] != "none" && !is_ipaddrv4($_POST['gateway']))) { $input_errors[] = gettext("A valid IP address must be specified for the gateway."); } if (($_POST['wins1'] && !is_ipaddrv4($_POST['wins1'])) || ($_POST['wins2'] && !is_ipaddrv4($_POST['wins2']))) { $input_errors[] = gettext("A valid IP address must be specified for the primary/secondary WINS servers."); } $parent_ip = get_interface_ip($_POST['if']); if (is_ipaddrv4($parent_ip) && $_POST['gateway'] && $_POST['gateway'] != "none") { $parent_sn = get_interface_subnet($_POST['if']); if (!ip_in_subnet($_POST['gateway'], gen_subnet($parent_ip, $parent_sn) . "/" . $parent_sn) && !ip_in_interface_alias_subnet($_POST['if'], $_POST['gateway'])) { $input_errors[] = sprintf(gettext("The gateway address %s does not lie within the chosen interface's subnet."), $_POST['gateway']); } } if (($_POST['dns1'] && !is_ipaddrv4($_POST['dns1'])) || ($_POST['dns2'] && !is_ipaddrv4($_POST['dns2'])) || ($_POST['dns3'] && !is_ipaddrv4($_POST['dns3'])) || ($_POST['dns4'] && !is_ipaddrv4($_POST['dns4']))) { $input_errors[] = gettext("A valid IP address must be specified for each of the DNS servers."); } if ($_POST['deftime'] && (!is_numeric($_POST['deftime']) || ($_POST['deftime'] < 60))) { $input_errors[] = gettext("The default lease time must be at least 60 seconds."); } if (isset($config['captiveportal']) && is_array($config['captiveportal'])) { $deftime = 7200; // Default value if it's empty if (is_numeric($_POST['deftime'])) { $deftime = $_POST['deftime']; } foreach ($config['captiveportal'] as $cpZone => $cpdata) { if (!isset($cpdata['enable'])) { continue; } if (!isset($cpdata['timeout']) || !is_numeric($cpdata['timeout'])) { continue; } $cp_ifs = explode(',', $cpdata['interface']); if (!in_array($if, $cp_ifs)) { continue; } if ($cpdata['timeout'] > $deftime) { $input_errors[] = sprintf(gettext( 'The Captive Portal zone (%1$s) has Hard Timeout parameter set to a value bigger than Default lease time (%2$s).'), $cpZone, $deftime); } } } if ($_POST['maxtime'] && (!is_numeric($_POST['maxtime']) || ($_POST['maxtime'] < 60) || ($_POST['maxtime'] <= $_POST['deftime']))) { $input_errors[] = gettext("The maximum lease time must be at least 60 seconds and higher than the default lease time."); } if (($_POST['ddnsdomain'] && !is_domain($_POST['ddnsdomain']))) { $input_errors[] = gettext("A valid domain name must be specified for the dynamic DNS registration."); } if (($_POST['ddnsdomain'] && !is_ipaddrv4($_POST['ddnsdomainprimary']))) { $input_errors[] = gettext("A valid primary domain name server IP address must be specified for the dynamic domain name."); } if (($_POST['ddnsdomainkey'] && !$_POST['ddnsdomainkeyname']) || ($_POST['ddnsdomainkeyname'] && !$_POST['ddnsdomainkey'])) { $input_errors[] = gettext("Both a valid domain key and key name must be specified."); } if ($_POST['domainsearchlist']) { $domain_array = preg_split("/[ ;]+/", $_POST['domainsearchlist']); foreach ($domain_array as $curdomain) { if (!is_domain($curdomain)) { $input_errors[] = gettext("A valid domain search list must be specified."); break; } } } // Validate MACs if (!empty($_POST['mac_allow']) && !validate_partial_mac_list($_POST['mac_allow'])) { $input_errors[] = gettext("If a mac allow list is specified, it must contain only valid partial MAC addresses."); } if (!empty($_POST['mac_deny']) && !validate_partial_mac_list($_POST['mac_deny'])) { $input_errors[] = gettext("If a mac deny list is specified, it must contain only valid partial MAC addresses."); } if (($_POST['ntp1'] && (!is_ipaddrv4($_POST['ntp1']) && !is_hostname($_POST['ntp1']))) || ($_POST['ntp2'] && (!is_ipaddrv4($_POST['ntp2']) && !is_hostname($_POST['ntp2'])))) { $input_errors[] = gettext("A valid IP address or hostname must be specified for the primary/secondary NTP servers."); } if (($_POST['domain'] && !is_domain($_POST['domain']))) { $input_errors[] = gettext("A valid domain name must be specified for the DNS domain."); } if ($_POST['tftp'] && !is_ipaddrv4($_POST['tftp']) && !is_domain($_POST['tftp']) && !filter_var($_POST['tftp'], FILTER_VALIDATE_URL)) { $input_errors[] = gettext("A valid IP address, hostname or URL must be specified for the TFTP server."); } if (($_POST['nextserver'] && !is_ipaddrv4($_POST['nextserver']))) { $input_errors[] = gettext("A valid IP address must be specified for the network boot server."); } if (gen_subnet($ifcfgip, $ifcfgsn) == $_POST['range_from']) { $input_errors[] = gettext("The network address cannot be used in the starting subnet range."); } if (gen_subnet_max($ifcfgip, $ifcfgsn) == $_POST['range_to']) { $input_errors[] = gettext("The broadcast address cannot be used in the ending subnet range."); } // Disallow a range that includes the virtualip if (is_array($config['virtualip']['vip'])) { foreach ($config['virtualip']['vip'] as $vip) { if ($vip['interface'] == $if) { if ($vip['subnet'] && is_inrange_v4($vip['subnet'], $_POST['range_from'], $_POST['range_to'])) { $input_errors[] = sprintf(gettext("The subnet range cannot overlap with virtual IP address %s."), $vip['subnet']); } } } } $noip = false; if (is_array($a_maps)) { foreach ($a_maps as $map) { if (empty($map['ipaddr'])) { $noip = true; } } } if ($_POST['staticarp'] && $noip) { $input_errors[] = gettext("Cannot enable static ARP when there are static map entries without IP addresses. Ensure all static maps have IP addresses and try again."); } if (is_array($pconfig['numberoptions']['item'])) { foreach ($pconfig['numberoptions']['item'] as $numberoption) { $numberoption_value = base64_decode($numberoption['value']); if ($numberoption['type'] == 'text' && strstr($numberoption_value, '"')) { $input_errors[] = gettext("Text type cannot include quotation marks."); } else if ($numberoption['type'] == 'string' && !preg_match('/^"[^"]*"$/', $numberoption_value) && !preg_match('/^[0-9a-f]{2}(?:\:[0-9a-f]{2})*$/i', $numberoption_value)) { $input_errors[] = gettext("String type must be enclosed in quotes like \"this\" or must be a series of octets specified in hexadecimal, separated by colons, like 01:23:45:67:89:ab:cd:ef"); } else if ($numberoption['type'] == 'boolean' && $numberoption_value != 'true' && $numberoption_value != 'false' && $numberoption_value != 'on' && $numberoption_value != 'off') { $input_errors[] = gettext("Boolean type must be true, false, on, or off."); } else if ($numberoption['type'] == 'unsigned integer 8' && (!is_numeric($numberoption_value) || $numberoption_value < 0 || $numberoption_value > 255)) { $input_errors[] = gettext("Unsigned 8-bit integer type must be a number in the range 0 to 255."); } else if ($numberoption['type'] == 'unsigned integer 16' && (!is_numeric($numberoption_value) || $numberoption_value < 0 || $numberoption_value > 65535)) { $input_errors[] = gettext("Unsigned 16-bit integer type must be a number in the range 0 to 65535."); } else if ($numberoption['type'] == 'unsigned integer 32' && (!is_numeric($numberoption_value) || $numberoption_value < 0 || $numberoption_value > 4294967295)) { $input_errors[] = gettext("Unsigned 32-bit integer type must be a number in the range 0 to 4294967295."); } else if ($numberoption['type'] == 'signed integer 8' && (!is_numeric($numberoption_value) || $numberoption_value < -128 || $numberoption_value > 127)) { $input_errors[] = gettext("Signed 8-bit integer type must be a number in the range -128 to 127."); } else if ($numberoption['type'] == 'signed integer 16' && (!is_numeric($numberoption_value) || $numberoption_value < -32768 || $numberoption_value > 32767)) { $input_errors[] = gettext("Signed 16-bit integer type must be a number in the range -32768 to 32767."); } else if ($numberoption['type'] == 'signed integer 32' && (!is_numeric($numberoption_value) || $numberoption_value < -2147483648 || $numberoption_value > 2147483647)) { $input_errors[] = gettext("Signed 32-bit integer type must be a number in the range -2147483648 to 2147483647."); } else if ($numberoption['type'] == 'ip-address' && !is_ipaddrv4($numberoption_value) && !is_hostname($numberoption_value)) { $input_errors[] = gettext("IP address or host type must be an IP address or host name."); } } } if (!$input_errors) { /* make sure the range lies within the current subnet */ if (ip_greater_than($_POST['range_from'], $_POST['range_to'])) { $input_errors[] = gettext("The range is invalid (first element higher than second element)."); } if (!is_inrange_v4($_POST['range_from'], $subnet_start, $subnet_end) || !is_inrange_v4($_POST['range_to'], $subnet_start, $subnet_end)) { $input_errors[] = gettext("The specified range lies outside of the current subnet."); } if (is_numeric($pool) || ($act == "newpool")) { if (is_inrange_v4($_POST['range_from'], $config['dhcpd'][$if]['range']['from'], $config['dhcpd'][$if]['range']['to']) || is_inrange_v4($_POST['range_to'], $config['dhcpd'][$if]['range']['from'], $config['dhcpd'][$if]['range']['to'])) { $input_errors[] = gettext("The specified range must not be within the DHCP range for this interface."); } } foreach ($a_pools as $id => $p) { if (is_numeric($pool) && ($id == $pool)) { continue; } if (is_inrange_v4($_POST['range_from'], $p['range']['from'], $p['range']['to']) || is_inrange_v4($_POST['range_to'], $p['range']['from'], $p['range']['to'])) { $input_errors[] = gettext("The specified range must not be within the range configured on a DHCP pool for this interface."); break; } } /* make sure that the DHCP Relay isn't enabled on this interface */ if (isset($config['dhcrelay']['enable']) && (stristr($config['dhcrelay']['interface'], $if) !== false)) { $input_errors[] = sprintf(gettext("The DHCP relay on the %s interface must be disabled before enabling the DHCP server."), $iflist[$if]); } if (is_array($a_maps)) { foreach ($a_maps as $map) { if (empty($map['ipaddr'])) { continue; } if (is_inrange_v4($map['ipaddr'], $_POST['range_from'], $_POST['range_to'])) { $input_errors[] = sprintf(gettext("The DHCP range cannot overlap any static DHCP mappings.")); break; } } } } } if (!$input_errors) { if (!is_numeric($pool)) { if ($act == "newpool") { $dhcpdconf = array(); } else { if (!is_array($config['dhcpd'][$if])) { $config['dhcpd'][$if] = array(); } $dhcpdconf = $config['dhcpd'][$if]; } } else { if (is_array($a_pools[$pool])) { $dhcpdconf = $a_pools[$pool]; } else { // Someone specified a pool but it doesn't exist. Punt. header("Location: services_dhcp.php"); exit; } } if (!is_array($dhcpdconf['range'])) { $dhcpdconf['range'] = array(); } $dhcpd_enable_changed = false; // Global Options if (!is_numeric($pool) && !($act == "newpool")) { $old_dhcpd_enable = isset($dhcpdconf['enable']); $new_dhcpd_enable = ($_POST['enable']) ? true : false; if ($old_dhcpd_enable != $new_dhcpd_enable) { /* DHCP has been enabled or disabled. The pf ruleset will need to be rebuilt to allow or disallow DHCP. */ $dhcpd_enable_changed = true; } $dhcpdconf['enable'] = $new_dhcpd_enable; $dhcpdconf['staticarp'] = ($_POST['staticarp']) ? true : false; $previous = $dhcpdconf['failover_peerip']; if ($previous != $_POST['failover_peerip']) { mwexec("/bin/rm -rf /var/dhcpd/var/db/*"); } $dhcpdconf['failover_peerip'] = $_POST['failover_peerip']; // dhcpleaseinlocaltime is global to all interfaces. So update the setting on all interfaces. foreach ($config['dhcpd'] as &$dhcpdifitem) { $dhcpdifitem['dhcpleaseinlocaltime'] = $_POST['dhcpleaseinlocaltime']; } } else { // Options that exist only in pools $dhcpdconf['descr'] = $_POST['descr']; } // Options that can be global or per-pool. $dhcpdconf['range']['from'] = $_POST['range_from']; $dhcpdconf['range']['to'] = $_POST['range_to']; $dhcpdconf['defaultleasetime'] = $_POST['deftime']; $dhcpdconf['maxleasetime'] = $_POST['maxtime']; $dhcpdconf['netmask'] = $_POST['netmask']; unset($dhcpdconf['winsserver']); if ($_POST['wins1']) { $dhcpdconf['winsserver'][] = $_POST['wins1']; } if ($_POST['wins2']) { $dhcpdconf['winsserver'][] = $_POST['wins2']; } unset($dhcpdconf['dnsserver']); if ($_POST['dns1']) { $dhcpdconf['dnsserver'][] = $_POST['dns1']; } if ($_POST['dns2']) { $dhcpdconf['dnsserver'][] = $_POST['dns2']; } if ($_POST['dns3']) { $dhcpdconf['dnsserver'][] = $_POST['dns3']; } if ($_POST['dns4']) { $dhcpdconf['dnsserver'][] = $_POST['dns4']; } $dhcpdconf['gateway'] = $_POST['gateway']; $dhcpdconf['domain'] = $_POST['domain']; $dhcpdconf['domainsearchlist'] = $_POST['domainsearchlist']; $dhcpdconf['ignorebootp'] = ($_POST['ignorebootp']) ? true : false; $dhcpdconf['denyunknown'] = ($_POST['denyunknown']) ? true : false; $dhcpdconf['nonak'] = ($_POST['nonak']) ? true : false; $dhcpdconf['ddnsdomain'] = $_POST['ddnsdomain']; $dhcpdconf['ddnsdomainprimary'] = $_POST['ddnsdomainprimary']; $dhcpdconf['ddnsdomainkeyname'] = $_POST['ddnsdomainkeyname']; $dhcpdconf['ddnsdomainkey'] = $_POST['ddnsdomainkey']; $dhcpdconf['ddnsupdate'] = ($_POST['ddnsupdate']) ? true : false; $dhcpdconf['mac_allow'] = $_POST['mac_allow']; $dhcpdconf['mac_deny'] = $_POST['mac_deny']; unset($dhcpdconf['ntpserver']); if ($_POST['ntp1']) { $dhcpdconf['ntpserver'][] = $_POST['ntp1']; } if ($_POST['ntp2']) { $dhcpdconf['ntpserver'][] = $_POST['ntp2']; } $dhcpdconf['tftp'] = $_POST['tftp']; $dhcpdconf['ldap'] = $_POST['ldap']; $dhcpdconf['netboot'] = ($_POST['netboot']) ? true : false; $dhcpdconf['nextserver'] = $_POST['nextserver']; $dhcpdconf['filename'] = $_POST['filename']; $dhcpdconf['filename32'] = $_POST['filename32']; $dhcpdconf['filename64'] = $_POST['filename64']; $dhcpdconf['rootpath'] = $_POST['rootpath']; unset($dhcpdconf['statsgraph']); if ($_POST['statsgraph']) { $dhcpdconf['statsgraph'] = $_POST['statsgraph']; enable_rrd_graphing(); } // Handle the custom options rowhelper if (isset($dhcpdconf['numberoptions']['item'])) { unset($dhcpdconf['numberoptions']['item']); } $dhcpdconf['numberoptions'] = $numberoptions; if (is_numeric($pool) && is_array($a_pools[$pool])) { $a_pools[$pool] = $dhcpdconf; } elseif ($act == "newpool") { $a_pools[] = $dhcpdconf; } else { $config['dhcpd'][$if] = $dhcpdconf; } write_config(); } } if ((isset($_POST['save']) || isset($_POST['apply'])) && (!$input_errors)) { $retval = 0; $retvaldhcp = 0; $retvaldns = 0; /* dnsmasq_configure calls dhcpd_configure */ /* no need to restart dhcpd twice */ if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic'])) { $retvaldns = services_dnsmasq_configure(); if ($retvaldns == 0) { clear_subsystem_dirty('hosts'); clear_subsystem_dirty('staticmaps'); } } else if (isset($config['unbound']['enable']) && isset($config['unbound']['regdhcpstatic'])) { $retvaldns = services_unbound_configure(); if ($retvaldns == 0) { clear_subsystem_dirty('unbound'); clear_subsystem_dirty('hosts'); clear_subsystem_dirty('staticmaps'); } } else { $retvaldhcp = services_dhcpd_configure(); if ($retvaldhcp == 0) { clear_subsystem_dirty('staticmaps'); } } if ($dhcpd_enable_changed) { $retvalfc = filter_configure(); } if ($retvaldhcp == 1 || $retvaldns == 1 || $retvalfc == 1) { $retval = 1; } $savemsg = get_std_save_message($retval); } if ($act == "delpool") { if ($a_pools[$_GET['id']]) { unset($a_pools[$_GET['id']]); write_config(); header("Location: services_dhcp.php?if={$if}"); exit; } } if ($act == "del") { if ($a_maps[$_GET['id']]) { unset($a_maps[$_GET['id']]); write_config(); if (isset($config['dhcpd'][$if]['enable'])) { mark_subsystem_dirty('staticmaps'); if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic'])) { mark_subsystem_dirty('hosts'); } } header("Location: services_dhcp.php?if={$if}"); exit; } } // Build an HTML table that can be inserted into a Form_StaticText element function build_pooltable() { global $a_pools, $if; $pooltbl = '