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); } }
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); }
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"); }
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"); }
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); }
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 = ' <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 = ' <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> </td> <td class="padding" align="left" width="100%"> </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"> </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); }