0% found this document useful (0 votes)
81 views44 pages

Class Dnslib

// URL under which IPplan is installed. May be required for servers // using virual hosts for which IPplan cannot figure out the URL // This parameter should be in a directory format. // if IPplan is at URL http://myhost.com/ipplan, then this setting // should be /ipplan // NOTE: no http, no hostname, no trailing / define("BASE_URL", '');

Uploaded by

jaier
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
81 views44 pages

Class Dnslib

// URL under which IPplan is installed. May be required for servers // using virual hosts for which IPplan cannot figure out the URL // This parameter should be in a directory format. // if IPplan is at URL http://myhost.com/ipplan, then this setting // should be /ipplan // NOTE: no http, no hostname, no trailing / define("BASE_URL", '');

Uploaded by

jaier
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 44

<?

php

// IPplan v4.92b

// Aug 24, 2001

//

// This program is free software; you can redistribute it and/or modify

// it under the terms of the GNU General Public License as published by

// the Free Software Foundation; either version 2 of the License, or

// (at your option) any later version.

//

// This program is distributed in the hope that it will be useful,

// but WITHOUT ANY WARRANTY; without even the implied warranty of

// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

// GNU General Public License for more details.

//

// You should have received a copy of the GNU General Public License

// along with this program; if not, write to the Free Software

// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

//

// workaround for funky behaviour of nested includes with older

// versions of php

require_once(dirname(__FILE__)."/config.php");

// common class functions for forward and reverse zones

class DNSZone extends IPplanDbf {

// form variables

var $hname;

var $ttl;

var $refresh;
var $retry;

var $expire;

var $minimum;

var $responsiblemail;

var $slaveonly;

var $zonepath;

var $seczonepath;

var $info="";

var $serialdate=0;

var $serialnum=0;

// local class variables

var $grps;

var $errstr = "";

var $err = 1;

var $clone = 0;

function SetSOA($hname, $ttl, $refresh, $retry, $expire, $minimum,

$responsiblemail, $slaveonly, $zonepath, $seczonepath, $info="") {

$this->hname = $hname;

$this->ttl = $ttl;

$this->refresh = $refresh;

$this->retry = $retry;

$this->expire = $expire;

$this->minimum = $minimum;

$this->responsiblemail = $responsiblemail;

$this->slaveonly = $slaveonly;
$this->zonepath = $zonepath;

$this->seczonepath = $seczonepath;

$this->info = $info;

function SetSerial($serialdate, $serialnum) {

$this->serialdate=$serialdate;

$this->serialnum=$serialnum;

// work out the new serial number from a previous SetSerial

function Serial() {

$now = getdate();

$newserialdate = $now["year"] . str_pad($now["mon"], 2, '0', STR_PAD_LEFT) . str_pad(


$now["mday"], 2, '0', STR_PAD_LEFT);

if ($this->serialdate==$newserialdate) {

$this->serialnum++;

}else{

$this->serialdate=$newserialdate;

$this->serialnum=0;

// remove domain name from FQDN, converts to lowercase

// if domain cannot be stripped, return FQDN with trailing .


function strip_domain($hname, $domain) {

$hname=strtolower($hname);

$domain=strtolower($domain);

// use ~ as sperator as this cannot appear in dns name

$temp = preg_replace("~\.$domain$~", "", $hname);

if ($hname===$temp) {

$temp=$hname.".";

return $temp;

function ZoneAXFR($domain, $server) {

require_once("Net/DNS.php");

$res = new Net_DNS_Resolver();

//$res->debug = 1;

$res->persistent_tcp=1;

$res->nameservers=array($server);

$answer = $res->axfr($domain);

/*

echo "<pre>";

var_dump($answer);

//var_dump($res);
//var_dump($answer[0]->header->rcode);

echo "</pre>";

exit;

*/

// check for errors

/*

if ($res->errorstring != "NOERROR") {

$this->err=70;

$this->errstr .= sprintf(my_("Zone transfer for domain %s failed with message %s"), $this-
>domain, $res->errorstring)."\n";

return "";

*/

if ($answer) {

$this->hname=array(); $i=1; // kill form information

foreach($answer as $rr) {

if ($rr->type == "SOA") {

//var_dump($rr);

$this->ttl=$rr->ttl;

$this->refresh=$rr->refresh;

$this->retry=$rr->retry;

$this->expire=$rr->expire;

$this->minimum=$rr->minimum;

$this->responsiblemail=$rr->rname;

if ($rr->type == "NS" and $rr->name == $this->domain) {

$this->hname[$i++]=$this->strip_domain($rr->nsdname, $this->domain);
}

$this->err = 0;

return $answer;

} else {

$this->errstr .= sprintf(my_("Zone transfer for domain %s failed - using defaults: %s"), $this-
>domain, $res->errorstring)."\n";

// could not do transfer, so use defaults from now on!

$this->err = -1;

return "";

} // end class DNSZone

// specific forward zone functions

class DNSfwdZone extends DNSZone {

var $cust;

var $dataid;

var $domain;

var $server;

var $createmod;

var $expiremod;
var $regmod;

function SetForm($cust, $dataid, $domain) {

$this->cust = $cust;

$this->dataid = $dataid;

$this->domain = $domain;

function SetDate($createmod, $expiremod, $regmod) {

$this->createmod = $createmod;

$this->expiremod = $expiremod;

$this->regmod = $regmod;

function FwdDelete($cust, $dataid, $domain) {

// use local function variables as they may change

$this->cust = $cust;

$this->rangeindex = $dataid;

$this->areaindex = $domain;

// check for records

$result = $this->ds->Execute("SELECT recidx

FROM fwdzonerec

WHERE customer=$cust AND data_id=$dataid");

$recs=$result->PO_RecordCount("fwdzonerec", "customer=$cust AND data_id=$dataid");

if ($recs) {
$this->err=50;

$this->errstr .= my_("Cannot delete domain zone - there are still DNS records\n");

return FALSE;

$result = $this->ds->Execute("DELETE FROM fwdzone

WHERE customer=$cust AND data_id=$dataid") and

$this->ds->Execute("DELETE FROM fwdzoneadd

WHERE customer=$cust AND data_id=$dataid") and

$this->ds->Execute("DELETE FROM fwddns

WHERE id=$dataid");

return $result;

function FwdZoneAddRR ($dataid, $answer) {

$i=5;

foreach($answer as $rr) {

if ($rr->type == "A") {

$recordtype=$rr->type;

$host=$this->strip_domain($rr->name, $this->domain);

$iphostname=$rr->address;

else if ($rr->type == "CNAME") {

$recordtype=$rr->type;

$host=$this->strip_domain($rr->name, $this->domain);

$iphostname=$this->strip_domain($rr->cname, $this->domain);

}
else if ($rr->type == "NS" and $rr->name != $this->domain) {

$recordtype=$rr->type;

$host=$this->strip_domain($rr->name, $this->domain);

$iphostname=$this->strip_domain($rr->nsdname, $this->domain);

else if ($rr->type == "MX") {

$recordtype=$rr->type;

$host=$this->strip_domain($rr->name, $this->domain);

$iphostname=$rr->preference." ".$this->strip_domain($rr->exchange, $this->domain);

else if ($rr->type == "TXT") {

$recordtype=$rr->type;

$host=$this->strip_domain($rr->name, $this->domain);

// truncate TXT field to 254 chars - can be much bigger

$iphostname=substr($rr->rdata, 1, $rr->rdlength > 254 ? 254 : $rr->rdlength);

else if ($rr->type == "SRV") {

$recordtype=$rr->type;

$host=$this->strip_domain($rr->name, $this->domain);

$iphostname=$rr->preference." ".$rr->weight." ".$rr->port." ".$this->strip_domain($rr-


>target, $this->domain);

else if ($rr->type == "AFSDB") {

$recordtype=$rr->type;

$host=$this->strip_domain($rr->name, $this->domain);

$iphostname=$rr->preference." ".$this->strip_domain($rr->exchange, $this->domain);

else {

continue;
}

$result = $this->ds->Execute("INSERT into fwdzonerec

(customer, data_id, sortorder, lastmod, host,

recordtype, userid, ip_hostname) ".

"VALUES ($this->cust, $dataid, ". $i.",".

$this->ds->DBTimeStamp(time()).",".

$this->ds->qstr($host).",".

$this->ds->qstr($recordtype).",".

$this->ds->qstr(getAuthUsername()).",".

$this->ds->qstr($iphostname).")" );

if (!$result) {

return FALSE;

$i=$i+5;

return TRUE;

function FwdAddNS($dataid) {

// add reverse DNS into fwddns table

for ($i = 1; $i < 11; $i++) {

if (isset($this->hname[$i]) and !empty($this->hname[$i])) {

$hnametemp=$this->hname[$i];

// add DNS records


$result=$this->ds->Execute("INSERT INTO fwddns

(id, hname, horder)

VALUES

($dataid,

".$this->ds->qstr($hnametemp).",

$i)");

if (!$result) {

return FALSE;

return TRUE;

// test if the zone exists and lock for update

function FwdZoneExists($cust, $dataid) {

// need to do select as mysql driver does not have RowLock

// mysqlt does have rowlock

$row = $this->ds->GetOne("SELECT data_id

FROM fwdzone

WHERE customer=$cust AND data_id=$dataid");

$this->ds->RowLock("fwdzone", "customer=$cust AND data_id=$dataid");

return !empty($row);

function FwdUpdateSOA($cust, $dataid) {


// use local function variables as they may change

$this->cust = $cust;

if (!$this->FwdZoneExists($cust, $dataid)) {

$this->err=90;

$this->errstr .= my_("Could not find the zone - possibly deleted by another user")."\n";

return FALSE;

// work out new serial numbers

$this->Serial();

// check and warn if there are zone records if slaveonly=Y

if ($this->slaveonly=="Y") {

$result = $this->ds->Execute("SELECT count(*) AS cnt

FROM fwdzonerec

WHERE customer=$cust AND data_id=$dataid");

// loop through each host record

$row = $result->FetchRow();

if($row["cnt"] > 0) {

$this->err=-50;

$this->errstr .= my_("You are changing this zone to a slave only zone, but there are zone
records\n");

// Updated DB here.

$result = $this->ds->Execute("UPDATE fwdzone ".

"set serialdate=".$this->ds->qstr($this->serialdate).
", serialnum=$this->serialnum".

",ttl=".$this->ttl.

",refresh=".$this->refresh.

",retry=".$this->retry.

",expire=".$this->expire.

",minimum=".$this->minimum.

",error_message=".$this->ds->qstr("E").

",responsiblemail=".$this->ds->qstr($this->responsiblemail).

",userid=".$this->ds->qstr(getAuthUsername()).

",zonefilepath1=".$this->ds->qstr($this->zonepath).

",zonefilepath2=".$this->ds->qstr($this->seczonepath).

",createmod=".$this->ds->DBDate($this->createmod).

",lastmod=".$this->ds->DBTimeStamp(time()).

",expiremod=".$this->ds->DBDate($this->expiremod).

",regmod=".$this->ds->DBDate($this->regmod).

",slaveonly=".$this->ds->qstr($this->slaveonly).

" WHERE customer=$cust AND data_id=".$dataid );

if($this->ds->GetRow("SELECT info

FROM fwdzoneadd

WHERE customer=$cust AND

data_id=$dataid")) { // should have FOR UPDATE here!

$result = $this->ds->Execute("UPDATE fwdzoneadd ".

"set info=".$this->ds->qstr($this->info).

" WHERE customer=$cust AND data_id=".$dataid );

else { // no record, insert

if (!empty($this->info)) {

$result = $this->ds->Execute("INSERT into fwdzoneadd (customer, data_id, info) ".


"VALUES ($this->cust,".

$dataid.",".

$this->ds->qstr($this->info).")" );

// delete all the DNS records first to preserve correct order

$result=$this->ds->Execute("DELETE FROM fwddns

WHERE id=$dataid");

// add reverse DNS into fwdzone table

$this->FwdAddNS($dataid);

return $result;

function FwdAddSOA() {

// work out new serial numbers

$this->Serial();

// Add to DB here.

$result = $this->ds->Execute("INSERT into fwdzone (customer, domain, error_message,

createmod, lastmod, expiremod, regmod, serialdate, serialnum, ttl, refresh, retry,

expire, minimum, responsiblemail, userid, zonefilepath1, zonefilepath2, slaveonly) ".

"VALUES ($this->cust,".

$this->ds->qstr($this->domain).",".
$this->ds->qstr("E").",".

$this->ds->DBDate($this->createmod).",".

$this->ds->DBTimeStamp(time()).",".

$this->ds->DBDate($this->expiremod).",".

$this->ds->DBDate($this->regmod).",".

$this->ds->qstr($this->serialdate).", $this->serialnum,".

$this->ttl.",".

$this->refresh.",".

$this->retry.",".

$this->expire.",".

$this->minimum.",".

$this->ds->qstr($this->responsiblemail).",".

$this->ds->qstr(getAuthUsername()).",".

$this->ds->qstr($this->zonepath).",".

$this->ds->qstr($this->seczonepath).",".

$this->ds->qstr($this->slaveonly).")" );

// did not fail due to key error?

// should not fail as we checked this already!

if ($result) {

if (DBF_TYPE=="mysql" or DBF_TYPE=="maxsql") {

$dataid=$this->ds->Insert_ID();

else {

// emulate getting the last insert_id

$result=$this->ds->Execute("SELECT data_id

FROM fwdzone

WHERE customer=$this->cust AND

domain=".$this->ds->qstr($this->domain));
$temprow = $result->FetchRow();

$dataid=$temprow["data_id"];

if (!empty($info)) {

$result = $this->ds->Execute("INSERT into fwdzoneadd (customer, data_id, info) ".

"VALUES ($this->cust,".

$dataid.",".

$this->ds->qstr($this->info).")" );

return $dataid;

// key error?

return 0;

function FwdAdd($cust, $domain, $server) {

// use local function variables as they may change

$this->cust = $cust;

// is the server variable set? then do zone transfer

// should really only read SOA if slaveonly set

if (!empty($server)) {

$answer=$this->ZoneAXFR($this->domain, $server);

// fatal zone transfer error?


if ($this->err > 0) {

return $this->err;

// could use unique key on database to do check, but requires extra key

// just to add a new record

$restemp=$this->ds->Execute("SELECT domain FROM fwdzone

WHERE customer=$cust AND domain = ".$this->ds->qstr($this->domain));

if ($restemp->FetchRow()) {

// domain already exists, fail transaction

$this->err=-60;

$this->errstr .= sprintf(my_("DNS Domain %s could not be created - possibly duplicate


zone"), $this->domain)."\n";

else {

// create the actual zone

$dataid=$this->FwdAddSOA();

$this->dataid=$dataid;

// did not fail due to key error?

if ($dataid) {

if(!$this->FwdAddNS($dataid)) {

$this->err = -60;

return $this->err;

// now load individual rr records if zone transfer requested


// only if not a slavezone and no previous error

if (!empty($server) and $this->slaveonly=="N" and !empty($answer)) {

if(!$this->FwdZoneAddRR($dataid, $answer)) {

$this->err = -60;

return $this->err;

// or clone zone if clone requested

else if (empty($server) and $this->slaveonly=="N" and $this->clone) {

// this SQL only works with MySql v >= 4.0.14

$result=$this->ds->Execute("INSERT INTO fwdzonerec

(data_id, host, recordtype, ip_hostname, sortorder, customer, userid, lastmod)

SELECT $dataid AS data_id, fwdzonerec.host, fwdzonerec.recordtype,

fwdzonerec.ip_hostname, fwdzonerec.sortorder, fwdzonerec.customer,

".$this->ds->qstr(getAuthUsername())." AS userid,

".$this->ds->DBTimeStamp(time())." AS lastmod

FROM fwdzonerec, fwdzone

WHERE fwdzonerec.data_id=fwdzone.data_id AND

fwdzone.domain=".$this->ds->qstr("template.com"));

$this->err = 0;

else {

$this->err = -60;

$this->errstr .= sprintf(my_("DNS Domain %s could not be created - possibly duplicate


zone"), $this->domain)."\n";

}
return $this->err;

function FwdZoneExport($cust, $dataid) {

// use local function variables as they may change

$this->cust = $cust;

$this->Serial();

// Update DNS Database Serial Count. Update Serial Count only when we export.

$result = $this->ds->Execute("UPDATE fwdzone ".

"set serialdate=".$this->ds->qstr($this->serialdate).

", userid=".$this->ds->qstr(getAuthUsername()).

", error_message=".$this->ds->qstr("").

", lastexp=".$this->ds->DBTimeStamp(time()).

", serialnum=$this->serialnum".

" WHERE customer=$cust AND data_id=".$dataid);

if ($result) {

$sqllastmod = $this->ds->SQLDate("M d Y H:i:s", 'lastmod');

$result = $this->ds->Execute("SELECT data_id, domain, engineer, error_message,

responsiblemail, serialdate, serialnum, ttl, refresh, retry, expire,

minimum, zonefilepath1, zonefilepath2, customer, admingrp,

$sqllastmod AS lastmod, userid, slaveonly

FROM fwdzone

WHERE customer=$cust AND data_id=$dataid");


$row = $result->FetchRow();

$this->domain=$row["domain"];

$info = $this->ds->GetOne("SELECT info

FROM fwdzoneadd

WHERE customer=$cust AND data_id=$dataid");

$tmpfname = tempnam (DNSEXPORTPATH, "zone_".$this->domain."_");

if(!$tmpfname) {

$this->err=80;

$this->errstr .= my_("Could not create temporary file!");

return;

$fp = fopen ("$tmpfname", "w");

// header of document

$output='<?xml version="1.0" ?>';

fputs($fp, $output);

fputs($fp, "\n");

fputs($fp, sprintf('<zone domain="%s" slaveonly="%s">', $row["domain"],

(empty($row["slaveonly"]) ? "N" : $row["slaveonly"])));

fputs($fp, "\n");

fputs($fp, sprintf("<path>\n<primary>\n%s\n</primary>\n",

htmlspecialchars($row["zonefilepath1"])));

fputs($fp, sprintf("<primaryfile>\n%s\n</primaryfile>\n",

htmlspecialchars(basename($row["zonefilepath1"]))));

fputs($fp, sprintf("<primarydir>\n%s\n</primarydir>\n",

htmlspecialchars(dirname($row["zonefilepath1"]))));
fputs($fp, sprintf("<secondary>\n%s\n</secondary>\n",

htmlspecialchars($row["zonefilepath2"])));

fputs($fp, sprintf("<secondaryfile>\n%s\n</secondaryfile>\n",

htmlspecialchars(basename($row["zonefilepath2"]))));

fputs($fp, sprintf("<secondarydir>\n%s\n</secondarydir>\n",

htmlspecialchars(dirname($row["zonefilepath2"]))));

fputs($fp, "</path>\n");

// SOA portion

fputs($fp, sprintf('<soa serialdate="%s" serialnum="%02d" ttl="%s" retry="%s" refresh="%s"


expire="%s" minimumttl="%s" email="%s" />',

$this->serialdate, $this->serialnum,

$row["ttl"],

$row["retry"],

$row["refresh"],

$row["expire"],

$row["minimum"],

$row["responsiblemail"]

));

fputs($fp, "\n");

// additional fields

if (!empty($info)) {

$template=new IPplanIPTemplate("fwdzonetemplate", $cust);

if ($template->is_error() == FALSE) {

$template->Merge($template->decode($info));

fputs($fp, "<additional>\n");

foreach($template->userfld as $field=>$val) {
fputs($fp, sprintf("\t<%s>%s</%s>\n",

htmlspecialchars($field),

htmlspecialchars($val["value"]),

htmlspecialchars($field)));

fputs($fp, "</additional>\n");

// nameservers

$result1 = $this->ds->Execute("SELECT hname

FROM fwddns

WHERE id=$dataid

ORDER BY horder");

$cnt=0;

while($row1 = $result1->FetchRow()) {

fputs($fp, '<record><NS>');

fputs($fp, sprintf('<iphostname>%s</iphostname>', $row1["hname"]));

fputs($fp, '</NS></record>');

fputs($fp, "\n");

$cnt++;

if ($cnt < 2) {

fclose($fp);

unlink($tmpfname);

$this->err=70;
$this->errstr .= my_("Invalid zone - zone should have at least two name servers
defined")."\n";

return;

$sqllastmod = $this->ds->SQLDate("M d Y H:i:s", 'lastmod');

$result = $this->ds->Execute("SELECT recidx, data_id, host, recordtype, ip_hostname,

error_message, sortorder, customer, $sqllastmod AS lastmod, userid

FROM fwdzonerec

WHERE customer=$cust AND data_id=$dataid

ORDER BY sortorder");

// loop through each host record

while($row = $result->FetchRow()) {

fputs($fp, sprintf('<record><%s>', $row["recordtype"]));

fputs($fp, sprintf('<host>%s</host>', $row["host"]));

// MX records are in format "10 hostname.com" in database field ip_hostname

if ($row["recordtype"]=="MX" or $row["recordtype"]=="AFSDB") {

list($preference, $iphost) = explode(" ", $row["ip_hostname"], 2);

if (is_numeric($preference) and $preference >= 0) {

fputs($fp, sprintf('<preference>%s</preference>', $preference));

fputs($fp, sprintf('<iphostname>%s</iphostname>', $iphost));

else {

fputs($fp, '<preference>10</preference>');

fputs($fp, sprintf('<iphostname>%s</iphostname>', $row["ip_hostname"]));

else if ($row["recordtype"]=="SRV")
{

list($priority, $weight, $port, $iphost) = explode(" ", $row["ip_hostname"], 4);

if (is_numeric($priority) and is_numeric($weight) and is_numeric($port)

and $priority >= 0 and $weight >= 0 and $port >= 0 ) {

fputs($fp, sprintf('<preference>%s %s %s</preference>', $priority, $weight, $port));

fputs($fp, sprintf('<iphostname>%s</iphostname>', $iphost));

else {

fputs($fp, '<preference> Invalid SRV record </preference>');

fputs($fp, sprintf('<iphostname>%s</iphostname>', $row["ip_hostname"]));

else {

fputs($fp, sprintf('<iphostname>%s</iphostname>', $row["ip_hostname"]));

fputs($fp, sprintf('</%s></record>', $row["recordtype"]));

fputs($fp, "\n");

// close zone

fputs($fp, '</zone>');

fputs($fp, "\n");

fclose($fp);

// give file proper extension

rename($tmpfname, $tmpfname.".xml");

@chmod($tmpfname.".xml",0644);

$this->err=0;
return $tmpfname.".xml";

//return $tmpfname;

// database error?

} // end of class DNSFwdZone

// specific forward zone functions

class DNSrevZone extends DNSZone {

var $cust;

var $zoneid;

var $zone;

var $zoneip;

var $size;

var $server;

function SetForm($cust, $zoneid, $zone, $zoneip, $size) {

$this->cust = $cust;

$this->zoneid = $zoneid;

$this->zone = $zone;

$this->zoneip = $zoneip;

$this->size = $size;
}

function RevDelete($cust, $zoneid, $zone) {

// use local function variables as they may change

$this->cust = $cust;

$result = $this->ds->Execute("DELETE FROM zones

WHERE customer=$cust AND id=$zoneid") and

$this->ds->Execute("DELETE FROM zonedns

WHERE id=$zoneid");

return $result;

function RevZoneAddRR ($zoneid, $answer) {

global $grps;

// open a new database connection

$ds = new Base();

if(!$ds) {

$this->err=90;

$this->errstr .= my_("Could not connect to database");

$ds->SetGrps($grps);

$ds->SetSearchIn(1);
foreach($answer as $rr) {

if ($rr->type == "PTR") {

$recordtype=$rr->type;

$domain=$rr->ptrdname; // proper domain name

$host=$rr->name; // in format 46.61.110.147.in-addr.arpa

else {

continue;

// now split ip address

list($oc1, $oc2, $oc3, $oc4, $tail) = split("\.", $host, 5);

$ipaddr="$oc4.$oc3.$oc2.$oc1";

if (testIP($ipaddr)) {

$this->errstr .= sprintf(my_("Invalid address %s"), $ipaddr)."\n";

continue;

$ds->SetIPaddr($ipaddr);

$result = $ds->FetchBase($this->cust, 0, 0);

if (!$result) {

$this->err=70;

$this->errstr .= $ds->errstr;

// add records here - got a match for a subnet

if ($row = $result->FetchRow()) {

$baseindex=$row["baseindex"];

$affected=$ds->UpdateIP(inet_aton($ipaddr), $baseindex, "hname", $domain);

if (!$affected) {
$ds->AddIP(inet_aton($ipaddr), $baseindex, "", "", "", "",

"Reverse zone import", $domain, "");

// no subnet matched, add something to the error string

else {

$this->errstr .= sprintf(my_("No subnet found for address %s"), $ipaddr)."\n";

return TRUE;

function RevAddNS($zoneid) {

// add reverse DNS into fwddns table

for ($i = 1; $i < 11; $i++) {

if (isset($this->hname[$i]) and !empty($this->hname[$i])) {

$hnametemp=$this->hname[$i];

// add DNS records

$result=$this->ds->Execute("INSERT INTO zonedns

(id, hname, horder)

VALUES

($zoneid,

".$this->ds->qstr($hnametemp).",

$i)");
if (!$result) {

return FALSE;

return TRUE;

// test if the zone exists and lock for update

function RevZoneExists($cust, $zoneid) {

// need to do select as mysql driver does not have RowLock

// mysqlt does have rowlock

$row = $this->ds->GetOne("SELECT id

FROM zones

WHERE customer=$cust AND id=$zoneid");

$this->ds->RowLock("zones", "customer=$cust AND id=$zoneid");

return !empty($row);

// test if the zone has changed records - check the last serial for the zone

// against the ippaddr table for changed records i.e. records with a date equal or

// later than the serial date

function RevZoneChanged($cust, $zoneid) {

$sqlfn = $this->ds->SQLDate('Ymd','ipaddr.lastmod');

$row = $this->ds->GetOne("SELECT zones.id

FROM zones, base, ipaddr

WHERE zones.customer=base.customer AND


base.baseindex=ipaddr.baseindex AND

$sqlfn >= zones.serialdate AND

ipaddr.ipaddr >= zones.zoneip AND

ipaddr.ipaddr < zones.zoneip+zones.zonesize AND

zones.id=$zoneid");

return !empty($row);

function RevUpdateSOA($cust, $zoneid, $zone, $zoneip, $size) {

// use local function variables as they may change

$this->cust = $cust;

if (!$this->RevZoneExists($cust, $zoneid)) {

$this->err=90;

$this->errstr .= my_("Could not find the zone - possibly deleted by another user")."\n";

return FALSE;

// work out new serial numbers

$this->Serial();

// Updated DB here.

$result = $this->ds->Execute("UPDATE zones SET zoneip=$zoneip".

",zone=".$this->ds->qstr($this->zone).

",zonesize=$size".

",serialdate=".$this->ds->qstr($this->serialdate).

",serialnum=$this->serialnum".

",ttl=".$this->ttl.
",refresh=".$this->refresh.

",retry=".$this->retry.

",expire=".$this->expire.

",minimum=".$this->minimum.

",error_message=".$this->ds->qstr("E").

",responsiblemail=".$this->ds->qstr($this->responsiblemail).

",userid=".$this->ds->qstr(getAuthUsername()).

",zonefilepath1=".$this->ds->qstr($this->zonepath).

",zonefilepath2=".$this->ds->qstr($this->seczonepath).

",lastmod=".$this->ds->DBTimeStamp(time()).

",slaveonly=".$this->ds->qstr($this->slaveonly).

" WHERE customer=$cust AND id=".$zoneid );

// delete all the DNS records first to preserve correct order

$result=$this->ds->Execute("DELETE FROM zonedns

WHERE id=$zoneid");

// add reverse DNS into fwdzone table

$this->RevAddNS($zoneid);

return $result;

function RevAddSOA() {

// work out new serial numbers

$this->Serial();
// Add to DB here.

$result = $this->ds->Execute("INSERT into zones

(customer, zoneip, zone, zonesize, serialdate,

serialnum, error_message, ttl, refresh, retry, expire, minimum,

lastmod, responsiblemail, userid, zonefilepath1,

zonefilepath2, slaveonly) ".

"VALUES ($this->cust, $this->zoneip,".

$this->ds->qstr($this->zone).", $this->size,".

$this->ds->qstr($this->serialdate).", $this->serialnum,".

$this->ds->qstr("E").",".

$this->ttl.",".

$this->refresh.",".

$this->retry.",".

$this->expire.",".

$this->minimum.",".

$this->ds->DBTimeStamp(time()).",".

$this->ds->qstr($this->responsiblemail).",".

$this->ds->qstr(getAuthUsername()).",".

$this->ds->qstr($this->zonepath).",".

$this->ds->qstr($this->seczonepath).",".

$this->ds->qstr($this->slaveonly).")" );

// did not fail due to key error?

// should not fail as we checked this already!

if ($result) {

if (DBF_TYPE=="mysql" or DBF_TYPE=="maxsql") {

$zoneid=$this->ds->Insert_ID();

}
else {

// emulate getting the last insert_id

$result=$this->ds->Execute("SELECT id

FROM zones

WHERE customer=$this->cust AND

zoneip=$this->zoneip");

$temprow = $result->FetchRow();

$zoneid=$temprow["id"];

return $zoneid;

// key error?

return 0;

function RevAdd($cust, $zone, $server) {

// use local function variables as they may change

$this->cust = $cust;

// is the server variable set? then do zone transfer

// should really only read SOA if slaveonly set

if (!empty($server)) {

$answer=$this->ZoneAXFR($this->zone, $server);

// fatal zone transfer error?

if ($this->err > 0) {
return $this->err;

// could use unique key on database to do check, but requires extra key

// just to add a new record

$restemp=$this->ds->Execute("SELECT zone FROM zones

WHERE customer=$cust AND zone = ".$this->ds->qstr($this->zone));

if ($restemp->FetchRow()) {

// domain already exists, fail transaction

$this->err=-60;

$this->errstr .= sprintf(my_("DNS Domain %s could not be created - possibly duplicate


zone"), $this->zone)."\n";

else {

// create the actual zone

$zoneid=$this->RevAddSOA();

$this->zoneid=$zoneid;

// did not fail due to key error?

if ($zoneid) {

if(!$this->RevAddNS($zoneid)) {

$this->err = -60;

return $this->err;

// now load individual rr records

// only if not a slavezone and no previous error


if (!empty($server) and $this->slaveonly=="N" and !empty($answer)) {

if(!$this->RevZoneAddRR($zoneid, $answer)) {

$this->err = -60;

return $this->err;

$this->err = 0;

else {

$this->err = -60;

$this->errstr .= sprintf(my_("DNS Domain %s could not be created - possibly duplicate


zone"), $this->zone)."\n";

return $this->err;

function RevZoneExport($cust, $zoneid) {

// use local function variables as they may change

$this->cust = $cust;

$this->Serial();

$result = $this->ds->Execute("UPDATE zones ".

"set serialdate=".$this->ds->qstr($this->serialdate).

", userid=".$this->ds->qstr(getAuthUsername()).

", lastexp=".$this->ds->DBTimeStamp(time()).
", error_message=".$this->ds->qstr("").

", serialnum=$this->serialnum ".

" WHERE customer=$cust AND id=$zoneid");

if ($result) {

$sqllastmod = $this->ds->SQLDate("M d Y H:i:s", 'lastmod');

$result = $this->ds->Execute("SELECT id, zoneip, zonesize, zone, serialdate,

serialnum, ttl, refresh, retry, expire, minimum, zonefilepath1,

zonefilepath2, responsiblemail, customer, $sqllastmod AS lastmod,

userid, slaveonly

FROM zones

WHERE customer=$cust AND id=$zoneid");

$row = $result->FetchRow();

$this->zone=$row["zone"];

$this->zoneip=$row["zoneip"];

$this->size=$row["zonesize"];

$prefix=inet_bits($row["zonesize"]);

$tmpfname = tempnam (DNSEXPORTPATH, "revzone_".$this->zone."_");

if(!$tmpfname) {

$this->err=80;

$this->errstr .= my_("Could not create temporary file!");

return;

$fp = fopen ("$tmpfname", "w");

// header of document

$output='<?xml version="1.0" ?>';


fputs($fp, $output);

fputs($fp, "\n");

$ip=inet_ntoa($row["zoneip"]);

list($octet1,$octet2,$octet3,$octet4) = explode(".",$ip);

fputs($fp, sprintf('<zone domain="%s" zoneip="%s" zonesize="%s" prefix="%s"


slaveonly="%s" octect1="%s" octect2="%s" octect3="%s" octect4="%s">',

$row["zone"], $ip, $row["zonesize"], $prefix,

(empty($row["slaveonly"]) ? "N" : $row["slaveonly"]),

$octet1, $octet2, $octet3, $octet4));

fputs($fp, "\n");

fputs($fp, sprintf("<path>\n<primary>\n%s\n</primary>\n",

htmlspecialchars($row["zonefilepath1"])));

fputs($fp, sprintf("<primaryfile>\n%s\n</primaryfile>\n",

htmlspecialchars(basename($row["zonefilepath1"]))));

fputs($fp, sprintf("<primarydir>\n%s\n</primarydir>\n",

htmlspecialchars(dirname($row["zonefilepath1"]))));

fputs($fp, sprintf("<secondary>\n%s\n</secondary>\n",

htmlspecialchars($row["zonefilepath2"])));

fputs($fp, sprintf("<secondaryfile>\n%s\n</secondaryfile>\n",

htmlspecialchars(basename($row["zonefilepath2"]))));

fputs($fp, sprintf("<secondarydir>\n%s\n</secondarydir>\n",

htmlspecialchars(dirname($row["zonefilepath2"]))));

fputs($fp, "</path>\n");

// SOA portion

fputs($fp, sprintf('<soa serialdate="%s" serialnum="%02d" ttl="%s" retry="%s" refresh="%s"


expire="%s" minimumttl="%s" email="%s" />',
$this->serialdate, $this->serialnum,

$row["ttl"],

$row["retry"],

$row["refresh"],

$row["expire"],

$row["minimum"],

$row["responsiblemail"]

));

fputs($fp, "\n");

// nameservers

$result1 = $this->ds->Execute("SELECT hname FROM zonedns

WHERE id=$zoneid

ORDER BY horder");

$cnt=0;

while($row1 = $result1->FetchRow()) {

fputs($fp, '<record><NS>');

fputs($fp, sprintf('<iphostname>%s</iphostname>', $row1["hname"]));

fputs($fp, '</NS></record>');

fputs($fp, "\n");

$cnt++;

if ($cnt < 2) {

fclose($fp);

unlink($tmpfname);

$this->err=90;
$this->errstr .= my_("Invalid zone - zone should have at least two name servers defined");

return;

// get records from main ipplan ipaddr tables

$result1 = $this->ds->Execute("SELECT ipaddr.ipaddr, ipaddr.hname

FROM base, ipaddr

WHERE base.customer = $cust AND

base.baseindex = ipaddr.baseindex AND

ipaddr.ipaddr >= ".$row["zoneip"]." AND

ipaddr.ipaddr <= ".($row["zoneip"]+$row["zonesize"])."

ORDER BY ipaddr.ipaddr");

while($row1 = $result1->FetchRow()) {

$ip=inet_ntoa($row1["ipaddr"]);

// ignore blank records

if (empty($row1["hname"])) {

continue;

// test for valid domain name

if (!preg_match('/^(([\w][\w\-\.]*)\.)?([\w][\w\-]+)(\.([\w][\w\.]*))?$/', $row1["hname"]))
{

$this->errstr .= sprintf(my_("Invalid record - ignored: %s %s"), $ip, $row1["hname"]);

continue;

fputs($fp, '<record><PTR>');

fputs($fp, sprintf('<host>%s</host>', $row1["hname"]));


list($octet1,$octet2,$octet3,$octet4) = explode(".",$ip);

fputs($fp, sprintf('<octet1>%s</octet1>', $octet1));

fputs($fp, sprintf('<octet2>%s</octet2>', $octet2));

fputs($fp, sprintf('<octet3>%s</octet3>', $octet3));

fputs($fp, sprintf('<octet4>%s</octet4>', $octet4));

fputs($fp, "\n");

fputs($fp, sprintf('<iphostname>%s</iphostname>', $ip));

fputs($fp, '</PTR></record>');

fputs($fp, "\n");

// close zone

fputs($fp, '</zone>');

fputs($fp, "\n");

fclose($fp);

// give file proper extension

rename($tmpfname, $tmpfname.".xml");

@chmod($tmpfname.".xml",0644);

$this->err=0;

return $tmpfname.".xml";

//return $tmpfname;

// database error?
/*

// Update DNS Database Serial Count. Update Serial Count only when we export.

$result = $this->ds->Execute("UPDATE fwdzone ".

"set serialdate=".$this->ds->qstr($this->serialdate).

", userid=".$this->ds->qstr(getAuthUsername()).

", serialnum=$this->serialnum".

" WHERE customer=$cust AND data_id=".$zoneid);

if ($result) {

$result = $this->ds->Execute("SELECT * FROM fwdzone

WHERE customer=$cust AND data_id=$zoneid");

$row = $result->FetchRow();

$this->domain=$row["domain"];

$tmpfname = tempnam (DNSEXPORTPATH, "zone_") or

myError($w,$p, my_("Could not create temporary file!"));

$fp = fopen ("$tmpfname", "w");

// header of document

$output='<?xml version="1.0" ?>';

fputs($fp, $output);
fputs($fp, "\n");

fputs($fp, sprintf('<zone domain="%s" slaveonly="%s">', $row["domain"],

(empty($row["slaveonly"]) ? "N" : $row["slaveonly"])));

fputs($fp, "\n");

// SOA portion

fputs($fp, sprintf('<soa serialdate="%s" serialnum="%02d" ttl="%s" retry="%s" refresh="%s"


expire="%s" minimumttl="%s" email="%s" />',

$this->serialdate, $this->serialnum,

$row["ttl"],

$row["retry"],

$row["refresh"],

$row["expire"],

$row["minimum"],

$row["responsiblemail"]

));

fputs($fp, "\n");

// nameservers

$result1 = $this->ds->Execute("SELECT hname

FROM fwddns

WHERE id=$zoneid

ORDER BY horder");

$cnt=0;

while($row1 = $result1->FetchRow()) {

fputs($fp, '<record><NS>');

fputs($fp, sprintf('<iphostname>%s</iphostname>', $row1["hname"]));

fputs($fp, '</NS></record>');
fputs($fp, "\n");

$cnt++;

if ($cnt < 2) {

insert($w,textbr(my_("Invalid zone - zone should have at least two name servers defined")));

$result = $this->ds->Execute("SELECT * FROM fwdzonerec

WHERE customer=$cust AND data_id=$zoneid

ORDER BY sortorder");

// loop through each host record

while($row = $result->FetchRow()) {

fputs($fp, sprintf('<record><%s>', $row["recordtype"]));

fputs($fp, sprintf('<host>%s</host>', $row["host"]));

// MX records are in format "10 hostname.com" in database field ip_hostname

if ($row["recordtype"]=="MX") {

list($preference, $iphost) = explode(" ", $row["ip_hostname"], 2);

if (is_numeric($preference) and $preference >= 0) {

fputs($fp, sprintf('<preference>%s</preference>', $preference));

fputs($fp, sprintf('<iphostname>%s</iphostname>', $iphost));

else {

fputs($fp, '<preference>10</preference>');

fputs($fp, sprintf('<iphostname>%s</iphostname>', $row["ip_hostname"]));

else {
fputs($fp, sprintf('<iphostname>%s</iphostname>', $row["ip_hostname"]));

fputs($fp, sprintf('</%s></record>', $row["recordtype"]));

fputs($fp, "\n");

// close zone

fputs($fp, '</zone>');

fputs($fp, "\n");

fclose($fp);

return $tmpfname;

*/

} // end of class DNSFwdZone

?>

You might also like