/usr/sbin/autodns-dhcp_ddns is in autodns-dhcp 0.9.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | #!/usr/bin/perl
#
# autodns-dhcp_ddns
# The procedure here is simple.
# If a record has been added since the last change, delte any previous
# mentions and add a new record. This can lead to expired records but this
# should not be a problem.
#
# Copyright (C) 1999 Stephen Carville
#
# 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
# use inverse time functions
use Time::Local;
use strict;
use Socket;
my $DEBUG = 0;
my $version="0.7";
# these are the only valid character for a machine name -- used in checkname()
my $NAMECHARS="[a-zA-Z0-9\\-]";
# define the extra filters to apply for machine names -- in checkname()
# these filters allow for extra name filtering if needed. For example, this
# filter only allows "legitimate" names into my employers's DNS
#my $CYPFILTER="cy(pci|pca|hpr|sun)t\\d{2}|\\d{3}";
# these are the active filters -- set this to "" if you don't need any extra
# filters.
my(@filters)=("");
# filter for a bogus ethernet address (look for seven octets :-)
#my $ETHER="\\w\\w:\\w\\w:\\w\\w:\\w\\w:\\w\\w:\\w\\w:\\w\\w";
# lets try filtering on the first two octets of the bogus address this may
# cause a legitimate address to choke but all the info I can find indicates
# the 52:41 sequence has never been issued to any manufacturer
my $ETHER="\^52:41:";
# nsupdate command strings
my $IFEXIST="prereq yxdomain";
my $IFNOTEXIST="prereq nxdomain";
my $ADD="update add";
my $DELETE="update delete";
# use a default time to live of one hour
my $TTL="3600";
my $LEASE_TEMP="dhcpd.leases.last";
# my $UPDATE="nsupdate.data";
my (%newip,%newmac,%newname,$hostname,$hostip,$hard);
my ($nowtime,$lastime,$ip,$linea);
my ($home,$dhcpdleases,$update,$dhcpup,$dhcpdleases_temp,$domain,$dhcpdconf);
my (@ddnscommand,@OUTPUT,@SALIDA);
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks);
# get the program environment variables
$home = $ENV{DDNSHOME};
$dhcpdleases = $ENV{DHCPDLEASES};
$update = $ENV{UPDATE};
$dhcpdleases_temp = $ENV{DHCPDLEASES_TEMP};
$dhcpdconf = $ENV{DHCPDCONF};
$domain = $ENV{DNS_DOMAIN};
$dhcpup = $ENV{DHCPUP};
# get the current GMT
$nowtime=time();
# get last update time;
if (-e "$home/$LEASE_TEMP") {
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks)=stat("$home/$LEASE_TEMP");
$lastime=$mtime;
}
else {
$lastime=0;
}
# now copy the dhcpd.leases file over to DDNSHOME
system "/bin/cp", $dhcpdleases, $dhcpdleases_temp;
# get the new data
# I have changed this to two global hashes:
# newip is indexed by IP and contains the last MAC asociated with that IP
# newmac is indexed by MAC and contains the last IP and the name for that MAC
load_new_data($nowtime,$lastime);
unless (open OUTPUT, ">$update") {
print STDERR "Unable to open $update\n";
die;
}
unless (open SALIDA, ">$dhcpup") {
print STDERR "Unable to open $dhcpup\n";
die;
}
unless (open ENTRADA, "<$dhcpdconf") {
print STDERR "Unable to open $dhcpdconf\n";
die;
}
if ($DEBUG == 1) {
*OUTPUT=*STDERR;
}
# We parse the dhcpd.conf file getting the already fixed parameters to make
# sure a MAC doesn't get two IPs and fixed IPs aren't asigned again.
# I know this can only happen in a few cases, but this has gotta be strong.
while (<ENTRADA>) {
if (/host.+hardware ethernet (.+); fixed-address (.+);.+/) {
delete $newmac{$1};
delete $newip{$2};
}
}
seek(ENTRADA,0,0);
# now do the adds
#For each of the found ips (sorted numerically)
foreach $ip (sort ipcomp keys (%newip)) {
#Get the mac for the ip we'll work with
$hard=$newip{$ip};
#For that mac, get it's IP and the host name
($hostip,$hostname) = split(/ /,$newmac{$hard});
#Do not add the host if the IP doesn't match the one we were asking for
unless ($hostip eq $ip) { next; }
#Do not add the host if the name is not valid acording to our criteria
unless (checkname($hostname)) { next; }
#Do not add the host if the name already exists on dns
if (gethostbyname("$hostname.$domain.")) { next; }
#Check if we had added the same name on this round (only add the first one)
if ( $newname{$hostname} ) { next; }
#Mark the name so that we don't add the name more than once
$newname{$hostname} = 1;
@ddnscommand=add_record($hostname,$ip);
while (($linea=<ENTRADA>) ne "range $ip;\n") {
print SALIDA $linea
}
print SALIDA "host $hostname {hardware ethernet $hard; fixed-address $ip;}\n";
print OUTPUT @ddnscommand;
}
while ($linea=<ENTRADA>) { print SALIDA $linea }
close SALIDA;
close ENTRADA;
#
# check an ethernet id
# Windows will try to grab multiple addresses. I can't stop DHCP from
# granting them but I can make sure only addresses granted to valid
# ethernet addresses get into the DNS
#
sub checkethid {
my ($ether)=@_;
if ($ether =~m/$ETHER/) {
return 1;
}
return 0;
}
#
# check a name to see if it is a valid name
# first check the name is FQDN valid then does it fit our
# internal naming policy. I may add an exception list here later.
#
sub checkname {
my ($name)=@_;
my (@array,$letter,$filter);
@array=split(//,$name);
foreach $letter(@array) {
unless ($letter=~m/$NAMECHARS/) {
return 0;
}
}
foreach $filter (@filters) {
unless ($name=~m/$filter/) {
return 0;
}
}
return 1;
}
#
# add a record
#
sub add_record {
my ($machine,$address) = @_;
my ($xaddress,@c,$arpa);
# get reverse lookup for the new address
$arpa=get_arpa($address);
# add the new forward record
push @c, "$ADD $machine.$domain $TTL IN A $address\n\n";
# add the new reverse record
push @c, "$ADD $arpa $TTL IN PTR $machine.$domain\n\n";
return @c;
}
#
# get the reverse lookup value for an address
#
sub get_arpa {
my ($address) = @_;
my ($arpa,$a,$b,$c,$d);
($a,$b,$c,$d) = split /\./, $address;
$arpa = "$d.$c.$b.$a.in-addr.arpa";
return $arpa;
}
#
# load the current dhcpd.leases file
# here we look at the hostname, the lease start time and the lease end time.
# if a hostname does not exist, there will be no entry made in DNS.
sub load_new_data{
my ($nowtime,$lastime)=@_;
my(@DATA,$hn,$ip,$startime,$endtime,@date,@time,@a,$hard,$bogus);
unless (open DATA,"$dhcpdleases_temp") {
print STDERR "autodns-dhcp_ddns $version: can't open $dhcpdleases_temp\n";
die;
}
# set the bogus ethernet id flag to 0
$bogus=0;
# parse each line in the file
while (<DATA>) {
# get rid of semicolons and quote marks
$_=~s/\"//g;
$_=~s/\;//g;
@a=split(" ",$_);
# get IP address
if ($a[0] eq "lease") {
# start of a new entry so reset bogus
$bogus=0;
$ip= $a[1];
}
# get the starting GMT for the lease
if ($a[0] eq "starts") {
@date=split("/",$a[2]);
@time=split(":",$a[3]);
$startime=timegm($time[2],$time[1],$time[0],$date[2],$date[1]-1,$date[0]);
}
# get the ending GMT for the lease
if ($a[0] eq "ends") {
@date=split("/",$a[2]);
@time=split(":",$a[3]);
$endtime=timegm($time[2],$time[1],$time[0],$date[2],$date[1]-1,$date[0]);
}
# check if the Ethernet address is legit. Some Win boxen will request
# multiple addresses using bogus ethernet id's (yuck!)
if ($a[0] eq "hardware") {
# if it is a bogus address go to the next entry
if (checkethid($hard=$a[2])) {
$bogus=$a[2];
next;
}
}
# since dhcpd adds new leases to the end of the file, it is assumed that
# a later entry is the most likely to be correct. Therefore just overwrite
# any duplicate hostnames found
if ($a[0] eq "client-hostname") {
$hn=lc($a[1]);
# is this lease new and valid? (is it worthwhile here to check for bogosity?)
if ($startime > $lastime && $endtime > $nowtime) {
unless ($bogus) {
$newip{$ip} = $hard;
$newmac{$hard} = "$ip $hn";
}
}
# if the lease is not valid and not bogus we remove the posible valid leases
# that had been assigned before.
else {
unless ($bogus) {
delete $newip{$ip};
delete $newmac{$hard};
}
}
}
}
close DATA;
}
sub ipcomp {
my @ip1 = split(/\./,$a);
my @ip2 = split(/\./,$b);
my $ip1n = (((($ip1[0]*256)+$ip1[1])*256)+$ip1[2])*256+$ip1[3];
my $ip2n = (((($ip2[0]*256)+$ip2[1])*256)+$ip2[2])*256+$ip2[3];
return ($ip1n <=> $ip2n);
}
|