dlzdb-util

Tool to add and remove IPs from the DLZ DB(Perl script to run a generic DLZ BDBHPT).

dlzdb-util [-a] [-z zone(domain)] [-t type] [-n name] [-v value] [-m mx-prefix]
                [-S serial] [-F refresh-time] [-R retry-time] [-E expire] [-H hostmaster]
                [-T minimumTTL] [-N primary-name-server]
dlzdb-util [-d] [-z zone(domain)] 
dlzdb-util [-s] [-z zone(domain)]
ex:
Add record
dlzdb-util -a -z dmain.com -t A -n www -v 172.16.5.33 
dlzdb-util -a -z dmain.com -t MX -n @ -v mail.domain.com. -m 10
dlzdb-util -a -z dmain.com -t TXT -n @ -v "text field here" -m 10
dlzdb-util -a -z dmain.com -t SOA -S 2006112401 -F 28800 -R 7200 -E 604800 -T 86400 -H hostmaster.domain.com. -N  01.dnsv.jp.
dlzdb-util -a -z 5.16.172.in-addr.arpa -t SOA -S 2006112401 -F 28800 -R 7200 -E 604800 -T 86400 -H  hostmaster.domain.com. -N 01.dnsv.jp.
dlzdb-util -a -z 5.16.172.in-addr.arpa -t PTR -n 34 -v www.dmain.com.
Delete record
dlzdb-util -d -z domain.com
Show record
dlzdb-util -s -z domain.com

#!/usr/bin/perl
#########################################################################
#### Perl Script to Add / Remove IPs from DLZ with use for RentalDNS.
####
#### Yoshikazu Kojima <kojima@gmo.jp>
#### Based on script by glenn <hgic@geekazoid.com>
#### and Jorgen <lundman@lundman.net>
####
#########################################################################
# 2007/07/15 lundman: added PTR support
# 2007/01/12 kojima: extending to support all types, not just RBL
# 2006/09/21 lundman: created script to add IPs to RBL db.
#########################################################################
#### TODO
#### 1. manually field update
#### 2. how to list existing domain
#### 3. re-generate all zone from DRSDB
#########################################################################
################################################################################
#####   Perl libraries we need for this script
################################################################################
use strict;
use BerkeleyDB;
use Getopt::Std;
use Socket;
use locale;
################################################################################
#####   Declare Global Variables
################################################################################
my $env;
my $cacheDnsData = "";
my $cacheDnsZone = "";
my $cachefileref = "";
my $cachefilesth = "";
my $dbenvpath = "/etc/ns";
#my $dbenvpath = "/export/home/kojima";
my $dbfilebase = "DLZ.dnsdata.db";
my $dbfilename = "$dbfilebase.pending";
my %types = ('SOA' => '1',
			 'A' => '1',
			 'MX' => '1',
			 'NS' => '1',
			 'CNAME' => '1',
			 'TXT' => '1',
                         'PTR' => '1',
			 );
my $dns_data;
my $dns_xfr;
my $lockfile = "$dbenvpath/$dbfilebase.UPDATE";
################################################################################
#####   Declare Hashes
################################################################################
$env = new BerkeleyDB::Env
	-Home		=> $dbenvpath,
	-Flags		=> DB_INIT_CDB|DB_INIT_MPOOL|DB_INIT_LOCK|DB_CREATE,
	-ErrFile	=> "error.txt",
	-Verbose	=> 1 ;
$dns_data = tie my %cacheDnsData, 'BerkeleyDB::Hash',
	-Env		=> $env,
	-Filename	=> "$dbenvpath/$dbfilename",
	-Flags		=> DB_CREATE,
	-Property	=> DB_DUP | DB_DUPSORT,
	-Subname	=> "dns_data",
	or die "Cannot create $dbfilename: $BerkeleyDB::Error\n";
tie my %cacheDnsZone, 'BerkeleyDB::Btree',
	-Env		=> $env,
	-Filename	=> "$dbenvpath/$dbfilename",
	-Flags		=> DB_CREATE,
	-Subname	=> "dns_zone",
	or die "Cannot create master.dns_zone.db: $BerkeleyDB::Error\n";
$dns_xfr = tie my %cacheDnsXfr, 'BerkeleyDB::Hash',
	-Env		=> $env,
	-Filename	=> "$dbenvpath/$dbfilename",
	-Flags		=> DB_CREATE,
	-Property	=> DB_DUP | DB_DUPSORT,
	-Subname	=> "dns_xfr",
	or die "Cannot create master.dns_xfr.db: $BerkeleyDB::Error\n";
tie my %cacheDnsClient, 'BerkeleyDB::Hash',
	-Env		=> $env,
	-Filename	=> "$dbenvpath/$dbfilename",
	-Flags		=> DB_CREATE,
	-Property	=> DB_DUP | DB_DUPSORT,
	-Subname	=> "dns_client",
	or die "Cannot create master.dns_client.db: $BerkeleyDB::Error\n";
################################################################################
#####   Usage
################################################################################
my $usage = <<EOT_USAGE;
Tool to add and remove IPs from the DLZ DB.
dlzdb-util [-a] [-z zone(domain)] [-t type] [-n name] [-v value] [-m mx-prefix]
		[-S serial] [-F refresh-time] [-R retry-time] [-E expire] [-H hostmaster]
		[-T minimumTTL] [-N primary-name-server]
dlzdb-util [-d] [-z zone(domain)]
dlzdb-util [-s] [-z zone(domain)]
ex:
Add record
dlzdb-util -a -z dmain.com -t A -n www -v 172.16.5.33 
dlzdb-util -a -z 5.16.172.in-addr.arpa -t PTR -n 34 -v www.dmain.com.
dlzdb-util -a -z dmain.com -t MX -n @ -v mail.domain.com. -m 10
dlzdb-util -a -z dmain.com -t TXT -n @ -v "text field here" -m 10
dlzdb-util -a -z dmain.com -t SOA -S 2006112401 -F 28800 -R 7200 -E 604800 -T 86400 -H hostmaster.domain.com. -N 01.dnsv.jp.
dlzdb-util -a -z 5.16.172.in-addr.arpa -t SOA -S 2006112401 -F 28800 -R 7200 -E 604800 -T 86400 -H hostmaster.domain.com. -N 01.dnsv.jp.
Delete record
dlzdb-util -d -z domain.com
Show record
dlzdb-util -s -z domain.com
EOT_USAGE
################################################################################
#####   Get options
################################################################################
my %options = ();
getopts('adsz:t:n:v:m:S:F:R:E:T:H:N:',\%options);
my $addflg = $options{'a'};
my $delflg = $options{'d'};
my $showflg = $options{'s'};
my $domain = $options{'z'};
my $type = $options{'t'};
my $name = $options{'n'};
my $value = $options{'v'};
my $mx = $options{'m'};
my $serial = $options{'S'};
my $refresh = $options{'F'};
my $retry = $options{'R'};
my $expire = $options{'E'};
my $minttl = $options{'T'};
my $hostmaster = $options{'H'};
my $nameserver = $options{'N'};
if($options{'h'}){
	print "$usage";
	exit;
}
################################################################################
#####  main part
################################################################################
if($addflg){
	&valid_chk();
} elsif($delflg || $showflg){
	if(&valid_fqdn($domain)){
		print "invalid domain[$domain]\n";
		exit;
	}
} #if($addflt)
## check if other process updating DB
#if(($addflg || $delflg) && -e $lockfile){
#	print "lockfile found. exiting...\n";
#	exit;
#} #if(($addflg...
if($addflg && $type eq 'SOA'){
	&CreateSOA($domain,$serial,$refresh,$retry,$expire,$minttl,$hostmaster,$nameserver);
} elsif($addflg) {
	&AddRecord($domain,$type,$name,$value,$mx);
} elsif($delflg) {
	&DelZone($domain);
} elsif($showflg) {
	&ShowZone($domain);
} else {
	print "$usage\n";
	exit;
}
################################################################################
#####   Data validation check
################################################################################
sub valid_chk{
## record type check
	if(&valid_type($type)){
		print "invalid record type [$type].\n";
		print "following record type are allowed.\n";
		print "SOA,A,MX,CNAME,NS,TXT,PTR\n";
		print "$usage";
		exit;
	} #if (&valid_type...
## check if you have enough data
	if($type eq 'A' || $type eq 'NS' || $type eq 'CNAME' || $type eq 'TXT'  || $type eq 'PTR'){
		unless($name && $value && $domain){
			print "not enough arguments.\n";
			print "A,NS,CNAME,TXT record requires 'domain','name' and 'value'\n";
			exit;
		}
	} #if($type eq 'A'...
	
	if($type eq 'MX'){
		unless($name && $value && $mx && $domain){
			print "not enough arguments.\n";
			print "MX record requires 'domain','name','value' and 'mx-prefix'\n";
			exit;
		}
	} #if($type eq 'MX')
	if($type eq 'SOA'){
		unless($serial && $refresh && $retry && $minttl
				&& $hostmaster && $domain){
			print "not enough arguments.\n";
			print "SOA record requires 'serial','refresh time','retry time',\n";
			print "'minimum ttl','hostmaster mail address' and 'domain'\n";
			exit;
		}
	} #if($type eq 'SOA')
## A record requires IP for value
	if($type eq 'A'){
		if(&valid_ip($value)){
			print "invalid value[$value] for A record.\n";
			print "A record requires IP.\n";
			exit;
		}
## MX,NS,CNAME record requires FQDN for value
	}elsif($type eq 'MX' || $type eq 'CNAME' || $type eq 'NS' || $type eq 'PTR'){
		if(&valid_fqdn($value)){
			print "invalid value[$value] for MX,CNAME,NS record.\n";
			print "MX,CNAME,NS,PTR record requires FQDN.\n";
			exit;
		}
## TXT record requires plain text for value
	}elsif($type eq 'TXT'){
		if(&valid_text){
			print "invalid value[$value] for TXT record.\n";
			print "TXT record doesn't allow special characters";
			exit;
		}
	} #if($type eq 'A')
## hostname should be FQDN or '*' or '@'
	if($name && &valid_host($name)){
		print "invalid hostname[$name].\n";
		exit;
	}
## serial,minttl,refresh,retry must be numeric
	if($serial && $serial =~ m/\D/){
		print "serial[$serial] must be number\n";
		exit;
	} #if($serial)
	if($refresh && $refresh =~ m/\D/){
		print "refresh[$refresh] must be number\n";
		exit;
	} #if($refresh)
	if($retry && $retry =~ m/\D/){
		print "retry[$retry] must be number\n";
		exit;
	} #if($retry)
	if($expire && $expire =~ m/\D/){
		print "expire[$expire] must be number\n";
		exit;
	} #if($expire)
	if($minttl && $minttl =~ m/\D/){
		print "minttl[$minttl] must be number\n";
		exit;
	} #if($minttl)
	if($hostmaster && &valid_fqdn($hostmaster)){
		print "hostmaster[$hostmaster] invalid.\n";
		exit;
	} #if($hostmaster)
	if($nameserver && &valid_fqdn($nameserver)){
		print "nameserver[$nameserver] invalid.\n";
		exit;
	} #if($nameserver)
} #sub valid_chk
################################################################################
#####  Subroutines for data validation check
################################################################################
sub valid_type {
	my $type = shift;
	if(!$types{$type}){
		return 1; #invalid type
	} else {
		return 0;
	} #unless
} #sub valid_type
sub valid_ip {
	my $ip = shift;
	if( $ip && ($ip =~ m/(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) &&
   ($1 < 256) && ($2 < 256) && ($3 < 256) && ($4 < 256) ){
		return 0;
	} else {
		return 1;
	}
} #sub valid_ip
sub valid_fqdn {
	my $fqdn = shift;
	if($fqdn =~ m/[^a-z0-9\-\_\.]/i){
		return 1; ## invalid character found
	} elsif(!($fqdn =~ m/[a-z]/i)){
		return 1; ## no alphabet found. given an IP?
	} else {
		return 0;
	}
} #sub valid_fqdn
sub valid_host {
	my $host = shift;
	if($host =~ m/[^a-z0-9\-\_\.\*\@]/i){
		return 1; ## invalid character found
	} else {
		return 0;
	}
} #sub valid_host
sub valid_text {
	my $text = shift;
	if($text =~ m/[^a-z0-9\-\_\.]/i){
		return 1; ## invalid character found
	} else {
		return 0;
	}
} #sub valid_text
################################################################################
#####   Initiate zone
################################################################################
sub CreateSOA {
	my $adddomain = shift;
	my $serial = shift;
	my $refresh = shift;
	my $retry = shift;
	my $expire = shift;
	my $minttl = shift;
	my $hostmaster = shift;
	my $nameserver = shift;
	$adddomain = lc($adddomain);
	$hostmaster = lc($hostmaster);
	$nameserver = lc($nameserver);
	if($type eq 'SOA' && $adddomain){
		print "Creating SOA for $adddomain... \n";
		## repID for SOA record is 1 (reserved)
		$cacheDnsData{"$adddomain @"} =
			"1 @ $minttl SOA $nameserver $hostmaster $serial $refresh $retry $expire $minttl";
		$cacheDnsClient{$adddomain} = '127.0.0.1';
		$cacheDnsZone{reverse("$adddomain")} = "";
	} #if ($type eq...
} #sub CreateSOA
################################################################################
#####   Adding record
################################################################################
sub AddRecord {
	my $domain = shift;
	my $type = shift;
	my $name = shift;
	my $value = shift;
	my $mx = shift if $type eq 'MX';
	$domain = lc($domain);
	$name = lc($name);
	$value = lc($value) if $type ne 'TXT';
	my $repid = &get_last_repid($domain,$name);
	my $ttl = &get_ttl($domain);
	if(($type eq 'A' || $type eq 'CNAME' || $type eq 'NS' || $type eq 'PTR') && $domain){
		print "add [$domain $name] [$repid $name $ttl $type $value]\n";
		$cacheDnsData{"$domain $name"} = "$repid $name $ttl $type $value";
		$cacheDnsXfr{$domain} = $name if $name ne '@';
	## TXT field value must be double quoted
	}elsif(($type eq 'TXT') && $domain){
		print "add [$domain $name] [$repid $name $ttl $type \"$value\"]\n";
		$cacheDnsData{"$domain $name"} = "$repid $name $ttl $type \"$value\"";
		$cacheDnsXfr{$domain} = $name if $name ne '@';
	## mx preference is set for MX record
	}elsif(($type eq 'MX') && $domain){
		print "add [$domain $name] [$repid $name $ttl $type $mx $value]\n";
		$cacheDnsData{"$domain $name"} = "$repid $name $ttl $type $mx $value";
		$cacheDnsXfr{$domain} = $name if $name ne '@';
	} #if (($type eq...
} #sub AddRecord
## every dns_data record has uniq ID it called replication ID.
## Pickup last replication ID for same key
sub get_last_repid {
	my $domain = shift;
	my $name = shift;
	my $repid = 1;
	my $datcur = $dns_data->db_cursor();
	my $datval;
	if($datcur->c_get("$domain $name",$datval, DB_SET) == 0){
		$repid++;
	}
	while($datcur->c_get("$domain $name",$datval, DB_NEXT_DUP) == 0){
		$repid++;
	}
	return $repid;
} #sub get_last_repid
## Pickup default TTL from SOA record
sub get_ttl {
	my $domain = shift;
	my $datcur = $dns_data->db_cursor();
	my $datval;
	my $ttl;
	$datcur->c_get("$domain @",$datval, DB_SET);
	while(1){
		if($datval =~ m/SOA/){
			$ttl = (split(/ /,$datval))[2];
			return $ttl;
		}
		unless($datcur->c_get("$domain @",$datval, DB_NEXT_DUP) == 0){
			last;
		}
	} #while(1)
} #sub get_ttl
################################################################################
#####   Delete zone
################################################################################
sub DelZone {
	my $deldomain = shift;
	$deldomain = lc($deldomain);
	if($deldomain){
		print "deleting zone ...\n";
		my $xfrcur = $dns_xfr->db_cursor();
		my $xfrval;
		my $datcur = $dns_data->db_cursor();
		my $datval;
		$xfrcur->c_get($domain,$xfrval,DB_SET);
		while(1){			
			$datcur->c_get("$deldomain $xfrval",$datval, DB_SET);
			while(1){
				#delete $cacheDnsData{"$deldomain $datval"};
				$datcur->c_del;
				unless($datcur->c_get("$deldomain $xfrval",$datval, DB_NEXT_DUP) == 0){
					last;
				}
			} #while(1)
			$xfrcur->c_del;
			unless($xfrcur->c_get($deldomain, $xfrval, DB_NEXT_DUP) == 0){
				last;
			}
		} #while (1)
		## remove SOA and generic records
		$datcur->c_get("$deldomain \@",$datval, DB_SET);
		while(1){
			#delete $cacheDnsData{"$deldomain \@"};
			$datcur->c_del;
			unless($datcur->c_get("$deldomain \@",$datval, DB_NEXT_DUP) == 0){
				last;
			}
		} #while(1)
		$xfrcur->c_del;
		delete $cacheDnsXfr{$deldomain};
		delete $cacheDnsClient{$deldomain};
		delete $cacheDnsZone{reverse("$deldomain")};
	} #if ($deldomain)
} #sub DelZone
################################################################################
#####   show zone status
################################################################################
sub ShowZone {
	my $domain = shift;
	$domain = lc($domain);
	print "status for domain $domain\n";
	if(exists($cacheDnsZone{reverse($domain)})){
		print "dns_zone: [" . reverse($domain) . "]\n";
	}else{
		print "domain $domain does not exist\n";
		return;
	}
	print "dns_client: [" . $domain . "] [" . $cacheDnsClient{$domain} . "]\n";
	my $xfrcur = $dns_xfr->db_cursor();
	my $xfrval;
	my $datcur = $dns_data->db_cursor();
	my $datval;
	## get entry for domain from dns_xfr database
	$xfrcur->c_get($domain,$xfrval,DB_SET);
	while(1){
		print "dns_xfr: [$domain] [$xfrval]\n";
		$datcur->c_get("$domain $xfrval",$datval, DB_SET);
		while(1){
			print "dns_data: [$domain $xfrval] [$datval]\n";
			unless($datcur->c_get("$domain $xfrval",$datval, DB_NEXT_DUP) == 0){
				last;
			}
		} #while(1)
		unless($xfrcur->c_get($domain, $xfrval, DB_NEXT_DUP) == 0){
			last;
		}
	} #while (1)
	## lookup SOA record and generic zone records
	$datcur->c_get("$domain @",$datval, DB_SET);
	print "dns_data: [$domain @] [$datval]\n";
	while($datcur->c_get("$domain @",$datval, DB_NEXT_DUP) == 0){
		print "dns_data: [$domain @] [$datval]\n";
	}
	undef $xfrcur;
	undef $datcur;
} #sub ShowZone

source:http://lundman.net/wiki/index.php/DLZUtil

发表评论