diff options
Diffstat (limited to 'config/tinydns/tinydns.inc')
-rw-r--r-- | config/tinydns/tinydns.inc | 964 |
1 files changed, 964 insertions, 0 deletions
diff --git a/config/tinydns/tinydns.inc b/config/tinydns/tinydns.inc new file mode 100644 index 00000000..24de1cab --- /dev/null +++ b/config/tinydns/tinydns.inc @@ -0,0 +1,964 @@ +<?php + +/* $Id$ */ +/* + tinydns.inc + Copyright (C) 2006, 2007, 2008 Scott Ullrich + Parts Copyright (C) 2007 Goffredo Andreone + part of pfSense + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +require_once("filter.inc"); + +function tinydns_custom_php_install_command() { + global $g, $config; + conf_mount_rw(); + $fd = fopen("/usr/local/etc/rc.d/svscan.sh", "w"); + if(!$fd) { + log_error("Could not open /usr/local/etc/rc.d/svscan.sh for writing."); + return; + } + $ipaddress = $config['installedpackages']['tinydns']['config'][0]['ipaddress']; + + $minsegment = "10240"; + $maxfilesize = "10240"; + $maxsegment = "20480"; + $maxfd = "100"; + $maxchild = "40"; + + if($config['installedpackages']['tinydns']['config'][0]['minsegment']) + $minsegment = $config['installedpackages']['tinydns']['config'][0]['minsegment']; + + if($config['installedpackages']['tinydns']['config'][0]['maxfilesize']) + $maxfilesize = $config['installedpackages']['tinydns']['config'][0]['maxfilesize']; + + if($config['installedpackages']['tinydns']['config'][0]['maxsegment']) + $maxsegment = $config['installedpackages']['tinydns']['config'][0]['maxsegment']; + + if($config['installedpackages']['tinydns']['config'][0]['maxfd']) + $maxfd = $config['installedpackages']['tinydns']['config'][0]['maxfd']; + + if($config['installedpackages']['tinydns']['config'][0]['maxchild']) + $maxchild = $config['installedpackages']['tinydns']['config'][0]['maxchild']; + + if($config['installedpackages']['tinydns']['config'][0]['refreshinterval']) + $refreshinterval = $config['installedpackages']['tinydns']['config'][0]['refreshinterval']; + + $svscan = <<<EOD +#!/bin/sh + +# PROVIDE: svscan +# REQUIRE: LOGIN +# KEYWORD: FreeBSD + +. /etc/rc.subr + +name="svscan" +rcvar=`set_rcvar` +command="/usr/local/bin/svscan" +svscan_enable=\${svscan_enable-"YES"} +svscan_servicedir=\${svscan_servicedir-"/service"} + +start_cmd="svscan_start" +stop_postcmd="svscan_stop_post" + +load_rc_config \$name + +required_dirs="\${svscan_servicedir}" + +svscan_start () { + echo "Starting svscan." + /usr/bin/env \ + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ + /usr/sbin/daemon -f /bin/sh -c "\$command \$svscan_servicedir 2>&1 | /usr/local/bin/readproctitle service errors: ................................................................................................................................................................................................................................................................................................................................................................................................................ &" > /dev/null + minicron {$refreshinterval} /var/run/ping_hosts.pid "/etc/ping_hosts.sh; cd /etc/tinydns/root && /usr/local/bin/tinydns-data" +} + +svscan_stop_post () { + echo "Stopping svscan." + find -L "\$svscan_servicedir" -mindepth 1 -maxdepth 2 -type d \( \! -path "\$svscan_servicedir/*/*" -or -name 'log' \) -print0 | xargs -0 /usr/local/bin/svc -dx + PIDTOKILL=`cat /var/run/ping_hosts.pid` + kill $PIDTOKILL +} + +run_rc_command "\$1" + +EOD; + + fwrite($fd, $svscan); + fclose($fd); + conf_mount_ro(); + filter_configure(); + + tinydns_custom_php_changeip_command(); + + exec("/usr/local/etc/rc.d/svscan.sh start"); +} + +function tinydns_custom_php_deinstall_command() { + global $g, $config; + conf_mount_rw(); + /* destroy all daemontools items */ + exec("/usr/sbin/pw groupdel Gtinydns"); + exec("/usr/sbin/pw groupdel Gdnscache"); + exec("/usr/sbin/pw groupdel Gdnslog"); + exec("/usr/sbin/pw userdel Gtinydns"); + exec("/usr/sbin/pw userdel Gdnscache"); + exec("/usr/sbin/pw userdel Gdnslog"); + exec("/usr/sbin/pw groupdel Gaxfrdns"); + exec("rm /usr/local/www/*tinydns*"); + exec("rm /usr/local/pkg/*tinydns*"); + exec("rm /usr/local/pkg/pf/*tinydns*"); + conf_mount_ro(); + filter_configure(); +} + +function tinydns_custom_php_changeip_command() { + global $g, $config; + conf_mount_rw(); + + $ip = $config['interfaces']['lan']['ipaddr']; + $ipmask = $config['interfaces']['lan']['subnet']; + $arr = tinydns_get_ip_subnet_arpa($ip, $ipmask); + $dnscacheip = $ip; + $dnsuserip = $arr[0]; + + /* For now force $dnsserverip to to 127.0.0.1 unless a separate IP is specified */ + $localhost = "127.0.0.1"; + $dnsserverip = $localhost; + if($config['installedpackages']['tinydns']['config'][0]['ipaddress'] != $localhost AND $config['installedpackages']['tinydns']['config'][0]['ipaddress'] != "") + $dnsserverip = $config['installedpackages']['tinydns']['config'][0]['ipaddress']; + if($config['installedpackages']['tinydns']['config'][0]['regdhcpstatic'] OR $config['installedpackages']['tinydns']['config'][0]['regdhcp']) + $dnsserverip = $localhost; + $config['installedpackages']['tinydns']['config'][0]['ipaddress'] = $dnsserverip; + + $updatecron = $config['installedpackages']['tinydns']['config'][0]['updatecron']; + + /* Populate Zone Transfer array */ + $ztipaddress = populate_zt_array(); + + /* setup daemon tools service area */ + if(!is_dir("/service")) + exec("/bin/mkdir /service"); + + exec("/usr/sbin/pw useradd Gtinydns"); + exec("/usr/sbin/pw useradd Gdnslog"); + exec("/usr/sbin/pw useradd Gdnscache"); + exec("/usr/sbin/pw useradd Gaxfrdns"); + + /* TinyDNS Server */ + exec("/usr/local/bin/tinydns-conf Gtinydns Gdnslog /etc/tinydns {$dnsserverip}"); + exec("/bin/ln -s /etc/tinydns /service/"); + + /* AXFRDNS - Zone transfers */ + if(is_array($ztipaddress)) + exec("/usr/local/bin/axfrdns-conf Gaxfrdns Gdnslog /etc/axfrdns /etc/tinydns {$dnsserverip}"); + exec("/bin/ln -s /etc/axfrdns /service/"); + + exec("echo {$dnsserverip} > /etc/tinydns/env/IP"); + exec("/usr/bin/killall -9 tinydns"); + + if($config['installedpackages']['tinydns']['config'][0]['enableforwarding']) { + if(!is_dir("/service/dnscache")) { + exec("/usr/sbin/pw useradd Gdnscache"); + exec("/usr/local/bin/dnscache-conf Gdnscache Gdnslog /etc/dnscache {$dnscacheip}"); + exec("/bin/ln -s /etc/dnscache /service/"); + exec("/bin/cp /var/etc/resolv.conf /var/etc/resolv.conf.original"); + exec("/bin/cp /var/etc/resolv.conf /var/etc/resolv.conf.dnscache"); + } + exec("echo {$dnscacheip} > /etc/dnscache/env/IP"); + tinydns_dnscache_forwarding_servers(); + exec("touch /etc/dnscache/root/ip/{$dnsuserip}"); + tinydns_create_soa_domain_list($dnsserverip); + exec("echo domain {$config['system']['domain']} > /var/etc/resolv.conf"); + exec("echo nameserver {$dnscacheip} >> /var/etc/resolv.conf"); + exec("/usr/bin/killall -9 dnscache"); + } else { + if(file_exists("/var/etc/resolv.conf.original")) + exec("/bin/cp /var/etc/resolv.conf.original /var/etc/resolv.conf"); + if(is_dir("/etc/dnscache")) { + dnscache_use_root_servers(); + exec("/usr/bin/killall -9 dnscache"); + } + } + conf_mount_ro(); + filter_configure(); +} + +function populate_zt_array() { + global $g, $config; + /* Populate Zone Transfer array */ + if($config['installedpackages']['tinydns']['config'][0]['row']) { + $ztipaddress = array(); + foreach($config['installedpackages']['tinydns']['config'][0]['row'] as $zt) { + $tmp = array(); + $tmp['ztipaddress'] = $zt['ztipaddress']; + $tmp['dnszone'] = $zt['dnszone']; + $ztipaddress[] = $tmp; + } + } + return $ztipaddress; +} + +function tinydns_setup_axfrdns() { + global $g, $config; + /* Populate Zone Transfer array */ + $ztipaddress = populate_zt_array(); + if(!is_array($ztipaddress)) + return; + $fd = fopen("/etc/axfrdns/tcp","w"); + if(!$fd) { + log_error("Could not open /etc/axfrdns/tcp for writing"); + return; + } + foreach($ztipaddress as $zt) { + if($zt['ztipaddress'] && $zt['dnszone']) + $zonet = "{$zt['ztipaddress']}:allow"; + if($zt['dnszone'] <> "*") + $zonet .= ",AXFR=\"{$zt['dnszone']}\""; + fwrite($fd, $zone . "\n"); + } + fclose($fd); + // Recompile database + exec("cd /service/axfrdns && /usr/local/bin/tinydns-data"); +} + +function tinydns_get_record_status($record, $pingthreshold = "", $wanpingthreshold = "") { + global $g, $config; + if(file_exists("/var/db/pingstatus/{$record}")) { + $status = ""; + $status = file_get_contents("/var/db/pingstatus/{$record}"); + if(stristr($status,"DOWN")) + return "DOWN"; + } + if($pingthreshold) { + $current_ms = ""; + if(file_exists("var/db/pingmsstatus/$record")) + $current_ms = file_get_contents("/var/db/pingmsstatus/$record"); + if($pingthreshold > $current_ms) + return "DOWN"; + } + if($wanpingthreshold) { + $current_avg = ""; + if(file_exists("/var/db/wanaverage")) + $current_avg = file_get_contents("/var/db/wanaverage"); + if($wanpingthreshold > $current_avg) + return "DOWN"; + } + return "UP"; +} + +function tinydns_get_backup_record($record) { + global $g, $config; + if($config['installedpackages']['tinydnsdomains']) { + foreach($config['installedpackages']['tinydnsdomains']['config'] as $domain) { + if($domain['ipaddress'] == $record) { + /* if no failover host exists, simply return original record */ + if(!$domain['row']) + return $record; + foreach($domain['row'] as $row) { + $status = tinydns_get_record_status($row['failoverip']); + if($status == "UP") + return $row['failoverip']; + } + } + } + } + return $record; +} + +function tinydns_setup_ping_items() { + global $g, $config; + if(!$config['installedpackages']['tinydnsdomains']) + return; + $wanif = get_real_wan_interface(); + $ip = find_interface_ip($wanif); + conf_mount_rw(); + $processed = array(); + /* XXX: make this work with other packages */ + $fd = fopen("/var/db/pkgpinghosts", "w"); + if(!$fd) { + log_error("Could not open /var/db/pkgpinghosts for writing."); + return; + } + config_lock(); + /* write out each ip address so ping_hosts.sh can begin monitoring ip + * status and create a database of the status information that we can use. + */ + foreach($config['installedpackages']['tinydnsdomains']['config'] as $domain) { + if(!in_array($domain['ipaddress'], $processed)) { + fwrite($fd, $ip . "|" . $domain['ipaddress'] . "|1|/usr/local/pkg/tinydns_down.php|/usr/local/pkg/tinydns_up.php\n"); + $processed[] = $domain['ipaddress']; + } + if($domain['monitorip'] <> "") + $monitorip = $domain['monitorip']; + if($domain['row']) { + foreach($domain['row'] as $row) { + if($row['pingthreshold']) + $pingthreshold = $row['pingthreshold']; + else + $row['pingthreshold'] = ""; + if($row['monitorip']) { + if(!in_array($row['monitorip'], $processed)) { + fwrite($fd, $ip . "|" . $row['monitorip'] . "|1|/usr/local/pkg/tinydns_down.php|/usr/local/pkg/tinydns_up.php|{$pingthreshold}\n"); + $processed[] = $row['monitorip']; + } + } else { + if(!in_array($monitorip, $processed)) { + fwrite($fd, $ip . "|" . $monitorip . "|1|/usr/local/pkg/tinydns_down.php|/usr/local/pkg/tinydns_up.php|{$pingthreshold}\n"); + $processed[] = $monitorip; + } + } + } + } + if($domain['monitorip']) { + if(!in_array($domain['monitorip'], $processed)) { + fwrite($fd, $ip . "|" . $domain['monitorip'] . "|1|/usr/local/pkg/tinydns_down.php|/usr/local/pkg/tinydns_up.php|{$pingthreshold}\n"); + $processed[] = $domain['monitorip']; + } + } else { + if(!in_array($row['failoverip'], $processed)) { + fwrite($fd, $ip . "|" . $row['failoverip'] . "|1|/usr/local/pkg/tinydns_down.php|/usr/local/pkg/tinydns_up.php|{$pingthreshold}\n"); + $processed[] = $row['failoverip']; + } + } + } + fclose($fd); + config_unlock(); + conf_mount_ro(); +} + +function tinydns_create_zone_file() { + global $g, $config; + conf_mount_rw(); + if(file_exists("/tmp/config.cache")) + unlink("/tmp/config.cache"); + parse_config(true); + config_lock(); + if(file_exists("/service/tinydns/root/data")) + exec("rm -f /service/tinydns/root/data"); + if(!is_dir("/service/tinydns/root")) + return; + $fd = fopen("/service/tinydns/root/data", "w"); + if(!$fd) { + log_error("Could not open /service/tinydns/root/data for writing."); + return; + } + + /* For now do not allow registration of 'local' DNS data if tinyDNS not bound to 127.0.0.1 */ + if($config['installedpackages']['tinydns']['config'][0]['ipaddress'] == "127.0.0.1") { + /* Load the root servers if Forwarding is enabled */ + /* Register LAN IP and SOA Forward and Reverse DNS recors in TinyDNS Server*/ + if($config['installedpackages']['tinydns']['config'][0]['enableforwarding']) { + $forwardingservers = tinydns_register_root_servers(); + if($forwardingservers) + fwrite($fd, $forwardingservers); + if($config['system']['hostname']['domain']) { + $dhcpdhostname = $config['system']['hostname']; + if($config['dhcpd']['lan']) + $dhcpddomain = $config['system']['domain']; + $dhcpdlanip = $config['interfaces']['lan']['ipaddr']; + $dhcpdipmask = $config['interfaces']['lan']['subnet']; + $dhcpdfqdn = "{$dhcpdhostname}.{$dhcpddomain}"; + tinydns_complete_soa_record($fd, $dhcpdlanip, $dhcpdipmask, $dhcpdhostname, $dhcpddomain); + } + } + + /* Register Static IPs */ + if($config['installedpackages']['tinydns']['config'][0]['regdhcpstatic']) { + foreach($config['dhcpd'] as $zone_key => $zone ) { + $dhcpdhostname = $config['system']['hostname']; + if ($zone['ddnsdomain']) + $dhcpddomain = $zone['ddnsdomain']; + else + $dhcpddomain = $config['system']['domain']; + $dhcpdlanip = $config['interfaces'][$zone_key]['ipaddr']; + $dhcpdipmask = $config['interfaces'][$zone_key]['subnet']; + $dhcpdfqdn = "{$dhcpdhostname}.{$dhcpddomain}"; + tinydns_complete_soa_record($fd, $dhcpdlanip, $dhcpdipmask, $dhcpdhostname, $dhcpddomain); + + if(is_array($zone['staticmap'])) { + foreach($zone['staticmap'] as $dhcpdstatic) { + $dhcpdhostname = $dhcpdstatic['hostname']; + $dhcpdfqdn = "{$dhcpdhostname}.{$dhcpddomain}"; + $dhcpdlanip = $dhcpdstatic['ipaddr']; + $dhcpda = "={$dhcpdfqdn}:{$dhcpdlanip}"; + if($dhcpdhostname) + fwrite($fd, $dhcpda . "\n"); + } + } + } + } + + /* Register Dynamic IPs */ + if($config['installedpackages']['tinydns']['config'][0]['regdhcp']) { + $leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases"; + $fl = fopen($leasesfile, "r"); + if(!$fl) { + log_error("Could not open {$leasesfile} for reading."); + return; + } + tinydns_add_active_leases($fl,$fd, $dhcpddomain); + } + } + + if($config['installedpackages']['tinydnsdomains']) { + for($x=0; $x< count($config['installedpackages']['tinydnsdomains']['config']); $x++) { + $domain = $config['installedpackages']['tinydnsdomains']['config'][$x]; + $record_data = ""; + $hostname = $domain['hostname']; + $ipaddress = $domain['ipaddress']; + $ttl = $domain['ttl']; + /* check record status, if it is down request + * backup server if defined. + */ + if($domain['monitorip']) + $monitorip = $domain['monitorip']; + if($monitorip) { + $status = tinydns_get_record_status($monitorip); + if($status == "DOWN") { + if($debug) + log_error("$ipaddress monitor ip $monitorip is offline."); + $ipaddress = tinydns_get_backup_record($ipaddress); + if($debug) + log_error("tinydns_get_backup_record returned $ipaddress "); + } + } + $record_data = tinydns_get_rowline_data($ipaddress, $domain['recordtype'], $ttl, $hostname, $domain['rdns']); + if($record_data) + fwrite($fd, $record_data . "\n"); + /* process load balanced items */ + if($domain['row']) { + foreach($domain['row'] as $row) { + if($row['loadbalance']) { + if($row['pingthreshold']) + $pingthreshold = $row['pingthreshold']; + else + $pingthreshold = ""; + if($row['wanpingthreshold']) + $wanpingthreshold = $row['wanpingthreshold']; + else + $wanpingthreshold = ""; + $status = tinydns_get_record_status($row['failoverip'], $pingthreshold, $wanpingthreshold); + if($status == "DOWN") { + $record_data = tinydns_get_rowline_data($row['failoverip'], $domain['recordtype'], $ttl, $hostname, ""); + fwrite($fd, $record_data . "\n"); + } + } + } + } + } + } + fclose($fd); + /* tell tinydns to reload zone file */ + exec("cd /service/tinydns/root && /usr/local/bin/tinydns-data"); + config_unlock(); + conf_mount_ro(); +} + +function tinydns_sync_on_changes() { + global $g, $config; + $synconchanges = $config['installedpackages']['tinydnssync']['config'][0]['synconchanges']; + if(!$synconchanges) + return; + $sync_hosts = $config['installedpackages']['tinydnssync']['config']; + foreach($sync_hosts as $sh) { + $sync_to_ip = $sh['ipaddress']; + $password = $sh['password']; + if($password and $sync_to_ip) + tinydns_do_xmlrpc_sync($sync_to_ip, $password); + } +} + +function tinydns_do_xmlrpc_sync($sync_to_ip, $password) { + global $config, $g; + + if(!$password) + return; + + if(!$sync_to_ip) + return; + + $xmlrpc_sync_neighbor = $sync_to_ip; + if($config['system']['webgui']['protocol'] != "") { + $synchronizetoip = $config['system']['webgui']['protocol']; + $synchronizetoip .= "://"; + } + $port = $config['system']['webgui']['port']; + /* if port is empty lets rely on the protocol selection */ + if($port == "") { + if($config['system']['webgui']['protocol'] == "http") + $port = "80"; + else + $port = "443"; + } + $synchronizetoip .= $sync_to_ip; + + /* xml will hold the sections to sync */ + $xml = array(); + $xml['tinydnsdomains'] = $config['installedpackages']['tinydnsdomains']; + + /* assemble xmlrpc payload */ + $params = array( + XML_RPC_encode($password), + XML_RPC_encode($xml) + ); + + /* set a few variables needed for sync code borrowed from filter.inc */ + $url = $synchronizetoip; + log_error("Beginning TinyDNS XMLRPC sync to {$url}:{$port}."); + $method = 'pfsense.merge_installedpackages_section_xmlrpc'; + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials('admin', $password); + if($g['debug']) + $cli->setDebug(1); + /* send our XMLRPC message and timeout after 250 seconds */ + $resp = $cli->send($msg, "250"); + if(!$resp) { + $error = "A communications error occured while attempting tinydns XMLRPC sync with {$url}:{$port}."; + log_error($error); + file_notice("sync_settings", $error, "tinydns Settings Sync", ""); + } elseif($resp->faultCode()) { + $cli->setDebug(1); + $resp = $cli->send($msg, "250"); + $error = "An error code was received while attempting tinydns XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "tinydns Settings Sync", ""); + } else { + log_error("tinydns XMLRPC sync successfully completed with {$url}:{$port}."); + } + + /* tell tinydns to reload our settings on the destionation sync host. */ + $method = 'pfsense.exec_php'; + $execcmd = "require('/usr/local/pkg/tinydns.inc');\n"; + $execcmd .= "tinydns_custom_php_changeip_command();\n"; + $execcmd .= "tinydns_custom_php_install_command();\n"; + $execcmd .= "tinydns_create_zone_file();\n"; + $execcmd .= "tinydns_setup_ping_items();\n"; + + /* assemble xmlrpc payload */ + $params = array( + XML_RPC_encode($password), + XML_RPC_encode($execcmd) + ); + + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials('admin', $password); + $resp = $cli->send($msg, "250"); + if(!$resp) { + $error = "A communications error occured while attempting tinydns XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; + log_error($error); + file_notice("sync_settings", $error, "tinydns Settings Sync", ""); + } elseif($resp->faultCode()) { + $cli->setDebug(1); + $resp = $cli->send($msg, "250"); + $error = "An error code was received while attempting tinydns XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "tinydns Settings Sync", ""); + } else { + log_error("tinydns XMLRPC sync successfully completed with {$url}:{$port} (pfsense.exec_php)."); + } + + log_error("[tinydns] tinydns_xmlrpc_sync.php is ending."); +} + +/* formats data as a tinydns data row item */ +/* A full description of the data format is available at 'man tinydns-data' */ +function tinydns_get_rowline_data($recordip, $recordtype, $ttl, $hostname, $rdns) { + if($ttl) + $ttl_string = ":{$ttl}"; + else + $ttl_string = ""; + switch ($recordtype) { + case "SOA": + $record_data = ".{$hostname}::{$recordip}{$ttl_string}"; + break; + case "NS": + $record_data = "&{$hostname}:{$recordip}{$ttl_string}"; + break; + case "MX": + $record_data = "@{$hostname}:{$recordip}::{$ttl_string}"; + break; + case "PTR": + /* "^" creates "PTR" record only to allow reverse DNS */ + $record_data = "^{$hostname}:{$recordip}{$ttl_string}"; + break; + case "A": + /* "=" creates both "A" and "PTR" records to allow both forward and reverse DNS */ + if($rdns) + $record_data = "={$hostname}:{$recordip}{$ttl_string}"; + else + /* "+" creates "A" records only to allow forward DNS */ + $record_data = "+{$hostname}:{$recordip}{$ttl_string}"; + break; + case "CNAME": + $record_data = "C{$hostname}:{$recordip}{$ttl_string}"; + break; + case "TXT": + /* "'" creates "TXT" record that can be used for SPF */ + $record_data = "'{$hostname}:{$recordip}{$ttl_string}"; + break; + } + return $record_data; +} + +/* Returns the last IP byte and the Trimmed IP*/ +function tinydns_get_lastip_byte($ipsub) { + $len= strlen($ipsub); + $pos = strrpos($ipsub, "."); + $last_byte = ""; + if ($pos === false) { + $last_byte = $ipsub; + return array ($last_byte,$ipsub); + } + $last_byte = substr($ipsub,$pos + 1); + $ipsub = substr($ipsub,0,$pos); + return array ($last_byte,$ipsub); +} + +/* in-add.arpa IP calculated from D.C.B.A and Mask to A.B.C.D.in-addr.arpa */ +/* subnet IP calculated from A.B.C.D and Mask */ +function tinydns_get_ip_subnet_arpa($ip, $ipmask) { + $ipsub = $ip; + $arpaip = ""; + $array = tinydns_get_lastip_byte($ipsub); + $a = $array[0]; + $ipsub = $array[1]; + $array = tinydns_get_lastip_byte($ipsub); + $b = $array[0]; + $ipsub = $array[1]; + $array = tinydns_get_lastip_byte($ipsub); + $c = $array[0]; + $ipsub = $array[1]; + $array = tinydns_get_lastip_byte($ipsub); + $d = $array[0]; + $ipsub = $array[1]; + switch ($ipmask) { + case ($ipmask <= 32 AND $ipmask > 24): + $s = 32 - $ipmask; + $a >> $s; + $arpaip = "{$a}.{$b}.{$c}.{$d}.in-addr.arpa"; + $subnet = "{$d}.{$c}.{$b}.{$a}"; + break; + case ($ipmask <= 24 AND $ipmask > 16): + $s = 24 - $ipmask; + $b >> $s; + $arpaip = "{$b}.{$c}.{$d}.in-addr.arpa"; + $subnet = "{$d}.{$c}.{$b}"; + break; + case ($ipmask <= 16 AND $ipmask > 8): + $s = 16 - $ipmask; + $c >> $s; + $arpaip = "{$c}.{$d}.in-addr.arpa"; + $subnet = "{$d}.{$c}"; + break; + case ($ipmask <= 8 AND $ipmask > 0): + $s = 8 - $ipmask; + $d >> $s; + $arpaip = "{$d}.in-addr.arpa"; + $subnet = "{$d}"; + break; + } + return array($subnet,$arpaip); +} + +/* Create a Forward and a Reverse DNS (SOA, A, PTR) records for Fully Qualififed Domain Name*/ +function tinydns_complete_soa_record($fd, $ip, $ipmask, $nsname, $domain) { + $fqdn = "{$nsname}.{$domain}"; + $rip = tinydns_get_ip_subnet_arpa($ip, $ipmask); + $soa = ".{$domain}::{$fqdn}"; + $rsoa = ".{$rip[1]}::{$fqdn}"; + $a = "={$fqdn}:{$ip}"; + if($fqdn) + fwrite($fd, $soa . "\n"); + if($rip) + fwrite($fd, $rsoa . "\n"); + if($nsname) + fwrite($fd, $a . "\n"); +} + +/* Search for active leases in the dhcpd.leases file and add them to tinyDNS */ +/* Currently it will add duplicate leases that are ignored by thee tinyDNS server*/ +/* Should duplicate leases be purged by DCHCP server in a remove stale records operation? */ +function tinydns_add_active_leases($fl,$fd, $leasedomain) { + $i = 0; + $lip = strlen("lease") + 1; + $lis = strlen("binding state active"); + $lic = strlen("client-hostname"); + $leaseip = ""; + $leasestatus = ""; + $leasehostname = ""; + while (!feof($fl)) { + $leases = fgets($fl, 4096); + $discard = ($leases[0] == "#") OR ($leases[0] == "\n"); + if(!$discard) { + if($leaseip == "") { + if ($leaseip = strstr($leases,"lease")) { + $leaseip = substr($leaseip,$lip,strpos($leases,"{") - $lip - 1); + } + } + elseif($leasestatus == FALSE) { + if (stristr($leases,"binding state active")) { + $leasestatus = TRUE; + } + } + elseif($leasestatus == TRUE AND $leasehostname == "") { + if($leasehostname = stristr($leases,"client-hostname")) { + $qstrt = strpos($leasehostname,'"') + 1; + $qlen = strrpos($leasehostname,'"') - $qstrt; + $leasehostname = substr($leasehostname,$qstrt,$qlen); + } + } + if($leases[0] == "}") { + $leasefqdn = "{$leasehostname}.{$leasedomain}"; + $leasea = "={$leasefqdn}:{$leaseip}"; + if($leasehostname AND $leasestatus)fwrite($fd, $leasea . "\n"); + $leaseip = ""; + $leasehostname = ""; + $leasestatus = FALSE; + } + $i = $i + 1; + } + } + fclose($fl); + $leaselines = $i; +} + +function tinydns_get_dns_record_type($tinydnsrecord) { + $rtype = ""; + $rtype2 = ""; + $rdns = ""; + switch ($tinydnsrecord) { + case($tinydnsrecord[0] == "."): + $rtype = "SOA"; + $rtype2 = "NS"; + break; + case($tinydnsrecord[0] == "="): + $rtype = "A"; + $rtype2 = "PTR"; + $rdns = "on"; + break; + case($tinydnsrecord[0] == "+"): + $rtype = "A"; + break; + case($tinydnsrecord[0] == "@"): + $rtype = "MX"; + break; + case($tinydnsrecord[0] == "^"): + $rtype = "PTR"; + $rdns = "on"; + break; + case($tinydnsrecord[0] == "&"): + $rtype = "NS"; + break; + case($tinydnsrecord[0] == "'"): + $rtype = "TXT"; + break; + case($tinydnsrecord[0] == "C"): + $rtype = "CNAME"; + break; + case($tinydnsrecord[0] == "Z"): + $rtype = "SOA"; + break; + default: + $rtype = ""; + } + return array ($rtype, $rtype2, $rdns); +} + +/* This function will be replaced by an auto detect DNS cache servers routine */ +/* At the moment there is no tagging of DNSroute to a WAN port. It needs to be added */ +function tinydns_dnscache_forwarding_servers() { + $fr = fopen("/var/etc/resolv.conf.dnscache", "r"); + if (! $fr) { + printf("Error: cannot open resolv.conf.dnscache in tinydns_register_forwarding_servers().\n"); + return 1; + } + + $lip = strlen("nameserver") + 1; + $j = 0; + $iprecords = ""; + while (!feof($fr)) { + $routers = fgets($fr, 4096); + $discard = ($routers[0] == "\n"); + if(!$discard) { + if ($routerip = strstr($routers,"nameserver")) { + $routerip = substr($routerip,$lip); + if($routerip) { + $j += 1; + $routera = "{$routerip}"; + $iprecords .= $routera; + } + } + } + } + fclose($fr); + exec("echo 1 > /etc/dnscache/env/FORWARDONLY"); + if(is_dir("/etc/dnscache/root/servers/")) + exec("rm -R /etc/dnscache/root/servers/"); + exec("mkdir /etc/dnscache/root/servers/"); + $fr = fopen("/etc/dnscache/root/servers/@", "w"); + if (! $fr) { + printf("Error: cannot write to /etc/dnscache/root/servers/@ in tinydns_dnscache_forwarding_servers().\n"); + return 1; + } + if($iprecords) + fwrite($fr, $iprecords); + fclose($fr); +} + +/* This routine adds filenames to /etc/dnscache/root/servers/ with the contents pointing to the tinyDNS server */ +function tinydns_create_soa_domain_list($dnsserverip) { + if(file_exists("/service/tinydns/root/data")) + $tinydns_data = file_get_contents("/service/tinydns/root/data"); + else + $tinydns_data = ""; + + $datalen = strlen($tinydns_data); + $startofrecord = 0; + while ($startofrecord < $datalen ) { + $endofrecord = strpos($tinydns_data,"\n",$startofrecord); + $dnsrecord = substr($tinydns_data,$startofrecord,$endofrecord-$startofrecord); + $startofrecord = $endofrecord + 1; + + $col1 = strpos($dnsrecord,":"); + $fqdn = substr($dnsrecord,1,$col1-1); + if($fqdn) { + $rtypes = tinydns_get_dns_record_type($dnsrecord); + if($rtypes[0] == "SOA") { + $fr = fopen("/etc/dnscache/root/servers/{$fqdn}", "w"); + if (! $fr) { + printf("Error: cannot open /etc/dnscache/root/servers/{$fqdn} in tinydns_create_soa_domain_list().\n"); + return 1; + } + if($fqdn)fwrite($fr, $dnsserverip); + fclose($fr); + } + } + } +} + +/* This function is not called */ +/* At the moment there is no tagging of DNSroute to a WAN port. It needs to be added */ +function tinydns_register_forwarding_servers() { + $fr = fopen("/var/etc/resolv.conf", "r"); + if (! $fr) { + printf("Error: cannot open resolv.conf in tinydns_register_forwarding_servers().\n"); + return 1; + } + + $lip = strlen("nameserver") + 1; + $j = 0; + $nsrecords = ""; + $arecords = ""; + while (!feof($fr)) { + $routers = fgets($fr, 4096); + $discard = ($routers[0] == "\n"); + if(!$discard) { + if ($routerip = strstr($routers,"nameserver")) { + $routerip = substr($routerip,$lip); + if($routerip) { + $j += 1; + $routerfqdn = "DNSroute-{$j}.wan{$j}"; + $routerns = "&::{$routerfqdn}"; + $routera = "={$routerfqdn}:{$routerip}"; + $nsrecords .= $routerns . "\n"; + $arecords .= $routera; + } + } + } + } + fclose($fr); + $dnsroutes ="{$nsrecords}{$arecords}"; + return $dnsroutes; +} + +function tinydns_register_root_servers() { + $rootservers =<<<EOD +&::a.root-servers.net +&::b.root-servers.net +&::c.root-servers.net +&::d.root-servers.net +&::e.root-servers.net +&::f.root-servers.net +&::g.root-servers.net +&::h.root-servers.net +&::i.root-servers.net +&::j.root-servers.net +&::k.root-servers.net +&::l.root-servers.net +&::m.root-servers.net +=a.root-servers.net:198.41.0.4 +=b.root-servers.net:128.9.0.107 +=c.root-servers.net:192.33.4.12 +=d.root-servers.net:128.8.10.90 +=e.root-servers.net:192.203.230.10 +=f.root-servers.net:192.5.5.241 +=g.root-servers.net:192.112.36.4 +=h.root-servers.net:128.63.2.53 +=i.root-servers.net:192.36.148.17 +=j.root-servers.net:192.58.128.30 +=k.root-servers.net:193.0.14.129 +=l.root-servers.net:199.7.83.42 +=m.root-servers.net:202.12.27.33 + +EOD; + return $rootservers; +} + +function dnscache_use_root_servers() { + $rootservers =<<<EOD +198.41.0.4 +128.9.0.107 +192.33.4.12 +128.8.10.90 +192.203.230.10 +192.5.5.241 +192.112.36.4 +128.63.2.53 +192.36.148.17 +192.58.128.30 +193.0.14.129 +199.7.83.42 +202.12.27.33 + +EOD; + + exec("echo 0 > /etc/dnscache/env/FORWARDONLY"); + if(is_dir("/etc/dnscache/root/servers/")) + exec("rm -R /etc/dnscache/root/servers/"); + exec("mkdir /etc/dnscache/root/servers/"); + $fr = fopen("/etc/dnscache/root/servers/@", "w"); + if (! $fr) { + printf("Error: cannot write to /etc/dnscache/root/servers/@ in dnscache_use_root_servers().\n"); + return 1; + } + fwrite($fr, $rootservers); + fclose($fr); +} + +?>
\ No newline at end of file |