#!/usr/bin/perl #################################################################### # Edit These for Your Domain # #################################################################### $LEASES = "/var/lib/dhcp3/dhcpd.leases"; $DOMAIN = "lan.domain.org"; $REVERSE = "168.192.in-addr.arpa"; $FORWARD_BASE = "ou=forward,ou=dns,dc=lan,dc=domain,dc=org"; $REVERSE_BASE = "ou=reverse,ou=dns,dc=lan,dc=domain,dc=org"; $USER = 'uid=dnsupdate,ou=users,dc=lan,dc=domain,dc=org'; $PASSWORD = "password"; $LDAP_HOST = 'localhost'; $UPDATE_TIME = 30; # In Seconds $AUTO_VERIFY = 0; # Set this to positive if you would like dhcp2ldap # to periodically re-read the entire leases file # even if the time stamp hasn't changed # # It will perform the auto-verify after # ($AUTO_VERIFY * $UPDATE_TIME) seconds # # This is probably a good idea unless your parse times # are incredibly high #################################################################### # Do Not Edit Below This Line # #################################################################### use IO::Socket; use Net::LDAP; print "Initializing LDAP Connection..."; $ldap = Net::LDAP->new($LDAP_HOST) or die "$@"; $ldap->bind($USER, password => $PASSWORD) or die "$!\n"; print "Done\n"; $params = shift; if($params eq "-d"){ daemonize(); } if($params eq "-h"){ usage(); exit; } while(1){ if(changed($LEASES)){ parse($LEASES); do_stuff(); } sleep $UPDATE_TIME; } sub changed{ my $file = shift; my $curstat = (stat($file))[9]; if($AUTO_VERIFY){ $check_count++; } if($oldstat != $curstat || (($check_count == $AUTO_VERIFY) && $AUTO_VERIFY)){ $oldstat = $curstat; $check_count = 0; print "Timestamp change or AUTO_VERIFY triggered...\n"; return 1; } else{ return 0; } } sub daemonize{ chdir '/'; umask 0; open STDIN, '/dev/null'; open STDOUT, '/dev/null'; open STDERR, '/dev/null'; if(fork()){ exit; } else{ setsid; return; } } sub parse{ my $ip,$hostname; open IN, shift or die "Could not open leases file: $!\n"; while($_ = ){ if(/^#/){ next; } chomp $_; if(/lease/){ /\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}/; $ip = $&; while(!(/\}/)){ $_ = ; if(/client-hostname/){ /\".*\"/; $_ = $&; /\w+\S*\w+/; $_ = $&; $hostname = lc; $hosts{$hostname} = $ip; } } } $line = ""; }; close IN; } sub do_stuff{ my $readd, $host, $ip, $hostname; while(($host,$ip) = each(%hosts)){ $hostname = $host . "." . $DOMAIN . "."; $lookup = ""; eval{$lookup = inet_ntoa((gethostbyname("$host.$DOMAIN"))[4]); }; ($first,$second,$third,$fourth) = split(/\./,$ip); if($lookup eq $ip){ next; } elsif($lookup ne $ip){ print "Removing inaccurate records for $host...\n"; $result = $ldap->delete("relativeDomainName=$host," . $FORWARD_BASE); $result->code && warn "failed to remove entry: ", $result->error ; $result = $ldap->delete("relativeDomainName=$fourth.$third," . $REVERSE_BASE); $result->code && warn "failed to remove entry: ", $result->error ; $readd = 1; } if(!$lookup || $readd){ print "Adding entry for $host at $ip...\n"; $result = $ldap->add( "relativeDomainName=$host," . $FORWARD_BASE, attr => [ 'relativeDomainName'=> $host, 'objectClass'=> ['top','dNSZone'], 'dNSTTL' => '7200', 'zoneName' => $DOMAIN, 'aRecord' => $ip ] ); $result->code && warn "failed to add entry: ", $result->error ; $result = $ldap->delete("relativeDomainName=$fourth.$third," . $REVERSE_BASE); $result->code && warn "failed to remove entry: ", $result->error ; $result = $ldap->add( "relativeDomainName=$fourth.$third," . $REVERSE_BASE, attr => [ 'relativeDomainName'=> "$fourth.$third", 'objectClass'=> ['top','dNSZone'], 'dNSTTL' => '7200', 'zoneName' => $REVERSE, 'pTRRecord' => $hostname ] ); $result->code && warn "failed to add entry: ", $result->error ; $readd = 0; } } } sub usage{ print < under the GNU GPL Usage: dhcp2ldapd [-d | -h] -d runs dhcp2ldap in daemon mode -h displays this help message Please edit the config variables before running! EOF } ############################################################################# #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 #############################################################################