* */ if (defined("DNS_INC")) return(""); define("DNS_INC", "1"); /******************************************************************* For information on configuring this class, visit http://www.ypass.net/php/dns/ *******************************************************************/ define("NAMED_CONF_PATH", "/var/named/named.conf"); define("NAMED_CONF_MASTER_ADD_FILE", "/var/named/named.masters"); define("NAMED_CONF_SLAVE_ADD_FILE", "/var/named/named.masters"); define("NAMED_CONF_PATH_PARSED", "/var/named/named.conf.parsed"); define("NAMED_DIR", "/var/named"); define("LOCK_DIR", "/var/lock/"); // Default values for new zones (DON'T FORGET THE TRAILING DOTS!!!!!) define("DEFAULT_PRIMARY_NAMESERVER", "ns1.yourdomain.com."); define("DEFAULT_SECONDARY_NAMESERVER", "ns2.yourdomain.com."); define("DEFAULT_CONTACT_EMAIL", "hostmaster.yourdomain.com."); define("DEFAULT_PRIMARY_MX", "mx1.yourdomain.com."); define("DEFAULT_SECONDARY_MX", "mx2.yourdomain.com."); class ZONE { var $domainName; var $defaultTTL = ""; var $origin; var $rr = array(); var $zoneconf; var $error; var $curRR = 0; function ZONE($domainName, $search = 0) { $this->zoneconf = new ZONECONF; if ($domainName != "") { $this->domainName = $domainName; $this->origin = $domainName . "."; if (! $this->zoneconf->findZoneFile($domainName)) $this->error = $this->zoneconf->error; else $this->readZone(); } } // Locks the zone file so other's can't access it function lock($domainName) { if (file_exists(LOCK_DIR . "/" . $domainName . ".lock")) { $this->error = "$domainName is already locked"; return(0); } if (touch(LOCK_DIR . "/" . $domainName . ".lock")) return(1); $this->error = "couldn't touch lock file"; return(0); } // Unlocks the zone file function unlock($domainName) { if (unlink(LOCK_DIR . "/" . $domainName . ".lock")) return(1); $this->error = "could not unlock domain"; return(0); } // Tests to see if the zone is locked function isLocked($domainName) { if (file_exists(LOCK_DIR . "/" . $domainName . ".lock")) return(1); return(0); } // Open's and parses the zone file for the domain. // An RR object is created for each resource record for the zone. // GENERATE and TTL are parsed correctly. function readZone() { if (! ($f = fopen(NAMED_DIR . "/" . $this->zoneconf->file, "r"))) { $this->error = "Couldn't open " . NAMED_DIR . "/" . $this->zoneconf->file . " for read"; return(0); } $foundSOA = 0; $rrnum = 0; $linenum = 0; while (! feof($f)) { $line = fgets($f, 1024); if (ereg("^[ \t]*;", $line, $regs)) continue; if (ereg("^[ \t\n\r]$", $line, $regs)) continue; // Parse any $ commands if (ereg("^\\\$([^ \t]+)[ \t]+(.*)$", $line, $regs)) { switch ($regs[1]) { case "ORIGIN": $this->origin = chop($regs[2]); break; case "TTL": $this->defaultTTL = chop($regs[2]); break; case "GENERATE": if (ereg("^([0-9]+)-([0-9]+)[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]+([^ \t\r\n]+)", $regs[2], $gen)) { for ($ctr = $gen[1]; $ctr <= $gen[2]; $ctr++) { ereg("(.*)\\\$(.*)", $gen[3], $lhs); $gen[3] = $lhs[1] . $ctr . $lhs[2]; ereg("(.*)\\\$(.*)", $gen[5], $rhs); $gen[5] = $rhs[1] . $ctr . $rhs[2]; $line .= $gen[3] . "\t" . $gen[4] . "\t" . $gen[5] . "\n"; $this->rr[$rrnum]->lhs = $gen[3]; $this->rr[$rrnum]->id = $rrnum; $this->rr[$rrnum]->ttl = ""; $this->rr[$rrnum]->type = $gen[4]; switch ($this->rr[$rrnum]->type) { case "A": $this->rr[$rrnum]->rhs = new A; $this->rr[$rrnum++]->rhs->ipAddress = $gen[5]; break; case "AAAA": $this->error = "parse error: can't handle IPv6 yet"; return(0); case "CNAME": $this->rr[$rrnum]->rhs = new CNAME; $this->rr[$rrnum++]->rhs->hostname = $gen[5]; break; case "MX": if (!ereg("^([0-9]+)[ \t]+([^ \t;]+)", $gen[5], $mx)) { $this->error = "bad mx record on line $linenum"; return(0); } $this->rr[$rrnum]->rhs = new MX; $this->rr[$rrnum]->rhs->preference = $mx[1]; $this->rr[$rrnum++]->rhs->hostname = $mx[2]; break; case "NS": $this->rr[$rrnum]->rhs = new NS; $this->rr[$rrnum++]->rhs->hostname = $gen[5]; break; case "PTR": $this->rr[$rrnum]->rhs = new PTR; $this->rr[$rrnum++]->rhs->hostname = $gen[5]; break; } if (substr($this->rr[$rrnum-1]->lhs, strlen($this->rr[$rrnum-1]->lhs)-1) != ".") $this->rr[$rrnum-1]->lhs = $this->rr[$rrnum-1]->lhs . "." . $this->origin; } } break; } continue; } if (! $foundSOA) { // Get the whole SOA record before doing anything else $line = ereg_replace("^(.*)[;]*.*$", "\\1", $line); $linenum++; while (!strstr($line, ")")) { $line .= fgets($f, 1024); $linenum++; $line = ereg_replace("^(.*);.*$", "\\1", $line); } if (!ereg("^([^ \t\n\r]+)[ \t\n\r]+IN[ \t\n\r]+SOA[ \t\n\r]+([^ \t\n\r]+)[ \t\n\r]+([^ \t\n\r]+)[ \t\n\r]+\([ \t\n\r]+([0-9]+)[ \t\n\r]+([0-9]+)[ \t\n\r]+([0-9]+)[ \t\n\r]+([0-9]+)[ \t\n\r]+([0-9]+)[ \t\n\r]*\)", $line, $soa)) { $this->error = "SOA parser error on line $linenum"; return(0); } $this->rr[$rrnum] = new RR; $this->rr[$rrnum]->id = $rrnum; $this->rr[$rrnum]->lhs = $soa[1]; $this->rr[$rrnum]->ttl = ""; $this->rr[$rrnum]->type = "SOA"; $this->rr[$rrnum]->rhs = new SOA; $this->rr[$rrnum]->rhs->priNS = $soa[2]; $this->rr[$rrnum]->rhs->techContact = $soa[3]; $this->rr[$rrnum]->rhs->serial = $soa[4]; $this->rr[$rrnum]->rhs->refresh = $soa[5]; $this->rr[$rrnum]->rhs->retry = $soa[6]; $this->rr[$rrnum]->rhs->expire = $soa[7]; $this->rr[$rrnum++]->rhs->minimum = $soa[8]; $foundSOA = 1; } else if (ereg("^([^ \t]*)[ \t]+([0-9]*)[ \t]*[I]*[N]*[ \t]+(A|CNAME|MX|NS|PTR)[ \t]+([^;\n]+)", $line, $regs)) { if ($regs[1] == "") $this->rr[$rrnum]->lhs = $this->rr[$rrnum-1]->lhs; else $this->rr[$rrnum]->lhs = $regs[1]; $this->rr[$rrnum]->id = $rrnum; $this->rr[$rrnum]->ttl = $regs[2]; $this->rr[$rrnum]->type = $regs[3]; switch ($this->rr[$rrnum]->type) { case "A": $this->rr[$rrnum]->rhs = new A; $this->rr[$rrnum++]->rhs->ipAddress = $regs[4]; break; case "AAAA": $this->error = "parse error: can't handle IPv6 yet"; return(0); case "CNAME": $this->rr[$rrnum]->rhs = new CNAME; $this->rr[$rrnum++]->rhs->hostname = $regs[4]; break; case "MX": if (!ereg("^([0-9]+)[ \t]+([^ \t;]+)", $regs[4], $mx)) { $this->error = "bad mx record on line $linenum"; return(0); } $this->rr[$rrnum]->rhs = new MX; $this->rr[$rrnum]->rhs->preference = $mx[1]; $this->rr[$rrnum++]->rhs->hostname = $mx[2]; break; case "NS": $this->rr[$rrnum]->rhs = new NS; $this->rr[$rrnum++]->rhs->hostname = $regs[4]; break; case "PTR": $this->rr[$rrnum]->rhs = new PTR; $this->rr[$rrnum++]->rhs->hostname = $regs[4]; break; } } else if (! feof($f)) { // Found an invalid RR $this->error = "RR parse error at line $linenum: $line"; return(0); } // Tack the origin on to the end of the lhs if needed if ($this->rr[$rrnum-1]->lhs == "@") $this->rr[$rrnum-1]->lhs = $this->origin; else if (substr($this->rr[$rrnum-1]->lhs, strlen($this->rr[$rrnum-1]->lhs)-1) != ".") $this->rr[$rrnum-1]->lhs = $this->rr[$rrnum-1]->lhs . "." . $this->origin; // Tack the origin on the the end of the rhs if needed switch ($this->rr[$rrnum-1]->type) { case "PTR": case "NS": case "MX": if ($this->rr[$rrnum-1]->rhs->hostname == "@") $this->rr[$rrnum-1]->rhs->hostname = $this->origin; if (substr($this->rr[$rrnum-1]->rhs->hostname, strlen($this->rr[$rrnum-1]->rhs->hostname)-1) != ".") $this->rr[$rrnum-1]->rhs->hostname = $this->rr[$rrnum-1]->rhs->hostname . "." . $this->origin; default: break; } } return(1); } // returns the name of the technical contact specified in the zone file function administrator($admin = "") { if (! $administrator) return($this->rr[0]->rhs->techContact); return($this->rr[0]->rhs->techContact = $admin); } // Returns the number of RR's in a zone function rrCount() { return(count($this->rr)); } // reset the internal RR counter to the first RR function resetRR() { $this->curRR = 0; } // get the next RR in the zone file function getRR() { if ($this->curRR > count($this->rr)) return(0); return($this->rr[$this->curRR++]); } // save any modifications back to the zone file function saveZone() { $this->resetRR(); if (! $this->lock($this->domainName)) { $this->error = "domain " . $this->domainName . " is current locked"; return(0); } if (! ($f = fopen(NAMED_DIR . "/" . $this->zoneconf->file . ".new", "w"))) { $this->error = "Couldn't open " . NAMED_DIR . "/" . $this->zoneconf->file . ".new for write"; return(0); } fputs($f, '$TTL ' . $this->defaultTTL . "\n"); while ($rr = $this->getRR()) { $writeRR = $rr->lhs . ($rr->ttl ? (" " . $rr->ttl) : "") . " IN " . $rr->type . " "; switch($rr->type) { case "SOA": $rr->rhs->setSerial(); $writeRR = "@ " . $rr->ttl . " IN " . $rr->type . " " . $rr->rhs->priNS . " " . $rr->rhs->techContact . " (\n\t\t" . $rr->rhs->serial . "\t; serial\n\t\t" . $rr->rhs->refresh . "\t\t; refresh\n\t\t" . $rr->rhs->retry . "\t\t; retry\n\t\t" . $rr->rhs->expire . "\t\t; expire\n\t\t" . $rr->rhs->minimum . " )\t\t; minimum\n\n"; break; case "NS": $writeRR .= $rr->rhs->hostname . "\n"; break; case "MX": $writeRR .= $rr->rhs->preference . " " . $rr->rhs->hostname . "\n"; break; case "A": $writeRR .= $rr->rhs->ipAddress . "\n"; break; case "PTR": $writeRR .= $rr->rhs->hostname . "\n"; break; case "CNAME": $writeRR .= $rr->rhs->hostname . "\n"; break; default: $this->error = "unknown type $rr->type."; fclose($f); unlink(NAMED_DIR . "/" . $this->zoneconf->file . ".new"); $this->unlock($this->domainName); return(0); } fputs($f, $writeRR); } fclose($f); rename(NAMED_DIR . "/" . $this->zoneconf->file . ".new", NAMED_DIR . "/" . $this->zoneconf->file); $this->unlock($this->domainName); return(1); } // add a new resource record. Only parameter is an RR object function addRR($newRR) { if ($newRR->lhs == "@") $newRR->lhs = $this->origin; if (substr($newRR->lhs, strlen($newRR->lhs)-1) != ".") $newRR->lhs = $newRR->lhs . "." . $this->origin; if ($newRR->rhs->hostname == "@") $newRR->rhs->hostname = $this->origin; if (substr($newRR->rhs->hostname, strlen($newRR->rhs->hostname)-1) != ".") $newRR->rhs->hostname = $newRR->rhs->hostname . "." . $this->origin; $this->rr[$this->rrCount()] = $newRR; } // add an MX record to the zone file (frontend for addRR) function addMX($lhs, $pref, $rhs, $ttl = "") { $newRR = new RR; $newRR->lhs = $lhs; $newRR->ttl = $ttl; $newRR->type = "MX"; $newRR->rhs = new MX; $newRR->rhs->preference = $pref; $newRR->rhs->hostname = $rhs; $this->addRR($newRR); } // add an NS record to the zone file (frontend for addRR) function addNS($lhs, $rhs, $ttl = "") { $newRR = new RR; $newRR->lhs = $lhs; $newRR->ttl = $ttl; $newRR->type = "NS"; $newRR->rhs = new NS; $newRR->rhs->hostname = $rhs; $this->addRR($newRR); } // add an CNAME record to the zone file (frontend for addRR) function addCNAME($lhs, $rhs, $ttl = "") { $newRR = new RR; $newRR->lhs = $lhs; $newRR->ttl = $ttl; $newRR->type = "CNAME"; $newRR->rhs = new CNAME; $newRR->rhs->hostname = $rhs; $this->addRR($newRR); } // add an A record to the zone file (frontend for addRR) function addA($lhs, $rhs, $ttl = "") { $newRR = new RR; $newRR->lhs = $lhs; $newRR->ttl = $ttl; $newRR->type = "A"; $newRR->rhs = new A; $newRR->rhs->ipAddress = $rhs; $this->addRR($newRR); } // add an PTR record to the zone file (frontend for addRR) function addPTR($lhs, $rhs, $ttl = "") { $newRR = new RR; $newRR->lhs = $lhs; $newRR->ttl = $ttl; $newRR->type = "PTR"; $newRR->rhs = new PTR; $newRR->rhs->hostname = $rhs; $this->addRR($newRR); } // remove an RR record from a zone file. You can specify the specific // RR number (the index of the array). If you pass no parameters, it // will remove the element last returned by getRR. function removeRR($specific = -1) { if ($specific != -1) { if ($specific == 0) { $this->error = "Cannot delete the SOA record"; return(0); } else { $this->curRR = $specific; } } else { $this->curRR--; } for ($ctr = $this->curRR+1; $ctr < $this->rrCount(); $ctr++) $this->rr[$ctr-1] = $this->rr[$ctr]; unset($this->rr[$ctr-1]); } // Create a new zone (in memory). You must save the file to put it // on disk. function addZone($zonename) { if ($this->zoneconf->findZoneFile($zonename)) { $this->error = "Could not add zone: zone already exists"; return(0); } if (! $this->zoneconf->addZone($zonename)) { $this->error = $this->zoneconf->error; return(0); } $this->domainName = $zonename; $this->origin = $zonename . "."; $this->defaultTTL = 259200; // Set the SOA record $this->rr[0] = new RR; $this->rr[0]->id = 0; $this->rr[0]->lhs = $this->origin; $this->rr[0]->ttl = ""; $this->rr[0]->type = "SOA"; $this->rr[0]->rhs = new SOA; $this->rr[0]->rhs->priNS = DEFAULT_PRIMARY_NAMESERVER; $this->rr[0]->rhs->techContact = DEFAULT_CONTACT_EMAIL; $this->rr[0]->rhs->serial = $this->rr[0]->rhs->setSerial(); $this->rr[0]->rhs->refresh = 43200; $this->rr[0]->rhs->retry = 7200; $this->rr[0]->rhs->expire = 1209600; $this->rr[0]->rhs->minimum = 3600; // Set the primary nameserver $this->rr[1] = new RR; $this->rr[1]->id = 1; $this->rr[1]->lhs = $this->origin; $this->rr[1]->ttl = ""; $this->rr[1]->type = "NS"; $this->rr[1]->rhs = new NS; $this->rr[1]->rhs->hostname = DEFAULT_PRIMARY_NAMESERVER; // Set the secondary nameserver $this->rr[2] = new RR; $this->rr[2]->id = 2; $this->rr[2]->lhs = $this->origin; $this->rr[2]->ttl = ""; $this->rr[2]->type = "NS"; $this->rr[2]->rhs = new NS; $this->rr[2]->rhs->hostname = DEFAULT_SECONDARY_NAMESERVER; // Set the primary mail exchanger $this->rr[3] = new RR; $this->rr[3]->id = 3; $this->rr[3]->lhs = $this->origin; $this->rr[3]->ttl = ""; $this->rr[3]->type = "MX"; $this->rr[3]->rhs = new MX; $this->rr[3]->rhs->preference = "10"; $this->rr[3]->rhs->hostname = DEFAULT_PRIMARY_MX; // Set the secondary mail exchanger $this->rr[4] = new RR; $this->rr[4]->id = 4; $this->rr[4]->lhs = $this->origin; $this->rr[4]->ttl = ""; $this->rr[4]->type = "MX"; $this->rr[4]->rhs = new MX; $this->rr[4]->rhs->preference = "20"; $this->rr[4]->rhs->hostname = DEFAULT_SECONDARY_MX; if (! $this->saveZone()) return(0); return(1); } // Remove a zone file function removeZone($zonename) { if (! $this->zoneconf->findZoneFile($zonename)) { $this->error = "Couldn't remove zone: zone does not exist"; return(0); } if (! $this->zoneconf->removeZone($zonename)) { $this->error = $this->zoneconf->error; return(0); } if (! unlink(NAMED_DIR . "/" . $this->zoneconf->file)) { $this->error = "could not remove zone file"; return(0); } return(1); } } // Object defines a resource record. the $rhs property is an object // of type SOA, NS, MX, A, CNAME, or PTR class RR { var $id; var $lhs; var $ttl; var $type; var $rhs; } class SOA { var $priNS; var $techContact; var $serial = ""; var $refresh = ""; var $retry = ""; var $expire = ""; var $minimum = ""; function setSerial() { $newSerial = date("Ymd") . "01"; if ($this->serial >= $newSerial) return($this->serial++); else return($this->serial = $newSerial); } } class NS { var $hostname; } class MX { var $preference; var $hostname; } class A { var $ipAddress; } class PTR { var $hostname; } class CNAME { var $hostname; } class ZONECONF { var $domainName; var $file; var $error; // Get's the filename of the specified zone. function findZoneFile($domain) { if (! $ncStat = stat(NAMED_CONF_PATH)) { $this->error = "Couldn't stat NAMED_CONF_PATH"; return(0); } if (! ($ncpStat = stat(NAMED_CONF_PATH_PARSED)) || $ncStat[9] > $ncpStat[9]) { $this->readNamedConf(); } if (! ($f = fopen(NAMED_DIR . "/named.conf.parsed", "r"))) { $this->error = "Couldn't open " . NAMED_DIR . "/named.conf.parsed for read"; return(0); } while (! feof($f)) { $line = fgets($f, 1024); $d = explode(":", $line); if ($d[0] == $domain) { $this->domainName = $d[0]; $this->file = chop($d[1]); fclose($f); return(1); } } fclose($f); $this->error = "zone does not exist"; return(0); } // returns a list of domains with searchSpec as a substring of the zone name function findZone($searchSpec) { if (! $ncStat = stat(NAMED_CONF_PATH)) { $this->error = "Couldn't stat NAMED_CONF_PATH"; return(0); } if (! ($ncpStat = stat(NAMED_CONF_PATH_PARSED)) || $ncStat[9] > $ncpStat[9]) $this->readNamedConf(); if (! ($f = fopen(NAMED_DIR . "/named.conf.parsed", "r"))) { $this->error = "Couldn't open " . NAMED_DIR . "/named.conf.parsed for read"; return(0); } $ctr = 0; if ($searchSpec != "*") { while (! feof($f)) { $line = fgets($f, 1024); $d = explode(":", $line); if ($d[0] == $searchSpec) $dlist[$ctr++] = $d[0]; } if ($dlist[0] != "") $flag = 1; rewind($f); while (! feof($f)) { $line = fgets($f, 1024); $d = explode(":", $line); if (strstr($d[0], $searchSpec)) $dlistu[$ctr++] = $d[0]; } if (count($dlistu)) sort($dlistu); if ($flag == 1) { for ($ctr = 0; $ctr < count($dlistu); $ctr++) $dlist[$ctr+1] = $dlistu[$ctr]; return($dlist); } else return($dlistu); } else { while (! feof($f)) { $line = fgets($f, 1024); $d = explode(":", $line); $dlist[$ctr++] = $d[0]; } sort($dlist); return($dlist); } } // Read and parse the named.conf file function readNamedConf($includedfile = "", $fp = 0) { if ($includedfile) { if (! ($f = fopen(NAMED_DIR . "/" . $includedfile, "r"))) { $this->error = "Couldn't open " . NAMED_DIR . "/" . $includedfile . " for read"; return(0); } } else { if (! ($f = fopen(NAMED_CONF_PATH, "r"))) { $this->error = "Couldn't open " . NAMED_CONF_PATH . " for read"; return(0); } } if (! $fp && !($fp = fopen(NAMED_CONF_PATH_PARSED, "w"))) { fclose($f); $this->error = "Couldn't open 'NAMED_CONF_PATH_PARSED' for write"; return(0); } while (! feof($f)) { $line = fgets($f, 1024); $linenum++; if (ereg("^[ \t]*//.*$", $line, $regs)) continue; // Look for an include keyword if (ereg("^[ \t]*include[ \t]*\"([^\"]+)\"", $line, $regs)) { $this->readNamedConf($regs[1], $fp); } // Looking for the zone keyword if (ereg("^[ \t]*zone[ \t]*\"([^\"]+)\"[ \t]*(.*)$", $line, $regs)) { $zonedef = $regs[2]; $zchar = ""; $ref = 1; while ($ref != 0 && ! feof($f)) { $zchar = fgetc($f); $zonedef .= $zchar; if ($zchar == "{") $ref++; else if ($zchar == "}") $ref--; } $type = ereg_replace(".*type[ \t]+([^;]+);.*", "\\1", $zonedef); if (strcasecmp($type, "master") == 0) { $file = ereg_replace(".*file[ \t]+\"(.*)\";.*", "\\1", $zonedef); fputs($fp, $regs[1] . ":" . $file . "\n"); } } } if (! $includedfile) fclose($fp); fclose($f); return(1); } // Add a new zone to the named.conf file. function addZone($zonename) { while (file_exists(NAMED_CONF_MASTER_ADD_FILE . ".lock") && $ctr++ < 10) usleep(10); if (file_exists(NAMED_CONF_MASTER_ADD_FILE . ".lock")) { $this->error = "Couldn't add zone: " . NAMED_CONF_MASTER_ADD_FILE . " is locked."; return(0); } if (! touch(NAMED_CONF_MASTER_ADD_FILE . ".lock")) { $this->error = "Couldn't add zone: can't touch " . NAMED_CONF_MASTER_ADD_FILE . ".lock"; return(0); } if ($this->findZoneFile($zonename)) { $this->error = "Couldn't add zone: zone already exists"; unlink(NAMED_CONF_MASTER_ADD_FILE . ".lock"); return(0); } if (! ($f = fopen(NAMED_CONF_MASTER_ADD_FILE, "a"))) { $this->error = "Couldn't add zone: Couldn't open " . NAMED_CONF_MASTER_ADD_FILE . " for append"; unlink(NAMED_CONF_MASTER_ADD_FILE . ".lock"); return(0); } if (! ($f2 = fopen(NAMED_CONF_PATH_PARSED, "a"))) { $this->error = "Couldn't add zone: Couldn't open " . NAMED_CONF_PATH_PARSED . " for append"; unlink(NAMED_CONF_MASTER_ADD_FILE . ".lock"); return(0); } $adds = 'zone "' . $zonename . '" { type master; file "masters/' . $zonename[0] . '/' . $zonename . '"; }; '; fputs($f, $adds); fclose($f); $this->domainName = $zonename; $this->file = 'masters/' . $zonename[0] . '/' . $zonename; fputs($f2, $zonename . ":" . $this->file . "\n"); fclose($f2); touch(NAMED_CONF_PATH_PARSED, time()+1); unlink(NAMED_CONF_MASTER_ADD_FILE . ".lock"); return(1); } // remove a zone from the named.conf file function removeZone($zonename) { while (file_exists(NAMED_CONF_MASTER_ADD_FILE . ".lock") && $ctr++ < 10) usleep(10); if (file_exists(NAMED_CONF_MASTER_ADD_FILE . ".lock")) { $this->error = "Couldn't remove zone: " . NAMED_CONF_MASTER_ADD_FILE . " is locked."; return(0); } if (! touch(NAMED_CONF_MASTER_ADD_FILE . ".lock")) { $this->error = "Couldn't remove zone: can't touch " . NAMED_CONF_MASTER_ADD_FILE . ".lock"; return(0); } if (! $this->findZoneFile($zonename)) { $this->error = "Couldn't remove zone: zone does not exist"; unlink(NAMED_CONF_MASTER_ADD_FILE . ".lock"); return(0); } if (! ($fr = fopen(NAMED_CONF_MASTER_ADD_FILE, "r"))) { $this->error = "Couldn't remove zone: Couldn't open " . NAMED_CONF_MASTER_ADD_FILE . " for read"; unlink(NAMED_CONF_MASTER_ADD_FILE . ".lock"); return(0); } if (! ($fw = fopen(NAMED_CONF_MASTER_ADD_FILE . ".new", "w"))) { $this->error = "Couldn't remove zone: Couldn't open " . NAMED_CONF_MASTER_ADD_FILE . ".new for write"; unlink(NAMED_CONF_MASTER_ADD_FILE . ".lock"); return(0); } if (! ($f2r = fopen(NAMED_CONF_PATH_PARSED, "r"))) { $this->error = "Couldn't remove zone: Couldn't open " . NAMED_CONF_PATH_PARSED . " for read"; unlink(NAMED_CONF_MASTER_ADD_FILE . ".lock"); return(0); } if (! ($f2w = fopen(NAMED_CONF_PATH_PARSED . ".new", "w"))) { $this->error = "Couldn't remove zone: Couldn't open " . NAMED_CONF_PATH_PARSED . ".new for write"; unlink(NAMED_CONF_MASTER_ADD_FILE . ".lock"); return(0); } while (! feof($fr)) { $line = fgets($fr, 1024); if (ereg("^[ \t]*zone[ \t]*\"$zonename\"[ \t]*(.*)$", $line, $regs)) { $zonedef = $regs[2]; $zchar = ""; $ref = 1; while ($ref != 0 && ! feof($fr)) { $zchar = fgetc($fr); $zonedef .= $zchar; if ($zchar == "{") $ref++; else if ($zchar == "}") $ref--; } while ($zchar != ";" && ! feof($fr)) $zchar = fgetc($fr); while ($zchar != "\n" && ! feof($fr)) $zchar = fgetc($fr); $line = ""; } fputs($fw, $line); } fclose($fr); fclose($fw); rename(NAMED_CONF_MASTER_ADD_FILE . ".new", NAMED_CONF_MASTER_ADD_FILE); while (! feof($f2r)) { $line = fgets($f2r, 1024); $d = explode(":", $line); if ($d[0] != $zonename) fputs($f2w, $line); } rename(NAMED_CONF_PATH_PARSED . ".new", NAMED_CONF_PATH_PARSED); touch(NAMED_CONF_PATH_PARSED, time()+1); unlink(NAMED_CONF_MASTER_ADD_FILE . ".lock"); return(1); } } ?>