function dns_record_modify($options = "") { global $conf, $self, $onadb; // Version - UPDATE on every edit! $version = '1.13'; printmsg("DEBUG => dns_record_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['set_name'] and !$options['set_ip'] and !$options['set_ttl'] and !$options['set_pointsto'] and !$options['set_srv_pri'] and !$options['set_srv_weight'] and !$options['set_srv_port'] and !$options['set_mx_preference'] and !$options['set_notes'] and !$options['set_view']) { // NOTE: Help message lines should not exceed 80 characters for proper display on a console $self['error'] = 'ERROR => Insufficient parameters'; return array(1, <<<EOM dns_record_modify-v{$version} Modify a DNS record Synopsis: dns_record_modify [KEY=VALUE] ... Where: name=NAME[.DOMAIN] or ID select dns record by name or ID Update: set_name=NAME[.DOMAIN] change name and/or domain set_ip=ADDRESS change IP the record points to set_ttl=NUMBER change the TTL value, 0 = use domains TTL value set_pointsto=NAME[.DOMAIN] change where a CNAME points set_notes=NOTES change the textual notes set_mx_preference=NUMBER change the MX record preference value set_txt=STRING change the value of the TXT record set_srv_pri=NUMBER change SRV Priority set_srv_weight=NUMBER change SRV Weight set_srv_port=NUMBER change SRV Port set_ebegin change the begin date for record, 0 disables set_domain=DOMAIN use if you need to explicitly set domain set_view=STRING change DNS view identifier. AKA Split horizon. Note: * You are not allowed to change the type of the DNS record, to do that you must delete and re-add the record with the new type. * DOMAIN will default to {$conf['dns_defaultdomain']} if not specified EOM ); } /* Modify logic 1. find the dns record we are editing 2. If it is an A, check that the name we are changing to does not already match an existing A/ip or CNAME 3. if its a CNAME, check that it is not the same as any other records. */ // Check permissions if (!auth('host_modify')) { $self['error'] = "Permission denied!"; printmsg($self['error'], 0); return array(10, $self['error'] . "\n"); } // Sanitize addptr.. set it to Y if it is not set $options['set_addptr'] = sanitize_YN($options['set_addptr'], 'Y'); // clean up what is passed in $options['set_ip'] = trim($options['set_ip']); $options['set_pointsto'] = trim($options['set_pointsto']); $options['set_name'] = trim($options['set_name']); $options['set_domain'] = trim($options['set_domain']); $options['set_txt'] = trim($options['set_txt']); //$options['set_view'] = trim($options['set_view']); // // Find the dns record we're modifying // // If the name we were passed has a leading . in it then remove the dot. $options['set_name'] = preg_replace("/^\\./", '', $options['set_name']); // Find the DNS record from $options['name'] list($status, $rows, $dns) = ona_find_dns_record($options['name']); printmsg("DEBUG => dns_record_modify() DNS record: {$dns['fqdn']}", 3); if ($rows > 1) { printmsg("DEBUG => Found more than one DNS record for: {$options['name']}", 3); $self['error'] = "ERROR => Found more than one DNS record for: {$options['name']}"; return array(2, $self['error'] . "\n"); } // If we didn't get a record then exit if (!$dns['id']) { printmsg("DEBUG => DNS record not found ({$options['name']})!", 3); $self['error'] = "ERROR => DNS record not found ({$options['name']})!"; return array(4, $self['error'] . "\n"); } // Set the current_name variable with the records current name // Used by the add pointer function below since it runs before any names are updated $current_name = $dns['fqdn']; $current_int_id = $dns['interface_id']; $check_dns_view_id = $dns['dns_view_id']; $current_dns_view_id = $dns['dns_view_id']; // Set status on if we are chaning IP addresses $changingint = 0; $changingview = 0; // Set a message to display when using dns views if ($conf['dns_views']) { $viewmsg = ' Ensure you are selecting the proper DNS view for this record.'; } // // Define the records we're updating // // This variable will contain the updated info we'll insert into the DB $SET = array(); // Gather DNS view information if (array_key_exists('set_view', $options)) { if (is_numeric($options['set_view'])) { $viewsearch = array('id' => $options['set_view']); } else { $viewsearch = array('name' => strtoupper($options['set_view'])); } // find the IP interface record, list($status, $rows, $dnsview) = ona_get_dns_view_record($viewsearch); if (!$rows) { printmsg("ERROR => dns_record_modify() Unable to find DNS view: {$options['set_view']}", 3); $self['error'] = "ERROR => dns_record_modify() Unable to find DNS view: {$options['set_view']}."; return array(4, $self['error'] . "\n"); } // If we have a new dns view, add it to the SET array and update the check view variable used in all the checks. if ($dns['dns_view_id'] != $dnsview['id']) { // You can only change the view on parent records.. if this record has a dns_id, you must change the parent if ($dns['dns_id']) { printmsg("ERROR => You must change the parent DNS A record to the new view. This record will follow.", 3); $self['error'] = "ERROR => You must change the parent DNS A record to the new view. This record will follow."; return array(5, $self['error'] . "\n"); } $SET['dns_view_id'] = $dnsview['id']; $check_dns_view_id = $dnsview['id']; $changingview = 1; } } // Checking the IP setting first to estabilish if we are changing the IP so I can check the new combo of A/ip later if ($options['set_ip'] and $options['set_ip'] != '0.0.0.0') { // find the IP interface record, to ensure it is valid list($status, $rows, $interface) = ona_find_interface($options['set_ip']); if (!$rows) { printmsg("ERROR => dns_record_modify() Unable to find IP interface: {$options['set_ip']}", 3); $self['error'] = "ERROR => dns_record_modify() Unable to find IP interface: {$options['set_ip']}\n"; return array(4, $self['error']); } // If they actually changed the ip address if ($interface['id'] != $dns['interface_id']) { // check for child records that would match our new values // I think they will always be just PTR records so I am only selecting that type for now? list($status, $rows, $dnschild) = ona_get_dns_record(array('dns_id' => $dns['id'], 'interface_id' => $interface['id'], 'type' => 'PTR')); if ($rows) { printmsg("ERROR => dns_record_modify() This change results in a duplicate child DNS record: PTR {$options['set_ip']}. Delete existing PTR record first.", 3); $self['error'] = "<br>ERROR => dns_record_modify() This change results in a duplicate child DNS record: PTR {$options['set_ip']}.<br> Delete existing PTR record first.\n"; return array(4, $self['error']); } $changingint = 1; $SET['interface_id'] = $interface['id']; // get the info on the original interface list($status, $rows, $origint) = ona_get_interface_record(array('id' => $dns['interface_id'])); } } // Set options['set_name']? // Validate that the DNS name has only valid characters in it if ($options['set_name']) { // If we are specifically passing in a domain, use its value. If we dont have a domain // then try to find it in the name that we are setting. if ($options['set_domain']) { // Find the domain name piece of $search list($status, $rows, $domain) = ona_find_domain($options['set_domain'], 0); } else { list($status, $rows, $domain) = ona_find_domain($options['set_name'], 0); } // Find the domain name piece of $search if (!isset($domain['id'])) { printmsg("ERROR => Unable to determine domain name portion of ({$options['set_name']})!", 3); $self['error'] = "ERROR => Unable to determine domain name portion of ({$options['set_name']})!"; return array(3, $self['error'] . "\n"); } printmsg("DEBUG => ona_find_domain({$options['set_name']}) returned: {$domain['fqdn']} for new name.", 3); // Now find what the host part of $search is $hostname = str_replace(".{$domain['fqdn']}", '', $options['set_name']); // Validate that the DNS name has only valid characters in it $hostname = sanitize_hostname($hostname); if (!$hostname) { printmsg("DEBUG => Invalid host name ({$options['set_name']})!", 3); $self['error'] = "ERROR => Invalid host name ({$options['set_name']})!"; return array(4, $self['error'] . "\n"); } // If the hostname we came up with and the domain name are the same, then assume this is // meant to be a domain specific record, like A, MX, NS type records. if ($hostname == $domain['fqdn']) { $hostname = ''; } // Debugging printmsg("DEBUG => Using hostname: {$hostname}.{$domain['fqdn']}, Domain ID: {$domain['id']}", 3); // if it is an a record and we are changing the name.. make sure there is not already an A with that name/ip combo if ($dns['type'] == 'A') { // If we are changing the interface id as determined above, check using that value if ($changingint) { $dns['interface_id'] = $SET['interface_id']; } list($status, $rows, $tmp) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'], 'interface_id' => $dns['interface_id'], 'type' => 'A', 'dns_view_id' => $check_dns_view_id)); if ($rows) { if ($tmp['id'] != $dns['id'] or $rows > 1) { printmsg("ERROR => There is already an A record with that name and IP address!{$viewmsg}", 3); $self['error'] = "ERROR => There is already an A record with that name and IP address!{$viewmsg}"; return array(5, $self['error'] . "\n"); } } } // make sure that name/pointsto combo doesnt already exist if ($dns['type'] == 'CNAME' or $dns['type'] == 'MX' or $dns['type'] == 'NS' or $dns['type'] == 'SRV') { list($status, $rows, $tmp) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'], 'dns_id' => $dns['dns_id'], 'type' => $dns['type'], 'dns_view_id' => $check_dns_view_id)); if ($rows) { if ($tmp['id'] != $dns['id'] or $rows > 1) { printmsg("ERROR => There is already a {$dns['type']} with that name pointing to that A record!{$viewmsg}", 3); $self['error'] = "ERROR => There is already a {$dns['type']} with that name pointing to that A record!{$viewmsg}"; return array(6, $self['error'] . "\n"); } } } if ($dns['type'] == 'CNAME') { // if it is a CNAME, make sure the new name is not an A record name already list($status, $rows, $tmp) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'], 'type' => 'A', 'dns_view_id' => $check_dns_view_id)); if ($status or $rows) { printmsg("ERROR => There is already an A record with that name!{$viewmsg}", 3); $self['error'] = "ERROR => There is already an A record with that name!{$viewmsg}"; return array(7, $self['error'] . "\n"); } } // lets try and determine the interface record using the name passed in. Only works if we get one record back // this is all to help associate if it can so that when the A record is removed, so is this TXT record. if ($dns['type'] == 'TXT') { // if we are dealing with a change to a domain only.. then blank the interface id and dns_id if ($hostname == '') { $SET['interface_id'] = ''; $SET['dns_id'] = ''; } else { list($status, $rows, $hostint) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'], 'type' => 'A', 'dns_view_id' => $check_dns_view_id)); if ($rows == 1) { $SET['interface_id'] = $hostint['interface_id']; $SET['dns_id'] = $hostint['id']; $SET['name'] = $hostname; } } } // If you have actually changed the name from what it was, set the new variable $SET if ($dns['name'] != $hostname) { $SET['name'] = $hostname; } if ($dns['domain_id'] != $domain['id']) { $SET['domain_id'] = $domain['id']; } } // If we are modifying a pointsto option if (array_key_exists('set_pointsto', $options) and ($options['set_type'] == 'CNAME' or $options['set_type'] == 'MX' or $options['set_type'] == 'NS' or $options['set_type'] == 'SRV')) { // Determine the host and domain name portions of the pointsto option // Find the domain name piece of $search list($status, $rows, $pdomain) = ona_find_domain($options['set_pointsto']); printmsg("DEBUG => ona_find_domain({$options['set_pointsto']}) returned: {$domain['fqdn']} for pointsto.", 3); // Now find what the host part of $search is $phostname = str_replace(".{$pdomain['fqdn']}", '', $options['set_pointsto']); // Validate that the DNS name has only valid characters in it $phostname = sanitize_hostname($phostname); if (!$phostname) { printmsg("DEBUG => Invalid pointsto host name ({$options['set_pointsto']})!", 3); $self['error'] = "ERROR => Invalid pointsto host name ({$options['set_pointsto']})!"; return array(4, $self['error'] . "\n"); } // Debugging printmsg("DEBUG => Using 'pointsto' hostname: {$phostname}.{$pdomain['fqdn']}, Domain ID: {$pdomain['id']}", 3); // Find the dns record that it will point to list($status, $rows, $pointsto_record) = ona_get_dns_record(array('name' => $phostname, 'domain_id' => $pdomain['id'], 'type' => 'A', 'dns_view_id' => $check_dns_view_id)); if ($status or !$rows) { printmsg("ERROR => Unable to find DNS A record to point {$options['set_type']} entry to!{$viewmsg}", 3); $self['error'] = "ERROR => Unable to find DNS A record to point {$options['set_type']} entry to!{$viewmsg}"; return array(5, $self['error'] . "\n"); } // Validate that there are no entries already pointed to the new A record list($c_status, $c_rows, $c_record) = ona_get_dns_record(array('name' => $dns['name'], 'domain_id' => $dns['domain_id'], 'dns_id' => $pointsto_record['id'], 'type' => $options['set_type'], 'dns_view_id' => $check_dns_view_id)); if ($c_record['id'] != $dns['id'] and $c_rows) { printmsg("ERROR => Another DNS {$options['set_type']} record exists with the values you've selected!{$viewmsg}", 3); $self['error'] = "ERROR => Another DNS {$options['set_type']} record exists with the values you've selected!{$viewmsg}"; return array(5, $self['error'] . "\n"); } $SET['dns_id'] = $pointsto_record['id']; $SET['interface_id'] = $pointsto_record['interface_id']; } // Set options['set_notes'] (it can be a null string!) if (array_key_exists('set_notes', $options)) { // There is an issue with escaping '=' and '&'. We need to avoid adding escape characters $options['set_notes'] = str_replace('\\=', '=', $options['set_notes']); $options['set_notes'] = str_replace('\\&', '&', $options['set_notes']); // If it changed... if ($dns['notes'] != $options['set_notes']) { $SET['notes'] = $options['set_notes']; } } // Check the date formatting etc if (isset($options['set_ebegin']) and $options['set_ebegin'] != $dns['ebegin']) { // format the time that was passed in for the database, leave it as 0 if they pass it as 0 $options['set_ebegin'] = $options['set_ebegin'] == '0' ? 0 : date('Y-m-j G:i:s', strtotime($options['set_ebegin'])); // Force the SET variable if its ont 0 and the current record is not 0000:00:00 00:00 if (!($options['set_ebegin'] == '0' and $dns['ebegin'] == '0000-00-00 00:00:00')) { $SET['ebegin'] = $options['set_ebegin']; } } else { // If I got no date, use right now as the date/time $options['set_ebegin'] = date('Y-m-j G:i:s'); } // Add the remaining items to the $SET variable // if there is a ttl setting and it is not the same as the existing record if (array_key_exists('set_ttl', $options) and $options['set_ttl'] != $dns['ttl']) { $SET['ttl'] = $options['set_ttl']; } if (array_key_exists('set_mx_preference', $options) and $options['set_mx_preference'] != $dns['mx_preference']) { $SET['mx_preference'] = $options['set_mx_preference']; } if (array_key_exists('set_srv_pri', $options) and $options['set_srv_pri'] != $dns['srv_pri']) { $SET['srv_pri'] = $options['set_srv_pri']; } if (array_key_exists('set_srv_weight', $options) and $options['set_srv_weight'] != $dns['srv_weight']) { $SET['srv_weight'] = $options['set_srv_weight']; } if (array_key_exists('set_srv_port', $options) and $options['set_srv_port'] != $dns['srv_port']) { $SET['srv_port'] = $options['set_srv_port']; } if (array_key_exists('set_txt', $options)) { // There is an issue with escaping '=' and '&'. We need to avoid adding escape characters $options['set_txt'] = str_replace('\\=', '=', $options['set_txt']); $options['set_txt'] = str_replace('\\&', '&', $options['set_txt']); // If it changed... if ($dns['txt'] != $options['set_txt']) { $SET['txt'] = $options['set_txt']; } } // If it is an A record and they have specified to auto add the PTR record for it. if ($options['set_addptr'] == 'Y' and $options['set_type'] == 'A') { printmsg("DEBUG => Auto adding a PTR record for {$options['set_name']}.", 0); // Run dns_record_add as a PTR type // Always use the $current_name variable as the name might change during the update list($status, $output) = run_module('dns_record_add', array('name' => $current_name, 'domain' => $domain['fqdn'], 'ip' => $options['set_ip'], 'ebegin' => $options['set_ebegin'], 'type' => 'PTR', 'view' => $check_dns_view_id)); if ($status) { return array($status, $output); } printmsg($text); } // Get the dns record before updating (logging) $original_record = $dns; // Update the host record if necessary //if(count($SET) > 0 and $options['set_ebegin'] != $dns['ebegin']) { if (count($SET) > 0) { // Use the ebegin value set above $SET['ebegin'] = $options['set_ebegin']; // If we are changing the interface id as determined above, check using that value if ($changingint) { // If the interface id has changed, make sure any child records are updated first if ($SET['interface_id'] != $current_int_id) { printmsg("DEBUG = > dns_record_modify() Updating child interfaces to new interface.", 2); list($status, $rows) = db_update_record($onadb, 'dns', array('dns_id' => $dns['id'], 'interface_id' => $current_int_id), array('interface_id' => $SET['interface_id'])); if ($status) { $self['error'] = "ERROR => dns_record_modify() SQL Query failed for dns record: " . $self['error']; printmsg($self['error'], 0); return array(11, $self['error'] . "\n"); } // TODO: may need set rebuild flag on each of the domains related to these child records that just changed } // Check the PTR record has the proper domain still $ipflip = ip_mangle($interface['ip_addr_text'], 'flip'); $octets = explode(".", $ipflip); if (count($octets) > 4) { $arpa = '.ip6.arpa'; $octcount = 31; } else { $arpa = '.in-addr.arpa'; $octcount = 3; } // Find a pointer zone for this record to associate with. list($status, $prows, $ptrdomain) = ona_find_domain($ipflip . $arpa); list($status, $drrows, $dnsrec) = ona_get_dns_record(array('type' => 'PTR', 'interface_id' => $SET['interface_id'], 'dns_view_id' => $check_dns_view_id)); // TRIGGER: we made a change and need to update the CURRENT PTR record as well, only sets it if the ptrdomain changes list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $dnsrec['domain_id']), array('rebuild_flag' => 1)); if ($status) { $self['error'] = "ERROR => dns_record_add() Unable to update rebuild flags for domain.: {$self['error']}"; printmsg($self['error'], 0); return array(7, $self['error'] . "\n"); } // if we find any PTR records and the domain has chaned, make sure the child PTR records have the updated PTR domain info. if (isset($ptrdomain['id']) and $drrows > 0 and $dnsrec['domain_id'] != $ptrdomain['id']) { list($status, $rows) = db_update_record($onadb, 'dns', array('id' => $dnsrec['id']), array('domain_id' => $ptrdomain['id'], 'ebegin' => $SET['ebegin'])); if ($status or !$rows) { $self['error'] = "ERROR => dns_record_modify() Child PTR record domain update failed: " . $self['error']; printmsg($self['error'], 0); return array(14, $self['error'] . "\n"); } // TRIGGER: we made a change and need to update the NEW PTR record as well, only sets it if the ptrdomain changes list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $ptrdomain['id']), array('rebuild_flag' => 1)); if ($status) { $self['error'] = "ERROR => dns_record_add() Unable to update rebuild flags for domain.: {$self['error']}"; printmsg($self['error'], 0); return array(7, $self['error'] . "\n"); } } } // If we are changing the view, we must change all other DNS records that point to this one to the same view. if ($changingview) { if ($SET['dns_view_id'] != $current_dns_view_id) { printmsg("DEBUG = > dns_record_modify() Updating child DNS records to new dns view.", 2); list($status, $rows) = db_update_record($onadb, 'dns', array('dns_id' => $dns['id']), array('dns_view_id' => $SET['dns_view_id'])); if ($status) { $self['error'] = "ERROR => dns_record_modify() SQL Query failed for dns record child view updates: " . $self['error']; printmsg($self['error'], 0); return array(11, $self['error'] . "\n"); } } // TRIGGER: yep I probably need one here FIXME } // Make sure we us A type for both A and AAAA if ($SET['type'] == 'AAAA') { $SET['type'] = 'A'; } // Change the actual DNS record list($status, $rows) = db_update_record($onadb, 'dns', array('id' => $dns['id']), $SET); if ($status or !$rows) { $self['error'] = "ERROR => dns_record_modify() SQL Query failed for dns record: " . $self['error']; printmsg($self['error'], 0); return array(12, $self['error'] . "\n"); } // TRIGGER: we made a change, lets mark the domain for rebuild on its servers list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $dns['domain_id']), array('rebuild_flag' => 1)); if ($status) { $self['error'] = "ERROR => dns_record_add() Unable to update rebuild flags for domain.: {$self['error']}"; printmsg($self['error'], 0); return array(7, $self['error'] . "\n"); } // TRIGGER: If we are changing domains, lets flag the new domain as well, lets mark the domain for rebuild on its servers if ($SET['domain_id']) { list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $SET['domain_id']), array('rebuild_flag' => 1)); if ($status) { $self['error'] = "ERROR => dns_record_add() Unable to update rebuild flags for domain.: {$self['error']}"; printmsg($self['error'], 0); return array(7, $self['error'] . "\n"); } } } // Get the host record after updating (logging) list($status, $rows, $new_record) = ona_get_dns_record(array('id' => $dns['id'])); // Return the success notice $self['error'] = "INFO => DNS record UPDATED:{$dns['id']}: {$new_record['fqdn']}"; $log_msg = "INFO => DNS record UPDATED:{$dns['id']}: "; $more = ''; foreach (array_keys($original_record) as $key) { if ($original_record[$key] != $new_record[$key]) { $log_msg .= $more . $key . "[" . $original_record[$key] . "=>" . $new_record[$key] . "]"; $more = "; "; } } // only print to logfile if a change has been made to the record if ($more != '') { printmsg($log_msg, 0); } return array(0, $self['error'] . "\n"); }
function ws_display_list($window_name, $form = '') { global $conf, $self, $onadb; global $images, $color, $style; $html = ''; $js = ''; // If the user supplied an array in a string, transform it into an array $form = parse_options_string($form); // Find the "tab" we're on $tab = $_SESSION['ona'][$form['form_id']]['tab']; // Build js to refresh this list $refresh = "xajax_window_submit('{$window_name}', xajax.getFormValues('{$form['form_id']}'), 'display_list');"; // If it's not a new query, load the previous query from the session // into $form and save the current page and filter in the session. // Also find/set the "page" we're viewing $page = 1; if ($form['page'] and is_numeric($form['page'])) { $form = array_merge($form, (array) $_SESSION['ona'][$form['form_id']][$tab]['q']); $_SESSION['ona'][$form['form_id']][$tab]['page'] = $page = $form['page']; $_SESSION['ona'][$form['form_id']][$tab]['filter'] = $form['filter']; } printmsg("DEBUG => Displaying records list page: {$page}", 1); // Calculate the SQL query offset (based on the page being displayed) $offset = $conf['search_results_per_page'] * ($page - 1); if ($offset == 0) { $offset = -1; } // Search results go in here $results = array(); $count = 0; // // *** ADVANCED RECORD SEARCH *** // FIND RESULT SET // // Start building the "where" clause for the sql query to find the records to display $where = ""; $and = ""; $orderby = ""; // enable or disable wildcards $wildcard = '%'; if ($form['nowildcard']) { $wildcard = ''; } // RECORD ID if ($form['record_id']) { $where .= $and . "id = " . $onadb->qstr($form['record_id']); $and = " AND "; } // DNS VIEW ID if ($form['dns_view']) { if (is_string($form['dns_view'])) { list($status, $rows, $dnsview) = ona_get_dns_view_record(array('name' => $form['dns_view'])); } if (is_numeric($form['dns_view'])) { list($status, $rows, $dnsview) = ona_get_dns_view_record(array('id' => $form['dns_view'])); } $where .= $and . "dns_view_id = " . $onadb->qstr($dnsview['id']); $and = " AND "; } // INTERFACE ID if ($form['interface_id']) { $where .= $and . "interface_id = " . $onadb->qstr($form['interface_id']); $and = " AND "; } // DNS RECORD note if ($form['notes']) { $where .= $and . "notes LIKE " . $onadb->qstr($wildcard . $form['notes'] . $wildcard); $and = " AND "; } // DNS RECORD TYPE if ($form['dnstype']) { $where .= $and . "type = " . $onadb->qstr($form['dnstype']); $and = " AND "; } // HOSTNAME if ($form['hostname']) { $where .= $and . "id IN (SELECT id " . " FROM dns " . " WHERE name LIKE " . $onadb->qstr($wildcard . $form['hostname'] . $wildcard) . " )"; $and = " AND "; } // DOMAIN if ($form['domain']) { // FIXME: MP test if this clause works correctly? Not sure that anything even uses this? list($status, $rows, $tmpdomain) = ona_find_domain($form['domain']); $where .= $and . "domain_id = " . $onadb->qstr($tmpdomain['id']); $orderby .= "name, domain_id"; $and = " AND "; } // DOMAIN ID if ($form['domain_id']) { //$where .= $and . "primary_dns_id IN ( SELECT id " . // " FROM dns " . // " WHERE domain_id = " . $onadb->qstr($form['domain_id']) . " ) "; $where .= $and . "domain_id = " . $onadb->qstr($form['domain_id']); $orderby .= "name, domain_id"; $and = " AND "; } // IP ADDRESS $ip = $ip_end = ''; if ($form['ip']) { // Build $ip and $ip_end from $form['ip'] and $form['ip_thru'] $ip = ip_complete($form['ip'], '0'); if ($form['ip_thru']) { $ip_end = ip_complete($form['ip_thru'], '255'); } else { $ip_end = ip_complete($form['ip'], '255'); } // Find out if $ip and $ip_end are valid $ip = ip_mangle($ip, 'numeric'); $ip_end = ip_mangle($ip_end, 'numeric'); if ($ip != -1 and $ip_end != -1) { // We do a sub-select to find interface id's between the specified ranges $where .= $and . "interface_id IN ( SELECT id " . " FROM interfaces " . " WHERE ip_addr >= " . $onadb->qstr($ip) . " AND ip_addr <= " . $onadb->qstr($ip_end) . " )"; $and = " AND "; } } // display a nice message when we dont find all the records if ($where == '' and $form['content_id'] == 'search_results_list') { $js .= "el('search_results_msg').innerHTML = 'Unable to find DNS records matching your query, showing all records';"; } // Wild card .. if $while is still empty, add a 'ID > 0' to it so you see everything. if ($where == '') { $where = 'id > 0'; } // If we dont have DNS views turned on, limit data to just the default view. // Even if there is data associated with other views, ignore it if (!$conf['dns_views']) { $where .= ' AND dns_view_id = 0'; } // Do the SQL Query $filter = ''; if ($form['filter']) { // Host names should always be lower case $form['filter'] = strtolower($form['filter']); $filter = ' AND name LIKE ' . $onadb->qstr('%' . $form['filter'] . '%'); } // If we get a specific host to look for we must do the following // 1. get (A) records that match any interface_id associated with the host // 2. get CNAMES that point to dns records that are using an interface_id associated with the host if ($form['host_id']) { // If we dont have DNS views turned on, limit data to just the default view. // Even if there is data associated with other views, ignore it // MP: something strange with this, it should only limit to default view.. sometimes it does not??? if (!$conf['dns_views']) { $hwhere .= 'dns_view_id = 0 AND '; } // Get the host record so we know what the primary interface is list($status, $rows, $host) = ona_get_host_record(array('id' => $form['host_id']), ''); list($status, $rows, $results) = db_get_records($onadb, 'dns', $hwhere . 'interface_id in (select id from interfaces where host_id = ' . $onadb->qstr($form['host_id']) . ') OR interface_id in (select interface_id from interface_clusters where host_id = ' . $onadb->qstr($form['host_id']) . ')', "type", $conf['search_results_per_page'], $offset); // If we got less than search_results_per_page, add the current offset to it // so that if we're on the last page $rows still has the right number in it. if ($rows > 0 and $rows < $conf['search_results_per_page']) { $rows += $conf['search_results_per_page'] * ($page - 1); } else { if ($rows >= $conf['search_results_per_page']) { list($status, $rows, $records) = db_get_records($onadb, 'dns', $hwhere . 'interface_id in (select id from interfaces where host_id = ' . $onadb->qstr($form['host_id']) . ') OR interface_id in (select interface_id from interface_clusters where host_id = ' . $onadb->qstr($form['host_id']) . ')' . $filter, "", 0); } } } else { list($status, $rows, $results) = db_get_records($onadb, 'dns', $where . $filter, $orderby, $conf['search_results_per_page'], $offset); // If we got less than search_results_per_page, add the current offset to it // so that if we're on the last page $rows still has the right number in it. if ($rows > 0 and $rows < $conf['search_results_per_page']) { $rows += $conf['search_results_per_page'] * ($page - 1); } else { if ($rows >= $conf['search_results_per_page']) { list($status, $rows, $records) = db_get_records($onadb, 'dns', $where . $filter, "", 0); } } } $count = $rows; // // *** BUILD HTML LIST *** // $html .= <<<EOL <!-- dns record Results --> <table id="{$form['form_id']}_dns_record_list" class="list-box" cellspacing="0" border="0" cellpadding="0"> <!-- Table Header --> <tr> <td colspan="2" class="list-header" align="center" style="{$style['borderR']};">Name</td> <td class="list-header" align="center" style="{$style['borderR']};">Time to Live</td> <td class="list-header" align="center" style="{$style['borderR']};">Type</td> <td class="list-header" align="center" style="{$style['borderR']};">Data</td> <td class="list-header" align="center" style="{$style['borderR']};">Effective</td> EOL; if ($conf['dns_views']) { $html .= "<td class=\"list-header\" align=\"center\" style=\"{$style['borderR']};\">DNS View</td>"; } $html .= <<<EOL <td class="list-header" align="center" style="{$style['borderR']};">Notes</td> <td class="list-header" align="center"> </td> </tr> EOL; // Loop and display each record // $last_record = array('name' => $results[0]['name'], 'domain_id' => $results[0]['domain_id']); // $last_record_count = 0; for ($i = 1; $i <= count($results); $i++) { $record = $results[$i]; // Get additional info about each host record $record = $results[$i - 1]; // if the interface is the primary_dns_id for the host then mark it $primary_record = ' '; if ($host['primary_dns_id'] == $record['id']) { $primary_record = '<img title="Primary DNS record" src="' . $images . '/silk/font_go.png" border="0">'; } // Check for interface records (and find out how many there are) list($status, $interfaces, $interface) = ona_get_interface_record(array('id' => $record['interface_id']), ''); if ($interfaces) { // Get the host record so we know what the primary interface is //list($status, $rows, $inthost) = ona_get_host_record(array('id' => $interface['host_id']), ''); // Make the type correct based on the IP passed in if (strlen($interface['ip_addr']) > 11 and $record['type'] == 'A') { $record['type'] = 'AAAA'; } $record['ip_addr'] = ip_mangle($interface['ip_addr'], 'dotted'); // Subnet description list($status, $rows, $subnet) = ona_get_subnet_record(array('id' => $interface['subnet_id'])); $record['subnet'] = $subnet['name']; $record['ip_mask'] = ip_mangle($subnet['ip_mask'], 'dotted'); $record['ip_mask_cidr'] = ip_mangle($subnet['ip_mask'], 'cidr'); // Create string to be embedded in HTML for display $data = <<<EOL {$record['ip_addr']} EOL; } else { // Get other DNS records which name this record as parent list($status, $rows, $dns_other) = ona_get_host_record(array('id' => $record['dns_id'])); // Create string to be embedded in HTML for display if ($rows) { $data = <<<EOL <a title="View host. ID: {$dns_other['id']}" class="nav" onClick="xajax_window_submit('work_space', 'xajax_window_submit(\\'display_host\\', \\'host_id=>{$dns_other['id']}\\', \\'display\\')');" >{$dns_other['name']}</a >.<a title="View domain. ID: {$dns_other['domain_id']}" class="domain" onClick="xajax_window_submit('work_space', 'xajax_window_submit(\\'display_domain\\', \\'domain_id=>{$dns_other['domain_id']}\\', \\'display\\')');" >{$dns_other['domain_fqdn']}</a> EOL; } } $record['notes_short'] = truncate($record['notes'], 30); // Add a dot to the end of record name for display purposes $record['name'] = $record['name'] . '.'; // Process PTR record if ($record['type'] == 'PTR') { list($status, $rows, $pointsto) = ona_get_dns_record(array('id' => $record['dns_id']), ''); list($status, $rows, $pdomain) = ona_get_domain_record(array('id' => $record['domain_id']), ''); // Flip the IP address $record['name'] = ip_mangle($record['ip_addr'], 'flip'); $record['domain'] = $pdomain['name']; if ($pdomain['parent_id']) { list($status, $rows, $parent) = ona_get_domain_record(array('id' => $pdomain['parent_id'])); $parent['name'] = ona_build_domain_name($parent['id']); $record['domain'] = $pdomain['name'] . '.' . $parent['name']; unset($parent['name']); } // strip down the IP to just the "host" part as it relates to the domain its in if (strstr($record['domain'], 'in-addr.arpa')) { $domain_part = preg_replace("/.in-addr.arpa\$/", '', $record['domain']); } else { $domain_part = preg_replace("/.ip6.arpa\$/", '', $record['domain']); } $record['name'] = preg_replace("/{$domain_part}\$/", '', $record['name']); $data = <<<EOL <a title="Edit DNS A record" class="act" onClick="xajax_window_submit('edit_record', 'dns_record_id=>{$record['dns_id']}', 'editor');" >{$pointsto['name']}</a>.<a title="View domain. ID: {$pointsto['domain_id']}" class="domain" onClick="xajax_window_submit('work_space', 'xajax_window_submit(\\'display_domain\\', \\'domain_id=>{$pointsto['domain_id']}\\', \\'display\\')');" >{$pointsto['domain_fqdn']}</a>. EOL; } // Process CNAME record if ($record['type'] == 'CNAME') { list($status, $rows, $cname) = ona_get_dns_record(array('id' => $record['dns_id']), ''); $data = <<<EOL <a title="Edit DNS A record" class="act" onClick="xajax_window_submit('edit_record', 'dns_record_id=>{$record['dns_id']}', 'editor');" >{$cname['name']}</a>.<a title="View domain. ID: {$cname['domain_id']}" class="domain" onClick="xajax_window_submit('work_space', 'xajax_window_submit(\\'display_domain\\', \\'domain_id=>{$cname['domain_id']}\\', \\'display\\')');" >{$cname['domain_fqdn']}</a>. EOL; } // Process NS record if ($record['type'] == 'NS') { // clear out the $record['domain'] value so it shows properly in the list $record['name'] = ''; list($status, $rows, $ns) = ona_get_dns_record(array('id' => $record['dns_id']), ''); $data = <<<EOL <a title="Edit DNS A record" class="act" onClick="xajax_window_submit('edit_record', 'dns_record_id=>{$record['dns_id']}', 'editor');" >{$ns['name']}</a>.<a title="View domain. ID: {$ns['domain_id']}" class="domain" onClick="xajax_window_submit('work_space', 'xajax_window_submit(\\'display_domain\\', \\'domain_id=>{$ns['domain_id']}\\', \\'display\\')');" >{$ns['domain_fqdn']}</a>. EOL; } // Process MX record if ($record['type'] == 'MX') { // show the preference value next to the type $record['type'] = "{$record['type']} ({$record['mx_preference']})"; list($status, $rows, $mx) = ona_get_dns_record(array('id' => $record['dns_id']), ''); $data = <<<EOL <a title="Edit DNS A record" class="act" onClick="xajax_window_submit('edit_record', 'dns_record_id=>{$record['dns_id']}', 'editor');" >{$mx['name']}</a>.<a title="View domain. ID: {$mx['domain_id']}" class="domain" onClick="xajax_window_submit('work_space', 'xajax_window_submit(\\'display_domain\\', \\'domain_id=>{$mx['domain_id']}\\', \\'display\\')');" >{$mx['domain_fqdn']}</a>. EOL; } // Process SRV record if ($record['type'] == 'SRV') { // show the preference value next to the type $record['type'] = "{$record['type']} ({$record['srv_port']})"; list($status, $rows, $srv) = ona_get_dns_record(array('id' => $record['dns_id']), ''); $data = <<<EOL <a title="Edit DNS A record" class="act" onClick="xajax_window_submit('edit_record', 'dns_record_id=>{$record['dns_id']}', 'editor');" >{$srv['name']}</a>.<a title="View domain. ID: {$srv['domain_id']}" class="domain" onClick="xajax_window_submit('work_space', 'xajax_window_submit(\\'display_domain\\', \\'domain_id=>{$srv['domain_id']}\\', \\'display\\')');" >{$srv['domain_fqdn']}</a>. EOL; } // Process TXT record if ($record['type'] == 'TXT') { // some records will have an interfaceid and dnsid when associated to another dns name // some will just be un associated txt records or domain only records. Determine that here and // display appropriately. This is to ensure associated DNS records match up if the name changes if ($record['interface_id'] and $record['dns_id']) { list($status, $rows, $txtmain) = ona_get_dns_record(array('id' => $record['dns_id']), ''); $record['name'] = $txtmain['name'] . '.'; } $data = truncate($record['txt'], 70); } // Get the domain name and domain ttl $ttl_style = 'title="Time-to-Live"'; list($status, $rows, $domain) = ona_get_domain_record(array('id' => $record['domain_id'])); // Make record['domain'] have the right name in it if ($record['type'] != 'PTR') { $record['domain'] = $domain['fqdn']; } // clear out the $record['domain'] value so it shows properly in the list for NS records if ($record['type'] == 'NS') { $record['domain'] = $domain['fqdn']; } // if the ttl is blank, use the one in the domain (minimum) if ($record['ttl'] == 0) { $record['ttl'] = $domain['default_ttl']; $ttl_style = 'style="font-style: italic;" title="Using TTL from domain"'; } // format the ebegin using the configured date format $ebegin = ''; // If it is in the future, print the time if (strtotime($record['ebegin']) > time()) { $ebegin = '<span title="Active in DNS on: ' . $record['ebegin'] . '">' . date($conf['date_format'], strtotime($record['ebegin'])) . '</span>'; } // If it is 0 then show as disabled if (strtotime($record['ebegin']) < 0) { $ebegin = <<<EOL <span style="background-color:#FFFF99;" title="Disabled: Won't build in DNS" onClick="var doit=confirm('Are you sure you want to enable this DNS record?'); if (doit == true) xajax_window_submit('edit_record', xajax.getFormValues('{$form['form_id']}_list_record_{$record['id']}'), 'enablerecord');" >Disabled</span> EOL; } // If we get this far and the name we have built has a leading . in it then remove the dot. $record['name'] = preg_replace("/^\\./", '', $record['name']); // Get the name of the view and the description if ($conf['dns_views']) { list($status, $rows, $dnsview) = ona_get_dns_view_record(array('id' => $record['dns_view_id'])); $record['view_name'] = $dnsview['name']; $record['view_desc'] = $dnsview['description']; } // Escape data for display in html foreach (array_keys($record) as $key) { $record[$key] = htmlentities($record[$key], ENT_QUOTES, $conf['php_charset']); } //$primary_object_js = "xajax_window_submit('work_space', 'xajax_window_submit(\'display_host\', \'host_id=>{$record['id']}\', \'display\')');"; $html .= <<<EOL <tr onMouseOver="this.className='row-highlight';" onMouseOut="this.className='row-normal';"> <td class="list-row" style="padding-right: 2px; padding-left: 4px;" width="16px"> {$primary_record} </td> <td class="list-row"> <span title="Record. ID: {$record['id']}" onClick="" >{$record['name']}</span ><a title="View domain. ID: {$domain['id']}" class="domain" onClick="xajax_window_submit('work_space', 'xajax_window_submit(\\'display_domain\\', \\'domain_id=>{$domain['id']}\\', \\'display\\')');" >{$record['domain']}.</a> </td> <td class="list-row"> <span onClick="" {$ttl_style} >{$record['ttl']} seconds</span> </td> <td class="list-row"> <span title="Record Type" onClick="" >{$record['type']}</span> </td> <td class="list-row" align="left"> EOL; // Put the data in! $html .= $data; $html .= <<<EOL </td> <td class="list-row" align="center"> {$ebegin} </td> EOL; // Display the view we are part of if ($conf['dns_views']) { $html .= <<<EOL <td class="list-row" align="center" title="{$record['view_desc']}"> {$record['view_name']} </td> EOL; } $html .= <<<EOL <td class="list-row"> <span title="{$record['notes']}">{$record['notes_short']}</span> </td> <!-- ACTION ICONS --> <td class="list-row" align="right"> <form id="{$form['form_id']}_list_record_{$record['id']}" ><input type="hidden" name="dns_record_id" value="{$record['id']}" ><input type="hidden" name="host_id" value="{$host['id']}" ><input type="hidden" name="js" value="{$refresh}" ></form> EOL; if (auth('dns_record_modify')) { // If it is an A record but not the primary, display an option to make it primary. and only if we are dealing with a specific host if (($record['type'] == 'A' or $record['type'] == 'AAAA') and $host['primary_dns_id'] != $record['id'] and $form['host_id']) { $html .= <<<EOL <a title="Make this the primary DNS record" class="act" onClick="var doit=confirm('Are you sure you want to make this the primary DNS record for this host?'); if (doit == true) xajax_window_submit('edit_record', xajax.getFormValues('{$form['form_id']}_list_record_{$record['id']}'), 'makeprimary');" ><img src="{$images}/silk/font_go.png" border="0"></a> EOL; } } // display a view host button on the dns record search form list if ($form['search_form_id'] == 'dns_record_search_form') { $html .= <<<EOL <a title="View associated host record: {$interface['host_id']}" class="act" onClick="xajax_window_submit('display_host', 'host_id=>{$interface['host_id']}', 'display');" ><img src="{$images}/silk/computer_go.png" border="0"></a> EOL; } if (auth('dns_record_modify')) { $html .= <<<EOL <a title="Edit DNS record" class="act" onClick="xajax_window_submit('edit_record', xajax.getFormValues('{$form['form_id']}_list_record_{$record['id']}'), 'editor');" ><img src="{$images}/silk/page_edit.png" border="0"></a> EOL; } if (auth('dns_record_del')) { $html .= <<<EOL <a title="Delete DNS record" class="act" onClick="xajax_window_submit('edit_record', xajax.getFormValues('{$form['form_id']}_list_record_{$record['id']}'), 'delete');" ><img src="{$images}/silk/delete.png" border="0"></a> EOL; } $html .= <<<EOL </td> </tr> EOL; // reset the record counter before we go back for the next iteration $last_record = array('name' => $record['name'], 'domain_id' => $record['domain_id']); $last_record_count = 1; } $html .= <<<EOL </table> EOL; // Build page links if there are any $html .= get_page_links($page, $conf['search_results_per_page'], $count, $window_name, $form['form_id']); // Insert the new html into the content div specified // Instantiate the xajaxResponse object $response = new xajaxResponse(); $response->addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); $response->addAssign($form['content_id'], "innerHTML", $html); if ($js) { $response->addScript($js); } return $response->getXML(); }