diff --git a/DDNS.pm b/DDNS.pm index 8eddcc0..b3264fb 100644 --- a/DDNS.pm +++ b/DDNS.pm @@ -5,7 +5,7 @@ use warnings; use Net::DNS; use File::Temp qw/tempfile/; -our $VERSION = '0.1'; +our $VERSION = '0.2'; sub new { my $me = shift; @@ -17,10 +17,20 @@ sub new { }, $me; } -sub _fqdn { - my ($dom) = @_; +sub _validateTypeOrDie { + my ($t) = @_; - return $dom . "_vhosts.private.invalid."; + die "Invalid type" + unless ($t =~ /^_(vhosts|hostedservers|pureslave|custom)$/); +} + +sub _fqdn { + my ($dom, $type) = @_; + $type ||= '_vhosts'; + + _validateTypeOrDie($type); + + return $dom . "$type.private.invalid."; } sub _validateOrDie { @@ -36,7 +46,7 @@ sub _lookupOrDie { my ($dom) = @_; _validateOrDie($dom); - my $fqdn = _fqdn($dom); + my $fqdn = _fqdn($dom, '_vhosts'); my $res = Net::DNS::Resolver->new; my $query = $res->query($fqdn, "TXT"); @@ -77,29 +87,11 @@ sub __docmd { unlink $filename; } -# Add a new vhost domain by adding a DDNS record that the slaves will notice. -sub addvhost { - my ($this, $dom, $master) = @_; - _validateOrDie($dom); - my $fqdn = _fqdn($dom); +sub _gethosts { + my ($this, $type) = @_; - $this->__docmd("update add $fqdn 60 TXT $master"); - $this->cleanup(); -} - -sub delvhost { - my ($this, $dom) = @_; - - _lookupOrDie($dom); - my $fqdn = _fqdn($dom); - - $this->__docmd("update delete $fqdn TXT"); - $this->cleanup(); -} - -sub getvhosts { - my ($this) = @_; + _validateTypeOrDie($type); my $fh; open($fh, "dig -t AXFR \@127.0.0.1 private.invalid. |") @@ -108,7 +100,7 @@ sub getvhosts { my @vh; while (<$fh>) { - if (/^(\S+)._vhosts.private.invalid.\s+\d+\s+IN\s+TXT\s+\"(.+)\"$/) { + if (/^(\S+).$type.private.invalid.\s+\d+\s+IN\s+TXT\s+\"(.+)\"$/) { push (@vh, { zone => $1, master => $2 }); } @@ -117,6 +109,31 @@ sub getvhosts { return @vh; } +sub add { + my ($this, $dom, $master, $type) = @_; + _validateOrDie($dom); + my $fqdn = _fqdn($dom, $type); + + $this->__docmd("update add $fqdn 60 TXT $master"); + $this->cleanup(); +} + +sub del { + my ($this, $dom, $type) = @_; + + _lookupOrDie($dom); + my $fqdn = _fqdn($dom, $type); + + $this->__docmd("update delete $fqdn TXT"); + $this->cleanup(); +} + +sub get { + my ($this, $type) = @_; + + return $this->_gethosts($type); +} + sub cleanup { my ($this) = @_; # Merge the .jnl file in with the domain file diff --git a/Makefile.PL b/Makefile.PL index d0898cb..0efe96a 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -11,6 +11,9 @@ WriteMakefile( 'bin/del-vhost', 'bin/list-vhosts', 'bin/sync-master-vhosts', + 'bin/add-slave', + 'bin/del-slave', + 'bin/list-slaves', ], 'AUTHOR' => 'Jorj Bauer ', ); diff --git a/bin/add-slave b/bin/add-slave new file mode 100755 index 0000000..088fb1f --- /dev/null +++ b/bin/add-slave @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Martnet::DDNS; +use Regexp::Common qw/net/; + +my $host = shift || die "No zonename provided"; +my $master = shift || die "No master DNS IP provided"; + +die "Zonename must end in a dot" + unless ($host =~ /^[a-zA-Z0-9\.\-\_]+\.$/); + +my $regex = $RE{net}{IPv4} . '|' . $RE{net}{IPv6}; +die "Master must be an IPv4 or IPv6 address" + unless ($master =~ /^$regex$/); + +my $ddns = Martnet::DDNS->new(); +$ddns->add($host, $master, '_pureslave'); diff --git a/bin/add-vhost b/bin/add-vhost index dec4526..605ef0c 100755 --- a/bin/add-vhost +++ b/bin/add-vhost @@ -17,4 +17,4 @@ die "Master must be an IPv4 or IPv6 address" unless ($master =~ /^$regex$/); my $ddns = Martnet::DDNS->new(); -$ddns->addvhost($host, $master); +$ddns->add($host, $master, '_vhosts'); diff --git a/bin/del-slave b/bin/del-slave new file mode 100755 index 0000000..4c0459e --- /dev/null +++ b/bin/del-slave @@ -0,0 +1,14 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Martnet::DDNS; +use Regexp::Common qw/net/; + +my $host = shift || die "No zonename provided"; + +die "Zonename must end in a dot" + unless ($host =~ /^[a-zA-Z0-9\-\_\.]+\.$/); + +my $ddns = Martnet::DDNS->new(); +$ddns->del($host, '_pureslave'); diff --git a/bin/del-vhost b/bin/del-vhost index 185a310..582115a 100755 --- a/bin/del-vhost +++ b/bin/del-vhost @@ -11,4 +11,4 @@ die "Hostname must end in a dot" unless ($host =~ /^[a-zA-Z0-9\-\_\.]+\.$/); my $ddns = Martnet::DDNS->new(); -$ddns->delvhost($host); +$ddns->del($host, '_vhosts'); diff --git a/bin/list-slaves b/bin/list-slaves new file mode 100755 index 0000000..6dfaa80 --- /dev/null +++ b/bin/list-slaves @@ -0,0 +1,12 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Martnet::DDNS; + +my $ddns = Martnet::DDNS->new(); + +my @vh = $ddns->get('_pureslave'); +foreach my $i (sort {$a->{zone} cmp $b->{zone}} @vh) { + print $i->{zone}, ". master: ", $i->{master},"\n"; +} diff --git a/bin/list-vhosts b/bin/list-vhosts index 90c51fb..da4fedf 100755 --- a/bin/list-vhosts +++ b/bin/list-vhosts @@ -6,7 +6,7 @@ use Martnet::DDNS; my $ddns = Martnet::DDNS->new(); -my @vh = $ddns->getvhosts(); +my @vh = $ddns->get('_vhosts'); foreach my $i (sort {$a->{zone} cmp $b->{zone}} @vh) { print $i->{zone}, ". master: ", $i->{master},"\n"; } diff --git a/bin/sync-master-vhosts b/bin/sync-master-vhosts index c2df879..6c180f6 100755 --- a/bin/sync-master-vhosts +++ b/bin/sync-master-vhosts @@ -7,7 +7,7 @@ use File::Temp qw/tempfile/; my $ddns = Martnet::DDNS->new(); -my @vh = $ddns->getvhosts(); +my @vh = $ddns->get('_vhosts'); # For each virtual host, generate a vhost zone file if there isn't one my $changecount = 0; diff --git a/sync-master-vhosts.cron b/sync-master-vhosts.cron index fc52996..bb4224c 100644 --- a/sync-master-vhosts.cron +++ b/sync-master-vhosts.cron @@ -1,2 +1,2 @@ MAILTO=jorj@jorj.org -* * * * * bind /usr/local/bin/sync-master-vhosts +* * * * * root /usr/local/bin/sync-master-vhosts