function subnet_conf($subnet = array(), $indent = 0)
{
    printmsg("DEBUG => subnet_conf(\$subnet, {$indent}) called", 5);
    // global $dhcp_entry_options;
    global $self;
    $exit = 0;
    // Validate input
    if (!(is_array($subnet) and count($subnet) > 0)) {
        return array(1, "");
    }
    // set the indent info if required
    $dent = '';
    if ($indent != 0) {
        $dent = '    ';
    }
    $text = "\n{$dent}# {$subnet['name']}\n";
    // Determine if this is a IPv6 address
    if ($subnet['ip_addr'] > '4294967295') {
        $text .= "{$dent}subnet6 " . ip_mangle($subnet['ip_addr'], 'ipv6') . "/" . ip_mangle($subnet['ip_mask'], 'cidr') . " {\n";
        // v6 does not allow a gateway defined, it uses the RA to do it.
        $hasgatewayoption = 1;
        $v6option = 'dhcp6.';
    } else {
        $text .= "{$dent}subnet " . long2ip($subnet['ip_addr']) . " netmask " . long2ip($subnet['ip_mask']) . " {\n";
        $hasgatewayoption = 0;
        $v6option = '';
    }
    // Loop through all of the dhcp entries and print them
    $i = 0;
    do {
        list($status, $rows, $dhcp_entry) = ona_get_dhcp_option_entry_record(array('subnet_id' => $subnet['id']));
        printmsg("DEBUG => subnet_conf(): Processing option {$dhcp_entry['display_name']}", 3);
        if (!$rows) {
            break;
        }
        if ($status) {
            $exit++;
            break;
        }
        // if the current dhcp entry is the "Default Gateway" option then set hasgatewayoption to 1
        if (strpos($dhcp_entry['name'], 'router') !== false) {
            printmsg("DEBUG => subnet_conf(\$subnet, {$indent}): --------.", 5);
            $hasgatewayoption = 1;
        }
        $i++;
        // format the tag appropriatly
        list($status, $formatted_entry) = format_tag($dhcp_entry);
        if ($formatted_entry) {
            $text .= "{$dent}    option {$v6option}{$dhcp_entry['name']} {$formatted_entry};\n";
        } else {
            $exit++;
            break;
        }
    } while ($i < $rows);
    // Loop through all of the dhcp pools and print them
    $i = 0;
    do {
        list($status, $poolrows, $pool) = ona_get_dhcp_pool_record(array('subnet_id' => $subnet['id']));
        if (!$rows) {
            break;
        }
        if ($status) {
            $exit++;
            break;
        }
        $i++;
        list($status, $srows, $server_subnet) = ona_get_dhcp_server_subnet_record(array('subnet_id' => $pool['subnet_id']));
        // if there is no failover group assignment and this pool is related to your server, print it
        if ($server_subnet['host_id'] == $self['serverid'] && $pool['dhcp_failover_group_id'] == 0) {
            printmsg("DEBUG => subnet_conf(\$subnet, {$indent}): Found pool with no failovergroup.", 5);
            list($status, $pool_entry) = process_dhcp_pool($pool, $indent);
            $text .= $pool_entry;
        }
        // if there is a failover group assignment, print the pool
        if ($pool['dhcp_failover_group_id'] != 0) {
            printmsg("DEBUG => subnet_conf(\$subnet, {$indent}): Found pool with a failovergroup", 5);
            list($status, $pool_entry) = process_dhcp_pool($pool, $indent);
            $text .= $pool_entry;
        }
    } while ($i < $poolrows);
    // Close the subnet block
    $text .= "{$dent}}\n";
    // Return the subnet block if there is a gateway option defined.
    if ($hasgatewayoption == 1) {
        return array($exit, $text);
    } else {
        printmsg("ERROR => subnet_conf({$subnet['name']}): Not enabling subnet, no gateway option defined. ", 0);
        $text = "\n{$dent}# WARNING => Subnet {$subnet['name']} has no default gateway opiton defined, skipping...\n";
        return array($exit, $text);
    }
}
Example #2
0
function rpt_get_data($form)
{
    global $base, $onadb;
    // If they want to perform a scan on an existing file
    if ($form['subnet']) {
        $rptdata['scansource'] = "Based on an existing scan file for '{$form['subnet']}'";
        //$xml = shell_exec("{$nmapcommand} -sP -R -oX - {$form['subnet']}");
        list($status, $rows, $subnet) = ona_find_subnet($form['subnet']);
        if ($rows) {
            $netip = ip_mangle($subnet['ip_addr'], 'dotted');
            $netcidr = ip_mangle($subnet['ip_mask'], 'cidr');
            $nmapxmlfile = "{$base}/local/nmap_scans/subnets/{$netip}-{$netcidr}.xml";
            if (file_exists($nmapxmlfile)) {
                $xml[0] = xml2ary(file_get_contents($nmapxmlfile));
            } else {
                $self['error'] = "ERROR => The subnet '{$form['subnet']}' does not have an nmap scan XML file on this server. {$nmapxmlfile}";
                return array(2, $self['error'] . "\n");
            }
        } else {
            $self['error'] = "ERROR => The subnet '{$form['subnet']}' does not exist.";
            return array(2, $self['error'] . "\n");
        }
    }
    // If they want to build a report on ALL the nmap data
    if ($form['all']) {
        $rptdata['scansource'] = "Showing all scan data";
        $nmapdir = "{$base}/local/nmap_scans/subnets";
        $dh = @opendir($nmapdir);
        $c = 0;
        while (false !== ($filename = @readdir($dh))) {
            if (strpos($filename, 'xml')) {
                $xml[$c] = xml2ary(file_get_contents($nmapdir . '/' . $filename));
            }
            $c++;
        }
    }
    // If they pass a file from the remote host via CLI
    if ($form['file']) {
        $rptdata['scansource'] = "Based on an uploaded XML file";
        $nmapxmlfile = $form['file'];
        // clean up escaped characters
        $nmapxmlfile = preg_replace('/\\\\"/', '"', $nmapxmlfile);
        $nmapxmlfile = preg_replace('/\\\\=/', '=', $nmapxmlfile);
        $nmapxmlfile = preg_replace('/\\\\&/', '&', $nmapxmlfile);
        $xml[0] = xml2ary($nmapxmlfile);
    }
    // loop through all the xml arrays that have been built.
    for ($z = 0; $z < count($xml); $z++) {
        // Find out how many total hosts we have in the array
        $rptdata['totalhosts'] = $xml[$z]['nmaprun']['_c']['runstats']['_c']['hosts']['_a']['total'];
        $rptdata['runtime'] = $xml[$z]['nmaprun']['_c']['runstats']['_c']['finished']['_a']['timestr'];
        // pull args to find subnet/cidr
        $rptdata['args'] = $xml[$z]['nmaprun']['_a']['args'];
        // process args
        list($subnetaddr, $netcidr) = explode('/', preg_replace("/.* (.*)\\/(\\d+)\$/", "\\1/\\2", $rptdata['args']));
        $netip = ip_mangle($subnetaddr, 'dotted');
        $netcidr = ip_mangle($netcidr, 'cidr');
        // Process the array for the total amount of hosts reported
        for ($i = 0; $i < $rptdata['totalhosts']; $i++) {
            // Clear MAC each itteration of the loop
            $macaddr = '';
            // Gather some info from the nmap XML file
            $netstatus = $xml[$z]['nmaprun']['_c']['host'][$i]['_c']['status']['_a']['state'];
            $ipaddr = $xml[$z]['nmaprun']['_c']['host'][$i]['_c']['address']['_a']['addr'];
            //$macaddr = $xml['nmaprun']['_c']['host'][$i]['_c']['address']['_a']['addr'];
            $dnsname = $xml[$z]['nmaprun']['_c']['host'][$i]['_c']['hostnames']['_c']['hostname']['_a']['name'];
            $dnsrows = 0;
            $dns = array();
            // Try the older nmap format if no IP found.. not sure of what differences there are in the XSL used?
            if (!$ipaddr) {
                $ipaddr = $xml[$z]['nmaprun']['_c']['host'][$i]['_c']['address']['0']['_a']['addr'];
                $macaddr = $xml[$z]['nmaprun']['_c']['host'][$i]['_c']['address']['1']['_a']['addr'];
            }
            // Lookup the IP address in the database
            if ($ipaddr) {
                list($status, $introws, $interface) = ona_find_interface($ipaddr);
                if (!$introws) {
                    $interface['ip_addr_text'] = 'NOT FOUND';
                    list($status, $introws, $tmp) = ona_find_subnet($ipaddr);
                    $interface['subnet_id'] = $tmp['id'];
                } else {
                    // Lookup the DNS name in the database
                    list($status, $dnsrows, $dnscount) = db_get_records($onadb, 'dns', "interface_id = {$interface['id']}", "", 0);
                    list($status, $dnsptrrows, $dnsptr) = ona_get_dns_record(array('interface_id' => $interface['id'], 'type' => 'PTR'));
                    list($status, $dnsprows, $dns) = ona_get_dns_record(array('id' => $dnsptr['dns_id']));
                }
            }
            // Find out if this IP falls inside of a pool
            $inpool = 0;
            $ip = ip_mangle($ipaddr, 'numeric');
            if ($ip > 0) {
                list($status, $poolrows, $pool) = ona_get_dhcp_pool_record("ip_addr_start <= '{$ip}' AND ip_addr_end >= '{$ip}'");
            }
            if ($poolrows) {
                $inpool = 1;
            }
            // some base logic
            // if host is up in nmap but no db ip then put in $nodb
            // if host is up and is in db then put in $noissue
            // if host is down and not in db then skip
            // if host is down and in db then put in $nonet
            // if host is up an in db, does DNS match?
            //    in DNS but not DB
            //    in DB but not DNS
            //    DNS and DB dont match
            // Setup the base array element for the IP
            $rptdata['ip'][$ipaddr] = array();
            $rptdata['ip'][$ipaddr]['netstatus'] = $netstatus;
            $rptdata['ip'][$ipaddr]['netip'] = $ipaddr;
            $rptdata['ip'][$ipaddr]['netdnsname'] = strtolower($dnsname);
            if ($macaddr != -1) {
                $rptdata['ip'][$ipaddr]['netmacaddr'] = $macaddr;
            }
            $rptdata['ip'][$ipaddr]['inpool'] = $inpool;
            $rptdata['ip'][$ipaddr]['dbip'] = $interface['ip_addr_text'];
            $rptdata['ip'][$ipaddr]['dbsubnetid'] = $interface['subnet_id'];
            $rptdata['ip'][$ipaddr]['dbdnsrows'] = $dnsrows;
            if (!$dns['fqdn']) {
                // lets see if its a PTR record
                if ($dnsptrrows) {
                    // If we have a PTR for this interface, use it (never if built from ona?)
                    $rptdata['ip'][$ipaddr]['dbdnsname'] = $dns['fqdn'];
                    $rptdata['ip'][$ipaddr]['dbdnsptrname'] = $dnsp['fqdn'];
                } else {
                    // find the hosts primary DNS record
                    list($status, $hostrows, $host) = ona_get_host_record(array('id' => $interface['host_id']));
                    if ($host['fqdn']) {
                        $host['fqdn'] = "({$host['fqdn']})";
                    }
                    if ($dnsrows) {
                        list($status, $dnstmprows, $dnstmp) = ona_get_dns_record(array('interface_id' => $interface['id']));
                        $rptdata['ip'][$ipaddr]['dbdnsname'] = $dnstmp['fqdn'];
                    } else {
                        $rptdata['ip'][$ipaddr]['dbdnsname'] = 'NO PTR';
                    }
                    $rptdata['ip'][$ipaddr]['dbdnsptrname'] = $host['fqdn'];
                }
            } else {
                if ($dnsptrrows > 1) {
                    $rptdata['ip'][$ipaddr]['dbdnsname'] = $dns['fqdn'];
                    $rptdata['ip'][$ipaddr]['dbdnsptrname'] = $dnsp['fqdn'];
                } else {
                    $rptdata['ip'][$ipaddr]['dbdnsname'] = $dns['fqdn'];
                    $rptdata['ip'][$ipaddr]['dbdnsptrname'] = $dnsp['fqdn'];
                }
            }
            $rptdata['ip'][$ipaddr]['dbmacaddr'] = $interface['mac_addr'];
            $rptdata['netip'] = $netip;
            $rptdata['netcidr'] = $netcidr;
            if ($form['all']) {
                $rptdata['all'] = 1;
            }
            if ($form['update_response']) {
                $rptdata['update_response'] = 1;
            }
        }
    }
    return array(0, $rptdata);
}
Example #3
0
function dhcp_pool_modify($options = "")
{
    // The important globals
    global $conf, $self, $onadb;
    // Version - UPDATE on every edit!
    $version = '1.03';
    printmsg("DEBUG => dhcp_pool_modify({$options}) called", 3);
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Return the usage summary if we need to
    if ($options['help'] or !($options['pool'] and ($options['set_failover_group'] or $options['set_start'] or $options['set_end'] or $options['set_llength'] or $options['set_lgrace'] or $options['set_lrenewal'] or $options['set_lrebind']))) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

dhcp_pool_modify-v{$version}
Updates a dhcp pool in the database pointing to the specified identifier

  Synopsis: dhcp_pool_modify [KEY=VALUE] ...

  Where:
    pool=ID                             Table ID for the pool

  Optional:
    set_failover_group=ID               group identifier
    set_server=NAME[.DOMAIN] or ID      server identifier
    set_start=IP                        Start ip address of pool
    set_end=IP                          End IP of pool
    set_llength=NUMBER                  Lease Time. Default ({$conf['dhcp_pool']['llength']})
    set_lgrace=NUMBER                   Lease Grace Period. Default ({$conf['dhcp_pool']['lgrace']})
    set_lrenewal=NUMBER                 Lease Renewal. Default ({$conf['dhcp_pool']['lrenewal']})
    set_lrebind=NUMBER                  Lease Rebind. Default ({$conf['dhcp_pool']['lrebind']})



EOM
);
    }
    // get the existing pool to edit
    list($status, $rows, $pool) = db_get_record($onadb, 'dhcp_pools', array('id' => $options['pool']));
    if (!$rows) {
        printmsg("DEBUG => Unable to find the DHCP pool record using id: {$options['id']}!", 3);
        $self['error'] = "ERROR => Unable to find a pool using id: {$options['pool']}";
        return array(1, $self['error'] . "\n");
    }
    // set the pool id in the set variable
    $SET['id'] = $pool['id'];
    // NOTE: currently modify pool does not allow you to change subnets
    // Get subnet info..
    list($status, $rows, $subnet) = ona_find_subnet($pool['subnet_id']);
    $SET['subnet_id'] = $subnet['id'];
    // make sure that the start address is actually part of an existing subnet
    if ($options['set_start']) {
        list($status, $rows, $subnetstart) = ona_find_subnet(ip_mangle($options['set_start'], 'dotted'));
        if (!$rows) {
            printmsg("DEBUG => Unable to find a subnet related to starting address ({$options['set_start']})!", 3);
            $self['error'] = "ERROR => Unable to find a subnet related to your starting address of {$options['set_start']}.";
            return array(1, $self['error'] . "\n");
        }
        if ($subnetstart['id'] != $pool['subnet_id']) {
            printmsg("DEBUG => The starting address ({$options['set_start']}) is not on the same subnet of the pool ({$pool['id']}) you are editing!", 3);
            $self['error'] = "ERROR => The starting address ({$options['set_start']}) is not on the same subnet of the pool ({$pool['id']}) you are editing!";
            return array(1, $self['error'] . "\n");
        }
    }
    // make sure that the end address is actually part of an existing subnet
    if ($options['set_end']) {
        list($status, $rows, $subnetend) = ona_find_subnet(ip_mangle($options['set_end'], 'dotted'));
        if (!$rows) {
            printmsg("DEBUG => Unable to find a subnet related to ending address ({$options['set_end']})!", 3);
            $self['error'] = "ERROR => Unable to find a subnet related to your ending address of {$options['set_end']}.";
            return array(1, $self['error'] . "\n");
        }
        if ($subnetend['id'] != $pool['subnet_id']) {
            printmsg("DEBUG => The ending address ({$options['set_end']}) is not on the same subnet of the pool ({$pool['id']}) you are editing!", 3);
            $self['error'] = "ERROR => The ending address ({$options['set_end']}) is not on the same subnet of the pool ({$pool['id']}) you are editing!";
            return array(1, $self['error'] . "\n");
        }
    }
    // Assign which failover group to use
    if ($options['set_failover_group'] == 0) {
        $desc = 'Not using a failover group';
        $SET['dhcp_failover_group_id'] = 0;
    } else {
        list($status, $rows, $fg) = ona_get_dhcp_failover_group_record(array('id' => $options['set_failover_group']));
        if (!$fg['id']) {
            printmsg("DEBUG => The failover_group specified ({$options['set_failover_group']}) does not exist", 3);
            $self['error'] = "ERROR => The failover_group specified ({$options['set_failover_group']}) does not exist!";
            return array(4, $self['error'] . "\n");
        }
        // get the server names for the two servers
        list($fail_host1, $fail_zone1) = ona_find_host($fg['primary_server_id']);
        list($fail_host2, $fail_zone2) = ona_find_host($fg['secondary_server_id']);
        $desc = $fail_host1['fqdn'] . '/' . $fail_host2['fqdn'];
        $SET['dhcp_failover_group_id'] = $fg['id'];
    }
    // check that start and end are not the same
    //if ($options['set_start'] and $options['set_end'] and $options['set_start'] == $options['set_end']) {
    //    printmsg("DEBUG => The start and end IP addresses (" . ip_mangle($options['set_start'],'dotted') . ") cannot be the same!",3);
    //    $self['error'] = "ERROR => The start and end IP addresses (" . ip_mangle($options['set_start'],'dotted') . ") cannot be the same!";
    //    return(array(2, $self['error'] . "\n"));
    //}
    if ($options['set_start']) {
        $start_dec = ip_mangle($options['set_start'], 'numeric');
    } else {
        $start_dec = $pool['ip_addr_start'];
    }
    if ($options['set_end']) {
        $end_dec = ip_mangle($options['set_end'], 'numeric');
    } else {
        $end_dec = $pool['ip_addr_end'];
    }
    $net_end = 4294967295 - $subnet['ip_mask'] + $subnet['ip_addr'];
    // Validate that the IP address supplied isn't the base or broadcast of the subnet
    if ($start_dec == $subnet['ip_addr'] or $end_dec == $subnet['ip_addr']) {
        printmsg("DEBUG => IP address can't be a subnet's base address (" . ip_mangle($subnet['ip_addr'], 'dotted') . ")!", 3);
        $self['error'] = "ERROR => IP address can't be a subnet's base address (" . ip_mangle($subnet['ip_addr'], 'dotted') . ")!";
        return array(7, $self['error'] . "\n");
    }
    if ($start_dec == $net_end or $end_dec == $net_end) {
        printmsg("DEBUG => IP address can't be a subnet's broadcast address (" . ip_mangle($net_end, 'dotted') . ")!", 3);
        $self['error'] = "ERROR => IP address can't be the subnet broadcast address(" . ip_mangle($net_end, 'dotted') . ")!";
        return array(8, $self['error'] . "\n");
    }
    // check that start is not after the end
    if ($start_dec > $end_dec) {
        printmsg("DEBUG => The start IP addresses (" . ip_mangle($start_dec, 'dotted') . ") falls after the end IP address (" . ip_mangle($end_dec, 'dotted') . ")!", 3);
        $self['error'] = "ERROR => The start IP addresses (" . ip_mangle($start_dec, 'dotted') . ") falls after the end IP address(" . ip_mangle($end_dec, 'dotted') . ")!";
        return array(2, $self['error'] . "\n");
    }
    // check for existing hosts inside the pool range
    list($status, $rows, $interface) = db_get_records($onadb, 'interfaces', 'subnet_id = ' . $subnet['id'] . ' AND ip_addr BETWEEN ' . $start_dec . ' AND ' . $end_dec, '', 0);
    if ($rows) {
        printmsg("DEBUG => IP conflict: Specified range (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") encompasses {$rows} host(s)!", 3);
        $self['error'] = "ERROR => IP conflict: Specified range (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") encompasses {$rows} host(s)";
        return array(4, $self['error'] . "\n");
    }
    // *** Check to see if the new pool overlaps any existing pools *** //
    // Look for overlaps like this (where new pool address starts inside an existing pool):
    //            [ -- new pool -- ]
    //    [ -- old pool --]
    list($status, $rows, $tmp) = db_get_record($onadb, 'dhcp_pools', 'id != ' . $SET['id'] . ' AND ' . $start_dec . ' BETWEEN ip_addr_start AND ip_addr_end');
    if ($rows != 0) {
        printmsg("DEBUG =>  Pool address conflict: New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") starts inside an existing pool!", 3);
        $self['error'] = "ERROR => Pool address conflict! New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") starts inside an existing pool.";
        return array(5, $self['error'] . "\n" . "INFO  => Conflicting pool record ID: {$tmp['id']}\n");
    }
    // Look for overlaps like this (where the new pool ends inside an existing pool):
    //    [ -- new pool -- ]
    //           [ -- old pool --]
    list($status, $rows, $tmp) = db_get_record($onadb, 'dhcp_pools', 'id != ' . $SET['id'] . ' AND ' . $end_dec . ' BETWEEN ip_addr_start AND ip_addr_end');
    if ($rows != 0) {
        printmsg("DEBUG =>  Pool address conflict: New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") ends inside an existing pool!", 3);
        $self['error'] = "ERROR => Pool address conflict! New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") ends inside an existing pool.";
        return array(6, $self['error'] . "\n" . "INFO  => Conflicting pool record ID: {$tmp['id']}\n");
    }
    // Look for overlaps like this (where the new pool entirely overlaps an existing pool):
    //    [ -------- new pool --------- ]
    //           [ -- old pool --]
    list($status, $rows, $tmp) = db_get_record($onadb, 'dhcp_pools', 'id != ' . $SET['id'] . ' AND (ip_addr_start BETWEEN ' . $start_dec . ' AND ' . $end_dec . ' OR ip_addr_end BETWEEN ' . $start_dec . ' AND ' . $end_dec . ')');
    if ($rows != 0) {
        printmsg("DEBUG =>  Pool address conflict: New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") would encompass an existing pool!", 3);
        $self['error'] = "ERROR => Pool address conflict! New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") would encompass an existing pool.";
        return array(7, $self['error'] . "\n" . "INFO  => Conflicting pool record ID: {$tmp['id']}\n");
    }
    // Check permissions
    if (!auth('advanced') or !authlvl($subnet['lvl'])) {
        $self['error'] = "Permission denied!";
        printmsg($self['error'], 0);
        return array(8, $self['error'] . "\n");
    }
    // define the remaining entries
    if (array_key_exists('set_lgrace', $options)) {
        $SET['lease_grace_period'] = $options['set_lgrace'];
    }
    if (array_key_exists('set_llength', $options)) {
        $SET['lease_length'] = $options['set_llength'];
    }
    if (array_key_exists('set_lrenewal', $options)) {
        $SET['lease_renewal_time'] = $options['set_lrenewal'];
    }
    if (array_key_exists('set_lrebind', $options)) {
        $SET['lease_rebind_time'] = $options['set_lrebind'];
    }
    // Set the IPs if you got this far
    $SET['ip_addr_start'] = $start_dec;
    $SET['ip_addr_end'] = $end_dec;
    // Get the DHCP pool record before updating (logging)
    list($status, $rows, $original_pool) = ona_get_dhcp_pool_record(array('id' => $SET['id']));
    // Update the record
    list($status, $rows) = db_update_record($onadb, 'dhcp_pools', array('id' => $SET['id']), $SET);
    if ($status or !$rows) {
        $self['error'] = "ERROR => dhcp_pool_modify() SQL Query failed: " . $self['error'];
        printmsg($self['error'], 0);
        return array(6, $add_to_error . $self['error'] . "\n");
    }
    $success_start = ip_mangle($SET['ip_addr_start'], 'dotted');
    $success_end = ip_mangle($SET['ip_addr_end'], 'dotted');
    // Get the DHCP pool record after updating (logging)
    list($status, $rows, $new_pool) = ona_get_dhcp_pool_record(array('id' => $SET['id']));
    // Return the success notice
    $self['error'] = "INFO => DHCP pool UPDATED:{$original_pool['id']}: {$success_start}-{$success_end} on {$subnet['name']}.";
    $log_msg = "INFO => DHCP pool UPDATED:{$original_pool['id']}: ";
    $more = "";
    foreach (array_keys($original_pool) as $key) {
        if ($original_pool[$key] != $new_pool[$key]) {
            $log_msg .= $more . $key . "[" . $original_pool[$key] . "=>" . $new_pool[$key] . "]";
            $more = ";";
        }
    }
    // only print to logfile if a change has been made to the record
    if ($more != '') {
        printmsg($self['error'], 0);
        printmsg($log_msg, 0);
    }
    return array(0, $add_to_error . $self['error'] . "\n");
}
Example #4
0
function subnet_modify($options = "")
{
    global $conf, $self, $onadb;
    //printmsg('DEBUG => subnet_modify('.implode (";",$options).') called', 3);
    // Version - UPDATE on every edit!
    $version = '1.08';
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Return the usage summary if we need to
    if ($options['help'] or !$options['subnet'] or !($options['set_ip'] or $options['set_netmask'] or $options['set_type'] or $options['set_name'] or array_key_exists('set_vlan', $options) or $options['set_security_level'])) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

subnet_modify-v{$version}
Modify a subnet (subnet) record

  Synopsis: subnet_modify [KEY=VALUE] ...

  Where:
    subnet=[ID|IP]           select subnet by search string

  Update:
    set_ip=IP                 change subnet "subnet" address
    set_netmask=MASK          change subnet netmask
    set_name=TEXT      change subnet name (i.e. "LAN-1234")
    set_type=TYPE             change subnet type by name or id
    set_vlan=VLAN             change vlan by name, number
    campus=CAMPUS             vlan campus name or id to help identify vlan
    set_security_level=LEVEL  numeric security level ({$conf['ona_lvl']})



EOM
);
    }
    $check_boundaries = 0;
    // Find the subnet record we're modifying
    list($status, $rows, $subnet) = ona_find_subnet($options['subnet']);
    if ($status or !$rows) {
        $self['error'] = "ERROR => Subnet not found";
        return array(2, $self['error'] . "\n");
    }
    // Check permissions
    if (!auth('subnet_modify')) {
        $self['error'] = "Permission denied!";
        printmsg($self['error'], 0);
        return array(3, $self['error'] . "\n");
    }
    // Validate the ip address
    if (!$options['set_ip']) {
        $options['set_ip'] = $subnet['ip_addr'];
    } else {
        $check_boundaries = 1;
        $options['set_ip'] = $setip = ip_mangle($options['set_ip'], 'numeric');
        // FIXME: what if ip_mangle returns a GMP object?
        if ($options['set_ip'] == -1) {
            $self['error'] = "ERROR => The IP address specified is invalid!";
            return array(4, $self['error'] . "\n");
        }
    }
    // Validate the netmask is okay
    if (!$options['set_netmask']) {
        $options['set_netmask'] = $subnet['ip_mask'];
        $cidr = ip_mangle($options['set_netmask'], 'cidr');
    } else {
        $check_boundaries = 1;
        $cidr = ip_mangle($options['set_netmask'], 'cidr');
        // FIXME: what if ip_mangle returns a GMP object?
        $options['set_netmask'] = ip_mangle($options['set_netmask'], 'numeric');
        if ($cidr == -1 or $options['set_netmask'] == -1) {
            $self['error'] = "ERROR => The netmask specified is invalid!";
            return array(5, $self['error'] . "\n");
        }
    }
    if (is_ipv4($setip)) {
        $padding = 32;
        $fmt = 'dotted';
        $ip1 = ip_mangle($setip, 'binary');
        $num_hosts = 0xffffffff - $options['set_netmask'];
        $first_host = $options['set_ip'] + 1;
        $last_host = $options['set_ip'] + $num_hosts;
        $str_last_host = $last_host;
        $last_last_host = $last_host - 1;
    } else {
        $padding = 128;
        $fmt = 'ipv6gz';
        $ip1 = ip_mangle($setip, 'bin128');
        $first_host = gmp_strval(gmp_add($options['set_ip'], 1));
        $sub = gmp_sub("340282366920938463463374607431768211455", $options['set_netmask']);
        $last_host = gmp_add($options['set_ip'], $sub);
        $str_last_host = gmp_strval($last_host);
        $last_last_host = gmp_strval(gmp_sub($last_host, 1));
    }
    // Validate that the subnet IP & netmask combo are valid together.
    $ip2 = str_pad(substr($ip1, 0, $cidr), $padding, '0');
    $ip1 = ip_mangle($ip1, $fmt);
    $ip2 = ip_mangle($ip2, $fmt);
    if ($ip1 != $ip2) {
        $self['error'] = "ERROR => Invalid subnet specified - did you mean: {$ip2}/{$cidr}?";
        return array(6, $self['error'] . "\n");
    }
    // If our IP or netmask changed we need to make sure that
    // we won't abandon any host interfaces.
    // We also need to verify that the new boundaries are valid and
    // don't interefere with any other subnets.
    if ($check_boundaries == 1) {
        // *** Check to see if the new subnet overlaps any existing ONA subnets *** //
        // I convert the IP address to dotted format when calling ona_find_subnet()
        // because it saves it from doing a few unnecessary sql queries.
        // Look for overlaps like this (where new subnet address starts inside an existing subnet):
        //            [ -- new subnet -- ]
        //    [ -- old subnet --]
        list($status, $rows, $record) = ona_find_subnet(ip_mangle($options['set_ip'], 'dotted'));
        if ($rows and $record['id'] != $subnet['id']) {
            $self['error'] = "ERROR => Subnet address conflict! New subnet starts inside an existing subnet.";
            return array(7, $self['error'] . "\n" . "ERROR  => Conflicting subnet record ID: {$record['id']}\n");
        }
        // Look for overlaps like this (where the new subnet ends inside an existing subnet):
        //    [ -- new subnet -- ]
        //           [ -- old subnet --]
        // Find last address of our subnet, and see if it's inside of any other subnet:
        list($status, $rows, $record) = ona_find_subnet(ip_mangle($str_last_host, 'dotted'));
        if ($rows and $record['id'] != $subnet['id']) {
            $self['error'] = "ERROR => Subnet address conflict! New subnet ends inside an existing subnet.";
            return array(8, $self['error'] . "\n" . "ERROR  => Conflicting subnet record ID: {$record['id']}\n");
        }
        // Look for overlaps like this (where the new subnet entirely overlaps an existing subnet):
        //    [ -------- new subnet --------- ]
        //           [ -- old subnet --]
        //
        // Do a cool SQL query to find all subnets whose start address is >= or <= the
        // new subnet base address.
        $where = "ip_addr >= {$options['set_ip']} AND ip_addr <= {$str_last_host}";
        list($status, $rows, $record) = ona_get_subnet_record($where);
        if ($rows > 1 or $rows == 1 and $record['id'] != $subnet['id']) {
            $self['error'] = "ERROR => Subnet address conflict! New subnet would encompass an existing subnet.";
            return array(9, $self['error'] . "\n" . "ERROR  => Conflicting subnet record ID: {$record['id']}\n");
        }
        // Look for any hosts that are currently in our subnet that would be
        // abandoned if we were to make the proposed changes.
        // Look for hosts on either side of the new subnet boundaries:
        //            [--- new subnet ---]
        //         *      **   *            *   <-- Hosts: the first and last host would be a problem!
        //       [------- old subnet --------]
        //
        $where1 = "subnet_id = {$subnet['id']} AND ip_addr < {$first_host}";
        $where2 = "subnet_id = {$subnet['id']} AND ip_addr > {$last_last_host}";
        list($status, $rows1, $record) = ona_get_interface_record($where1);
        list($status, $rows2, $record) = ona_get_interface_record($where2);
        if ($rows1 or $rows2) {
            $num = $rows1 + $rows2;
            $self['error'] = "ERROR => Changes would abandon {$num} hosts in an unallocated ip space";
            return array(10, $self['error'] . "\n");
        }
        // Look for any dhcp pools that are currently in our subnet that would be
        // abandoned if we were to make the proposed changes.
        // Look for existin pools with start/end values outside of new subnet range
        //            [--- new subnet ---]
        //                      [--cur pool--]
        //       [------- old subnet --------]
        //
        $where1 = "subnet_id = {$subnet['id']} AND ip_addr_start < {$options['set_ip']}";
        $where2 = "subnet_id = {$subnet['id']} AND ip_addr_end > {$str_last_host}";
        list($status, $rows1, $record) = ona_get_dhcp_pool_record($where1);
        list($status, $rows2, $record) = ona_get_dhcp_pool_record($where2);
        if ($rows1 or $rows2) {
            $num = $rows1 + $rows2;
            $self['error'] = "ERROR => Changes would abandon a DHCP pool in an unallocated ip space, adjust pool sizes first";
            return array(10, $self['error'] . "\n");
        }
    }
    //
    // Define the fields we're updating
    //
    // This variable will contain the updated info we'll insert into the DB
    $SET = array();
    $SET['ip_addr'] = $options['set_ip'];
    $SET['ip_mask'] = $options['set_netmask'];
    // Set options['set_security_level']?
    // Sanitize "security_level" option
    if (array_key_exists('set_security_level', $options)) {
        $options['set_security_level'] = sanitize_security_level($options['set_security_level']);
        if ($options['set_security_level'] == -1) {
            return array(11, $self['error'] . "\n");
        }
        $SET['lvl'] = $options['set_security_level'];
    }
    // Set options['set_name']?
    if ($options['set_name']) {
        // BUSINESS RULE: We require subnet names to be in upper case and spaces are converted to -'s.
        $options['set_name'] = trim($options['set_name']);
        $options['set_name'] = preg_replace('/\\s+/', '-', $options['set_name']);
        $options['set_name'] = strtoupper($options['set_name']);
        // Make sure there's not another subnet with this name
        list($status, $rows, $tmp) = ona_get_subnet_record(array('name' => $options['set_name']));
        if ($status or $rows > 1 or $rows == 1 and $tmp['id'] != $subnet['id']) {
            $self['error'] = "ERROR => That name is already used by another subnet!";
            return array(12, $self['error'] . "\n");
        }
        $SET['name'] = $options['set_name'];
    }
    // Set options['set_type']?
    if ($options['set_type']) {
        // Find the type from $options[type]
        list($status, $rows, $subnet_type) = ona_find_subnet_type($options['set_type']);
        if ($status or $rows != 1) {
            $self['error'] = "ERROR => Invalid subnet type specified!";
            return array(13, $self['error'] . "\n");
        }
        printmsg("Subnet type selected: {$subnet_type['display_name']} ({$subnet_type['short_name']})", 1);
        $SET['subnet_type_id'] = $subnet_type['id'];
    }
    // Set options['set_vlan']?
    if (array_key_exists('set_vlan', $options) or $options['campus']) {
        if (!$options['set_vlan']) {
            $SET['vlan_id'] = '';
        } else {
            // Find the VLAN ID from $options[set_vlan] and $options[campus]
            list($status, $rows, $vlan) = ona_find_vlan($options['set_vlan'], $options['campus']);
            if ($status or $rows != 1) {
                $self['error'] = "ERROR => The vlan/campus pair specified is invalid!";
                return array(15, $self['error'] . "\n");
            }
            printmsg("VLAN selected: {$vlan['name']} in {$vlan['vlan_campus_name']} campus", 1);
            $SET['vlan_id'] = $vlan['id'];
        }
    }
    // Update the subnet record
    list($status, $rows) = db_update_record($onadb, 'subnets', array('id' => $subnet['id']), $SET);
    if ($status or !$rows) {
        return array(16, $self['error'] . "\n");
    }
    // Load the updated record for display
    list($status, $rows, $subnet) = ona_get_subnet_record(array('id' => $subnet['id']));
    // Return the (human-readable) success notice
    $text = format_array($SET);
    $self['error'] = "INFO => Subnet UPDATED";
    return array(0, $self['error'] . ":\n{$text}\n");
}
Example #5
0
function interface_move($options = "")
{
    global $conf, $self, $onadb;
    printmsg("DEBUG => interface_move({$options}) called", 3);
    // Version - UPDATE on every edit!
    $version = '1.04';
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Return the usage summary if we need to
    if ($options['help'] or !$options['start'] or !$options['new_start']) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

interface_move-v{$version}
  Moves all interface addresses from one subnet to another.
  The initial range of IPs does not have to be consecutive.
  The new range of IPs will be used sequentially.

  Synopsis: interface_move [KEY=VALUE] ...

  IP block to move: (source)
    start=IP                      first IP to move
    [end=IP]                      last IP to move

  New IP block: (destination)
    new_start=IP                  first new IP address
    [new_end=IP]                  last new IP address

  Optional:
    commit=[yes|no]               commit db transaction (no)


EOM
);
    }
    // Set options[force] and options[create_a] to N if it's not set
    $options['commit'] = sanitize_YN($options['commit'], 'N');
    // Find the "start" subnet record by IP address
    list($status, $rows, $old_subnet) = ona_find_subnet($options['start']);
    if (!$old_subnet or !$old_subnet['id']) {
        printmsg("DEBUG => Source start address ({$options['start']}) isn't valid!", 3);
        $self['error'] = "ERROR => Source (start) address specified isn't valid!";
        return array(2, $self['error'] . "\n");
    }
    // If they specified an "END" address, make sure it's valid and on the same subnet
    if ($options['end']) {
        // Find an interface record by something in that interface's record
        list($status, $rows, $old_subnet_end) = ona_find_subnet($options['end']);
        // If we didn't get a record then exit
        if (!$old_subnet_end or !$old_subnet_end['id']) {
            printmsg("DEBUG => Source end address ({$options['end']}) isn't valid!", 3);
            $self['error'] = "ERROR => Source (end) address specified isn't valid!";
            return array(3, $self['error'] . "\n");
        }
        if ($old_subnet_end['id'] != $old_subnet['id']) {
            printmsg("DEBUG => Both source addresses ({$options['start']} and {$options['end']}) must be on the same subnet!", 3);
            $self['error'] = "ERROR => Both the source addresses (start and end) must be on the same subnet!";
            return array(4, $self['error'] . "\n");
        }
    } else {
        printmsg("DEBUG => Only moving one host source={$options['start']}!", 3);
        $options['end'] = $options['start'];
    }
    // Find the "end" subnet record by IP address
    list($status, $rows, $new_subnet) = ona_find_subnet($options['new_start']);
    // If we didn't get a record then exit
    if (!$new_subnet or !$new_subnet['id']) {
        printmsg("DEBUG => Destination start address ({$options['new_start']}) isn't valid!", 3);
        $self['error'] = "ERROR => Destination (new_start) address specified isn't valid!";
        return array(2, $self['error'] . "\n");
    }
    // Make sure the "old" and "new" subnets are different subnets
    if ($old_subnet['id'] == $new_subnet['id']) {
        printmsg("DEBUG => Both the source IP range ({$options['start']}+) and the destination IP range ({$options['new_start']}+) are on the same subnet!", 3);
        $self['error'] = "ERROR => Both the source IP range and the destination IP range are on the same subnet!";
        return array(2, $self['error'] . "\n");
    }
    // If they specified a "new_end" address, make sure it's valid and on the same subnet as the new_start subnet
    if ($options['new_end']) {
        // Find an interface record by something in that interface's record
        list($status, $rows, $new_subnet_end) = ona_find_subnet($options['new_end']);
        // If we didn't get a record then exit
        if (!$new_subnet_end or !$new_subnet_end['id']) {
            printmsg("DEBUG => Destination end address ({$options['new_end']}) isn't valid!", 3);
            $self['error'] = "ERROR => Destination (new_end) address specified isn't valid!";
            return array(3, $self['error'] . "\n");
        }
        if ($new_subnet_end['id'] != $new_subnet['id']) {
            printmsg("DEBUG => Both destination addresses ({$options['new_start']} and {$options['new_end']}) must be on the same subnet!", 3);
            $self['error'] = "ERROR => Both the destination addresses (new_start and new_end) must be on the same subnet!";
            return array(4, $self['error'] . "\n");
        }
    } else {
        printmsg("DEBUG => Only moving one host destination={$options['new_start']}!", 3);
        $options['new_end'] = $options['new_start'];
    }
    // Check permissions at the subnet level
    if (!auth('interface_modify')) {
        $self['error'] = "Permission denied!";
        printmsg($self['error'], 0);
        return array(13, $self['error'] . "\n");
    }
    // An array for all the interface records we'll be moving
    $to_move = array();
    // Message to display if we succeed
    $message = "";
    // Load all the interface records we'll be moving
    $i = 0;
    do {
        // FIXME: this should do a more advanced query someday! (like checking that the ipaddress is >= start and <= end
        list($status, $rows, $interface) = ona_get_interface_record(array('subnet_id' => $old_subnet['id']), 'ip_addr');
        if ($rows == 0) {
            break;
        }
        $i++;
        if ($interface['ip_addr'] >= ip_mangle($options['start'], 'numeric')) {
            if ($interface['ip_addr'] <= ip_mangle($options['end'], 'numeric')) {
                $to_move[$i] = $interface;
            }
        }
    } while ($i < $rows);
    $total_to_move = count($to_move);
    $total_assigned = 0;
    // If there's nothing to do, tell them
    if ($total_to_move == 0) {
        printmsg("DEBUG => There are no interfaces in the source address block!", 3);
        $self['error'] = "ERROR => There are no interfaces in the source address block!";
        return array(6, $self['error'] . "\n");
    }
    // Make sure we have a high enough "LVL" to modify the associated hosts
    foreach ($to_move as $interface) {
        // Load the associated host record
        list($status, $rows, $host) = ona_get_host_record(array('id' => $interface['host_id']));
        list($status, $rows, $dns) = ona_get_dns_record(array('id' => $host['primary_dns_id'], 'type' => 'A'));
        // Check permissions at the subnet level
        if (!authlvl($host['LVL'])) {
            $self['error'] = "Permission denied! Can't modify Host: {$host['id']} {$dns['fqdn']}";
            printmsg($self['error'], 0);
            return array(14, $self['error'] . "\n");
        }
        // Check to see if the host has any interfaces in the destination subnet
        // MP: this is now allowed
        //         list($status, $rows, $interface) = ona_get_interface_record(array('host_id' => $interface['host_id'], 'subnet_id' => $new_subnet['id']));
        //         if ($status or $rows) {
        //             printmsg("DEBUG => Source host {$ddns['fqdn']} already has an interface on the destination subnet!",3);
        //             $self['error'] = "ERROR => Source host {$dns['fqdn']} (ID {$host['id']}) already has an interface on the destination subnet!";
        //             return(array(15, $self['error'] . "\n"));
        //         }
    }
    // Get the numeric version of the start/end addresses we are moving interfaces to
    // .. and make sure that the $low_ip and $high_ip are not subnet or broadcast addresses!
    $low_ip = ip_mangle($options['new_start'], 'numeric');
    $high_ip = ip_mangle($options['new_end'], 'numeric');
    if ($low_ip == $new_subnet['ip_addr']) {
        $low_ip++;
    }
    $num_hosts = 0xffffffff - $new_subnet['ip_mask'];
    if ($high_ip == $new_subnet['ip_addr'] + $num_hosts) {
        $high_ip--;
    }
    printmsg("INFO => Asked to move {$total_to_move} interfaces to new range: " . ip_mangle($low_ip, 'dotted') . ' - ' . ip_mangle($high_ip, 'dotted'), 0);
    // Loop through each interface we need to move, and find an available address for it.
    $pool_interfering = 0;
    foreach (array_keys($to_move) as $i) {
        while ($low_ip <= $high_ip) {
            list($status, $rows, $interface) = ona_get_interface_record(array('ip_addr' => $low_ip));
            if ($rows == 0 and $status == 0) {
                // Since the IP seems available, let's double check and make sure it's not in a DHCP address pool
                list($status, $rows, $pool) = ona_get_dhcp_pool_record("ip_addr_start < '{$low_ip}' AND ip_addr_end > '{$low_ip}'");
                if ($rows == 0 and $status == 0) {
                    // The IP is available, lets use it!
                    $to_move[$i]['new_ip_address'] = $low_ip;
                    $total_assigned++;
                    $low_ip++;
                    break;
                }
                $pool_interfering = 1;
                printmsg("DEBUG => Couldn't use the DHCP POOL address: " . ip_mangle($low_ip, 'dotted'), 3);
            }
            $low_ip++;
        }
    }
    // If total_assigned != total_to_move, error - not enough free IP addresses in destination subnet!
    if ($total_assigned != $total_to_move) {
        printmsg("DEBUG => The destination IP range doesn't have enough free IP addresses!", 3);
        $self['error'] = "ERROR => The destination IP range doesn't have enough free IP addresses!\n";
        if ($pool_interfering) {
            $self['error'] .= "INFO => Some IPs in the destination range were part of a DHCP pool range.\n";
        }
        return array(6, $self['error']);
    }
    // Display what we would have done if "commit" isn't "yes"
    if ($options['commit'] != "Y") {
        $self['error'] = "Interface(s) NOT MOVED (see \"commit\" option)";
        $text = $self['error'] . "\n" . "Displaying {$total_to_move} interface(s) that would have been moved:\n\n";
        foreach ($to_move as $interface) {
            // Get display the hostname we would have moved, as well as it's IP address.
            list($status, $rows, $host) = ona_get_host_record(array('id' => $interface['host_id']));
            list($status, $rows, $dns) = ona_get_dns_record(array('id' => $host['primary_dns_id'], 'type' => 'A'));
            $hostname = strtolower("{$dns['fqdn']}");
            $text .= "  " . ip_mangle($interface['ip_addr'], 'dotted') . " -> " . ip_mangle($interface['new_ip_address'], 'dotted') . "\t({$hostname})\n";
        }
        $text .= "\n";
        return array(7, $text);
    }
    // Loop through and update each interface's IP_ADDRESS and SUBNET_ID
    $text = "SUCCESS => {$total_to_move} interface(s) moved\n";
    $text .= "Interface(s) moved:\n\n";
    foreach ($to_move as $interface) {
        list($status, $rows) = ona_update_record("interfaces", array('id' => $interface['id']), array('ip_addr' => $interface['new_ip_address'], 'subnet_id' => $new_subnet['id']));
        if ($status != 0 or $rows != 1) {
            $self['error'] = "ERROR => Database update failed! {$self['error']}";
            return array(8, $self['error'] . "\n");
        }
        // Get display the hostname we would have moved, as well as its IP address.
        list($status, $rows, $host) = ona_get_host_record(array('id' => $interface['host_id']));
        list($status, $rows, $dns) = ona_get_dns_record(array('id' => $host['primary_dns_id'], 'type' => 'A'));
        $hostname = strtolower("{$dns['fqdn']}");
        $text .= "  " . ip_mangle($interface['ip_addr'], 'dotted') . " -> " . ip_mangle($interface['new_ip_address'], 'dotted') . "\t({$hostname})\n";
    }
    // Return the success notice
    return array(0, $text);
}
Example #6
0
function ws_editor($window_name, $form = '')
{
    global $conf, $self, $onadb;
    global $font_family, $color, $style, $images;
    $window = array();
    // Check permissions
    if (!auth('advanced')) {
        $response = new xajaxResponse();
        $response->addScript("alert('Permission denied!');");
        return $response->getXML();
    }
    // If an array in a string was provided, build the array and store it in $form
    $form = parse_options_string($form);
    if ($form['subnet_id']) {
        $form['subnet'] = $form['subnet_id'];
    }
    // if it is a new pool, setup some things
    if (!$form['id']) {
        list($status, $rows, $subnet) = ona_get_subnet_record(array('id' => $form['subnet']));
        // set start and end IP to subnet IP
        $pool['start_ip'] = $pool['end_ip'] = ip_mangle($subnet['ip_addr'], 'dotted');
        // setup defaults for form values-- FIXME use $conf['dhcp_pool'] stuff later
        $pool['lease_length'] = '604800';
        $pool['lease_grace_period'] = '0';
        $pool['lease_rebind_time'] = '0';
        $pool['lease_renewal_time'] = '0';
        $pool['server_name_text'] = 'None';
        $window['title'] = "Add DHCP Pool";
    } else {
        list($status, $rows, $pool) = ona_get_dhcp_pool_record(array('id' => $form['id']));
        $pool['start_ip'] = ip_mangle($pool['ip_addr_start']);
        $pool['end_ip'] = ip_mangle($pool['ip_addr_end']);
        $pool['server_name_text'] = 'None';
        // Load the subnet record and associated info.
        if (is_numeric($form['subnet'])) {
            list($status, $rows, $subnet) = ona_get_subnet_record(array('id' => $form['subnet']));
        }
        // Load the server record and associated info.
        if ($pool['dhcp_failover_group_id'] >= 1) {
            list($status, $rows, $failover) = ona_get_dhcp_failover_group_record(array('id' => $pool['dhcp_failover_group_id']));
            list($status, $rows, $fail_host1) = ona_find_host($failover['primary_server_id']);
            list($status, $rows, $fail_host2) = ona_find_host($failover['secondary_server_id']);
            $pool['server_name_text'] = $fail_host1['fqdn'] . "/" . $fail_host2['fqdn'];
        }
        $window['title'] = "Edit DHCP Pool";
    }
    // Escape data for display in html
    foreach (array_keys((array) $subnet) as $key) {
        $subnet[$key] = htmlentities($subnet[$key], ENT_QUOTES, $conf['php_charset']);
    }
    foreach (array_keys((array) $failover) as $key) {
        $failover[$key] = htmlentities($failover[$key], ENT_QUOTES, $conf['php_charset']);
    }
    foreach (array_keys((array) $zone) as $key) {
        $zone[$key] = htmlentities($zone[$key], ENT_QUOTES, $conf['php_charset']);
    }
    foreach (array_keys((array) $host) as $key) {
        $host[$key] = htmlentities($host[$key], ENT_QUOTES, $conf['php_charset']);
    }
    foreach (array_keys((array) $server) as $key) {
        $server[$key] = htmlentities($server[$key], ENT_QUOTES, $conf['php_charset']);
    }
    // Javascript to run after the window is built
    $window['js'] = <<<EOL
        /* Put a minimize icon in the title bar */
        el('{$window_name}_title_r').innerHTML =
            '&nbsp;<a onClick="toggle_window(\\'{$window_name}\\');" title="Minimize window" style="cursor: pointer;"><img src="{$images}/icon_minimize.gif" border="0" /></a>' +
            el('{$window_name}_title_r').innerHTML;

        /* Put a help icon in the title bar */
        el('{$window_name}_title_r').innerHTML =
            '&nbsp;<a href="{$_ENV['help_url']}{$window_name}" target="null" title="Help" style="cursor: pointer;"><img src="{$images}/silk/help.png" border="0" /></a>' +
            el('{$window_name}_title_r').innerHTML;

        el('{$window_name}_form').onsubmit = function() { return false; };

        /* Setup the Quick Find pool server icon */
    var _button = el('qf_pool_server_{$window_name}');
    _button.style.cursor = 'pointer';
    _button.onclick =
        function(ev) {
            if (!ev) ev = event;
            /* Create the popup div */
            wwTT(this, ev,
                 'id', 'tt_qf_pool_server_{$window_name}',
                 'type', 'static',
                 'direction', 'south',
                 'delay', 0,
                 'styleClass', 'wwTT_qf',
                 'javascript',
                 "xajax_window_submit('tooltips', '" +
                     "tooltip=>qf_pool_server," +
                     "id=>tt_qf_pool_server_{$window_name}," +
                     "text_id=>pool_server_text_{$window_name}," +
                     "server=>set_pool_server_{$window_name}," +
                     "server_name=>{$pool['server_name_text']}," +
                     "failover_group_id=>{$pool['dhcp_failover_group_id']}," +
                     "failover_group=>set_failover_group_{$window_name}');"
            );
        };


EOL;
    // Define the window's inner html
    $window['html'] = <<<EOL

    <!-- DHCP pool Edit Form -->
    <form id="{$window_name}_form" onSubmit="return false;">
    <input type="hidden" name="id" value="{$pool['id']}">
    <input type="hidden" name="subnet_id" value="{$form['subnet']}">
    <input type="hidden" name="js" value="{$form['js']}">
    <table cellspacing="0" border="0" cellpadding="0" style="background-color: {$color['window_content_bg']}; padding-left: 20px; padding-right: 20px; padding-top: 5px; padding-bottom: 5px;">

        <!-- DHCP POOL RECORD -->
        <tr>
            <td align="left" nowrap="true"><b><u>DHCP Pool</u></b>&nbsp;</td>
            <td class="padding" align="left" width="100%">&nbsp;</td>
        </tr>

        <tr>
            <td align="right" nowrap="true">
                Subnet:
            </td>
            <td class="padding" align="left" width="100%">
                {$subnet['name']}
            </td>
        </tr>


        <tr>
            <td align="right" nowrap="true">
                Failover Group
            </td>
            <td class="padding" align="left" width="100%" nowrap="true">
                <input
                    type="hidden"
                    id="set_failover_group_{$window_name}"
                    name="failover_group"
                    value="{$pool['dhcp_failover_group_id']}">

                <span id="qf_pool_server_{$window_name}" title="DHCP Pool Server Quick Select">
                    <a id="pool_server_text_{$window_name}"
                       class="nav"
                    >{$pool['server_name_text']}</a>
                    <img src="{$images}/silk/find.png" border="0"
                /></span>
            </td>
        </tr>


        <!-- TODO: add a qf for IP addresses to list avail ips on subnet -->



        <tr>
            <td class="input_required" align="right" nowrap="true">
                IP Start
            </td>
            <td class="padding" align="left" width="100%">
                <input
                    name="start"
                    alt="IP Start"
                    value="{$pool['start_ip']}"
                    class="edit"
                    type="text"
                    size="25" maxlength="255"
                >
            </td>
        </tr>

        <tr>
            <td class="input_required" align="right" nowrap="true">
                IP End
            </td>
            <td class="padding" align="left" width="100%">
                <input
                    name="end"
                    alt="IP End"
                    value="{$pool['end_ip']}"
                    class="edit"
                    type="text"
                    size="25" maxlength="255"
                >
            </td>
        </tr>

        <tr>
            <td align="right" nowrap="true">
                Lease Length
            </td>
            <td class="padding" align="left" width="100%">
                <input
                    name="llength"
                    alt="Lease Length"
                    value="{$pool['lease_length']}"
                    class="edit"
                    type="text"
                    size="10" maxlength="10"
                >
            </td>
        </tr>

        <tr>
            <td align="right" nowrap="true">
                Lease Grace
            </td>
            <td class="padding" align="left" width="100%">
                <input
                    name="lgrace"
                    alt="Lease Grace"
                    value="{$pool['lease_grace_period']}"
                    class="edit"
                    type="text"
                    size="10" maxlength="10"
                >
            </td>
        </tr>

        <tr>
            <td align="right" nowrap="true">
                Lease Renewal
            </td>
            <td class="padding" align="left" width="100%">
                <input
                    name="lrenewal"
                    alt="Lease Renewal"
                    value="{$pool['lease_renewal_time']}"
                    class="edit"
                    type="text"
                    size="10" maxlength="10"
                >
            </td>
        </tr>


        <tr>
            <td align="right" nowrap="true">
                Lease Rebind
            </td>
            <td class="padding" align="left" width="100%">
                <input
                    name="lrebind"
                    alt="Lease Rebind"
                    value="{$pool['lease_rebind_time']}"
                    class="edit"
                    type="text"
                    size="10" maxlength="10"
                >
            </td>
        </tr>




        <tr>
            <td align="right" valign="top" nowrap="true">
                &nbsp;
            </td>
            <td class="padding" align="right" width="100%">
                <input type="hidden" name="overwrite" value="{$overwrite}">
                <input class="edit" type="button" name="cancel" value="Cancel" onClick="removeElement('{$window_name}');">
                <input class="edit" type="button"
                    name="submit"
                    value="Save"
                    accesskey=" "
                    onClick="xajax_window_submit('{$window_name}', xajax.getFormValues('{$window_name}_form'), 'save');"
                >
            </td>
        </tr>

    </table>
    </form>
EOL;
    return window_open($window_name, $window);
}