2.0) define('BIND_LOCALBASE', '/usr/pbi/bind-' . php_uname("m")); else define('BIND_LOCALBASE','/usr/local'); define('CHROOT_LOCALBASE','/cf/named'); function bind_zone_validate($post, $input_errors){ if (key_exists("mail",$_POST)) $_POST['mail']=preg_replace("/@/",".",$post['mail']); switch ($_POST['type']){ case 'slave': if( $_POST['slaveip'] == "") $input_errors[] = 'The field \'Master Zone IP\' is required for slave zones.'; break; case 'forward': if( $_POST['forwarders'] == "") $input_errors[] = 'The field \'Forwarders\' is required for forward zones.'; break; default: if($_POST['nameserver']=='') $input_errors[] = 'The field \'Name server\' is required for master zones.'; for ($i=0;$i < count($_POST);$i++){ if (key_exists("hostname$i",$_POST)){ if ($_POST['reverso']=="on"){ $_POST["hostvalue$i"]=""; if (!preg_match("/(PTR|NS)/",$_POST["hosttype$i"])) $input_errors[] = 'On reverse zones, valid record types are NS or PTR'; } if (preg_match("/(MX|NS)/",$_POST["hosttype$i"])) $_POST["hostname$i"]=""; if (!preg_match("/(MX|NS)/",$_POST["hosttype$i"]) && $_POST["hostname$i"]=="") $input_errors[] = 'Record cannot be empty for '.$_POST["hosttype$i"].' type '; if ($_POST["hosttype$i"]=="MX" && $_POST["hostvalue$i"]=="") $_POST["hostvalue$i"]="10"; if ($_POST["hosttype$i"]!="MX" && $_POST["hostvalue$i"]!="") $_POST["hostvalue$i"]=""; if ($_POST["hostdst$i"]=="") $input_errors[] = 'Alias or IP address cannot be empty.'; } } } } function bind_sync(){ global $config; conf_mount_rw(); //create rndc $rndc_confgen="/usr/local/sbin/rndc-confgen"; if (!file_exists(BIND_LOCALBASE."/etc/rndc-confgen.pfsense") && file_exists($rndc_confgen)){ exec("$rndc_confgen ",$rndc_conf); foreach($rndc_conf as $line) $confgen_file.="$line\n"; file_put_contents(BIND_LOCALBASE."/etc/rndc-confgen.pfsese",$confgen_file); } if (file_exists(BIND_LOCALBASE."/etc/rndc-confgen.pfsese")){ $rndc_conf=file(BIND_LOCALBASE."/etc/rndc-confgen.pfsese"); $confgen="rndc.conf"; $rndc_bindconf=""; foreach ($rndc_conf as $line){ if ($confgen =="rndc.conf"){ if (!preg_match ("/^#/",$line)) $rndc_file.=$line; } else{ if (!preg_match ("/named.conf/",$line)) $rndc_bindconf.=preg_replace('/#/',"",$line); } if (preg_match("/named.conf/",$line)){ $confgen="named.conf"; file_put_contents(BIND_LOCALBASE."/etc/rndc.conf",$rndc_file); } } } $bind = $config["installedpackages"]["bind"]["config"][0]; $bind_enable = $bind['enable_bind']; $bind_forwarder = $bind['bind_forwarder']; $forwarder_ips = $bind['bind_forwarder_ips']; $ram_limit = ($bind['bind_ram_limit']?$bind['bind_ram_limit']:"256M"); $hide_version = $bind['bind_hide_version']; $bind_notify = $bind['bind_notify']; $custom_options = base64_decode($bind['bind_custom_options']); $bind_logging = $bind['bind_logging']; $bind_conf ="#Bind pfsense configuration\n"; $bind_conf .="#Do not edit this file!!!\n\n"; $bind_conf .= "$rndc_bindconf\n"; $bind_conf .= <<$bind_listenonv6 $bind_listenon"; if (key_exists("ipv6allow",$config['system'])){ $bind_conf .="\t\tlisten-on-v6 { $bind_listenonv6 };\n"; } $bind_conf .="\t\tlisten-on { $bind_listenon };\n"; #forwarder config if ($bind_forwarder == on) $bind_conf .="\t\tforwarders { $forwarder_ips };\n"; if ($bind_notify == on) $bind_conf .="\t\tnotify yes;\n"; if ($hide_version == on) $bind_conf .="\t\tversion \"N/A\";\n"; $bind_conf .="\t\t$custom_options\n"; $bind_conf .= "\t};\n\n"; if ($bind_logging == on){ $bind_conf .= <<"any","description"=>"Default Access list","row" => array("value"=> "","description"=>"")); write_config("Create Default bind acl 'Any'"); } $bindacls = $config["installedpackages"]["bindacls"]["config"]; for ($i=0; $i 0){ write_config("save result config file for zone on xml"); } $bind_conf .= "};\n"; } $dirs=array("/etc/namedb","/var/run/named","/var/dump","/var/log","/var/stats","/dev"); foreach ($dirs as $dir){ if (!is_dir(CHROOT_LOCALBASE .$dir)) mkdir(CHROOT_LOCALBASE .$dir,0755,true); } //http://www.unixwiz.net/techtips/bind9-chroot.html //create devices on chroot exec('ls -lL /dev/zero /dev/null /dev/random',$devs); foreach ($devs as $cdev){ $dev=explode(" ",preg_replace("/,/","",$cdev)); if (preg_match("/\w+/",$dev[15]) && !file_exists(CHROOT_LOCALBASE.$dev[15])){ if (preg_match("/\d+/",$dev[9]) && preg_match("/\d+/",$dev[11])) exec("/sbin/mknod ".CHROOT_LOCALBASE."{$dev[15]} c {$dev[9]} {$dev[11]}"); } } file_put_contents(CHROOT_LOCALBASE.'/etc/namedb/named.conf', $bind_conf); file_put_contents(CHROOT_LOCALBASE.'/etc/namedb/rndc.conf', $rndc_file); if (!file_exists(CHROOT_LOCALBASE."/etc/namedb/named.root")){ //dig +tcp @a.root-servers.net > CHROOT_LOCALBASE."/etc/namedb/named.root" $named_root=file_get_contents("http://www.internic.net/domain/named.root"); file_put_contents(CHROOT_LOCALBASE."/etc/namedb/named.root",$named_root,LOCK_EX); } if (!file_exists(CHROOT_LOCALBASE."/etc/localtime")){ copy("/etc/localtime", CHROOT_LOCALBASE."/etc/localtime"); } bind_write_rcfile(); chown(CHROOT_LOCALBASE."/var/log","bind"); chgrp(CHROOT_LOCALBASE."/var/log","bind"); if($bind_enable == "on") mwexec("/usr/local/etc/rc.d/named.sh restart"); else mwexec("/usr/local/etc/rc.d/named.sh stop"); conf_mount_ro(); } function bind_print_javascript_type_zone(){ ?> on_type_zone_changed();document.iform.resultconfig.disabled = 1;\n"); } function bind_write_rcfile() { $rc = array(); $BIND_LOCALBASE = "/usr/local"; $rc['file'] = 'named.sh'; $rc['start'] = <</dev/null sleep 2 EOD; $rc['restart'] = <</dev/null sleep 3 {$BIND_LOCALBASE}/sbin/named -c /etc/namedb/named.conf -u bind -t /cf/named/ fi EOD; conf_mount_rw(); write_rcfile($rc); conf_mount_ro(); } function create_log_file(){ conf_mount_rw(); mwexec("touch ".CHROOT_LOCALBASE."/var/log/named.log"); mwexec("chown bind:bind ".CHROOT_LOCALBASE."/var/log/named.log"); mwexec("chmod 755 ".CHROOT_LOCALBASE."/var/log/named.log"); conf_mount_ro(); } function delete_log_file(){ conf_mount_rw(); mwexec("rm ".CHROOT_LOCALBASE."/var/log/named.log"); conf_mount_ro(); } /* Uses XMLRPC to synchronize the changes to a remote node */ function bind_sync_on_changes() { global $config, $g; if (is_array($config['installedpackages']['bind']['config'])){ $bind_sync=$config['installedpackages']['bind']['config'][0]; $synconchanges = $bind_sync['synconchanges']; $synctimeout = $bind_sync['synctimeout']; switch ($synconchanges){ case "manual": if (is_array($bind_sync[row])){ $rs=$bind_sync[row]; } else{ log_error("[bind] xmlrpc sync is enabled but there is no hosts to push on bind config."); return; } break; case "auto": if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])){ $system_carp=$config['installedpackages']['carpsettings']['config'][0]; $rs[0]['ipaddress']=$system_carp['synchronizetoip']; $rs[0]['username']=$system_carp['username']; $rs[0]['password']=$system_carp['password']; } else{ log_error("[bind] xmlrpc sync is enabled but there is no system backup hosts to push bind config."); return; } break; default: return; break; } if (is_array($rs)){ log_error("[bind] xmlrpc sync is starting."); foreach($rs as $sh){ $sync_to_ip = $sh['ipaddress']; $password = $sh['password']; if($sh['username']) $username = $sh['username']; else $username = 'admin'; if($password && $sync_to_ip) bind_do_xmlrpc_sync($sync_to_ip, $username, $password,$synctimeout); } log_error("[bind] xmlrpc sync is ending."); } } } /* Do the actual XMLRPC sync */ function bind_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout) { global $config, $g; if(!$username) return; if(!$password) return; if(!$sync_to_ip) return; if(!$synctimeout) $synctimeout=25; $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['bind'] = $config['installedpackages']['bind']; $xml['bindacls'] = $config['installedpackages']['bindacls']; $xml['bindviews'] = $config['installedpackages']['bindviews']; $xml['bindzone'] = $config['installedpackages']['bindzone']; /* 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("[bind] Beginning bind 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($username, $password); if($g['debug']) $cli->setDebug(1); /* send our XMLRPC message and timeout after defined sync timeout value*/ $resp = $cli->send($msg, $synctimeout); if(!$resp) { $error = "A communications error occurred while attempting bind XMLRPC sync with {$url}:{$port}."; log_error($error); file_notice("sync_settings", $error, "bind Settings Sync", ""); } elseif($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); $error = "An error code was received while attempting bind XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "bind Settings Sync", ""); } else { log_error("[bind] XMLRPC sync successfully completed with {$url}:{$port}."); } /* tell bind to reload our settings on the destination sync host. */ $method = 'pfsense.exec_php'; $execcmd = "require_once('/usr/local/pkg/bind.inc');\n"; $execcmd .= "bind_sync('yes');"; /* assemble xmlrpc payload */ $params = array( XML_RPC_encode($password), XML_RPC_encode($execcmd) ); log_error("[bind] XMLRPC reload data {$url}:{$port}."); $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); $cli->setCredentials($username, $password); $resp = $cli->send($msg, $synctimeout); if(!$resp) { $error = "A communications error occurred while attempting bind XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; log_error($error); file_notice("sync_settings", $error, "Bind Settings Sync", ""); } elseif($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); $error = "[Bind] An error code was received while attempting bind XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "bind Settings Sync", ""); } else { log_error("Bind XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); } } ?>