#!/usr/bin/perl -w # Copyright (c) 2007 Ted Unangst # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # Copies hostnames from a dhcpd leases file to named zone files # Existing hosts or IPs are not updated # # Usage: lease2zone.pl dhcpd.leases zonefile.dom zonefile.dom.rev # Then pkill -HUP named use strict; @ARGV == 3 or die "not enough arguments: leasefile zonefile reversezone"; # regexes for hostnames and ips my $hregex = "[a-zA-Z0-9-]+"; my $iregex = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"; my %clients; # dhcpd clients my %hosts; # hostnames already governed by zone my $domain; # domain name from $ORIGIN # find all the clients open(LEASEFILE, "<", $ARGV[0]) or die "can't open lease file"; my $ip; #temp var while () { if (/lease\s($iregex)\s{/) { $ip = $1; } elsif (/client-hostname "($hregex)";/) { $clients{$ip} = $1; } } close(LEASEFILE); foreach $ip (keys %clients) { #print "$ip is named $clients{$ip}\n"; } # pass through zone files and remove clients with existing hostnames open(ZONEFILE, "<", $ARGV[1]) or die "o"; while () { if (/^($hregex)\s+IN\s+A\s+($iregex)/) { delete($clients{$2}); $hosts{$1} = $2; } elsif (/^\$ORIGIN\s+(($hregex\.)+)/) { #print "domain is $1\n"; $domain = $1; } } close(ZONEFILE); # same with rev zone file open(ZONEFILE, "<", $ARGV[2]) or die "o"; while () { if (/^(\d+)\s+PTR\s+($hregex)/) { delete($clients{$1}); $hosts{$2} = $1; } } close(ZONEFILE); # we have the list of new client ips now # do another sweep to remove taken hostnames foreach $ip (keys %clients) { my $hostname = $clients{$ip}; #print "new ip $ip is named $hostname "; if (defined($hosts{$hostname})) { #print "taken\n"; delete($clients{$ip}); } else { #print "new host\n"; } } # add the new clients to the right files open(ZONEFILE, ">>", $ARGV[1]) or die "can't append zone file"; foreach $ip (keys %clients) { my $hostname = $clients{$ip}; print ZONEFILE "$hostname\tIN\tA\t$ip\n"; } close(ZONEFILE); open(ZONEFILE, ">>", $ARGV[2]) or die "can't append rev zone file"; foreach $ip (keys %clients) { my $hostname = $clients{$ip}; $ip =~ s/\d+\.\d+\.\d+\.(\d+)/$1/; print ZONEFILE "$ip\t\tPTR\t$hostname.$domain\n"; } close(ZONEFILE);