#!/usr/bin/perl -w
#  dyndns.cgi - Updates a dynamic dns record.
#  Copyright (C) 1999 Tom Rothamel
#  
#  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; see the file COPYING.  If not, write to
#  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
#  Boston, MA 02111-1307, USA.


### Documentation

# This needs the Net::DNS module. Install it in your apache web tree, 
# in an access-controlled directory. The directory must be set up so 
# that the username used to access it is the prefix of the host that
# will be updated. (So that if I use the user "tux_penguin" to access
# the script, the host tux_penguin.$domain will be updated.)

# The DNS server must allow updates from the web server. (For Bind 8, 
# the line "allow-updates { <web-server-ip>; };" must be part of the
# zone config.

# The lines below are valid for my setup, but need to be tuned for 
# other setups.


### Configuration

# The domain that the host is part of.
my $domain = "dyn.onegeek.org";

# The servers to be updated.
my @servers = ("asuka.computerworks.net", "ziggy.computerworks.net");



use Net::DNS;
print <<EOT;
Content-Type: text/plain

Attempting DNS update:
Host = $ENV{REMOTE_USER}, Addr = $ENV{REMOTE_ADDR}
EOT

$res = new Net::DNS::Resolver;
$query = $res->search($ENV{REMOTE_ADDR});
if ($query) {
        foreach $rr ($query->answer) {
        	next unless $rr->type eq "PTR";
                $reverse = $rr->ptrdname;
		$reverse = "CNAME $reverse.";
	}
} else {
	$reverse = "A $ENV{REMOTE_ADDR}";
} 

print <<EOT;
Record = $reverse
EOT

for $i (@servers) {
	dodnsupdate($ENV{REMOTE_USER}, $domain, $reverse, $i);
}

sub dodnsupdate ($$$$) {
  my $host = shift;
  my $domain = shift;
  my $address = shift;
  my $server = shift;
  
  $update = new Net::DNS::Update($domain);
  
  $update->push("update", rr_del("$host.$domain."));
  $update->push("update", rr_add("$host.$domain. 300 IN $address"));
  
  $res = new Net::DNS::Resolver;
  $res->nameservers($server);
  $reply = $res->send($update);
  
  if (defined $reply) {
    if ($reply->header->rcode eq "NOERROR") {
      print "$server: Update succeeded\n";
    }
    else {
      print "$server: Update failed: ", $reply->header->rcode, "\n";
    }
  }
  else {
    print "$server: Update failed: ", $res->errorstring, "\n";
  } 
}
