source: npl/internetserver/djbdns/djb_update.pl @ 08cf024

Last change on this file since 08cf024 was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100755
File size: 7.2 KB
Line 
1#!/usr/bin/perl
2#
3##########################################################################
4#
5# Filename:     djb_update.pl
6# Description:  Dynamic DNS-DHCP update scrypt
7# Author:       Michael Stella
8# Created:      November 10, 1998
9# Last Updated: December 05, 2002
10# Email:        kazin@thismetalsky.org
11# HomePage:     http://www.thismetalsky.org/magic/projects/dhcp_dns.html
12#
13###########################################################################
14#
15#  This code is Copyright (c) 1998-2002 by Michael Stella
16#
17#  NO WARRANTY is given for this program.  If it doesn't
18#  work on your system, sorry.  If it eats your hard drive,
19#  again, sorry.  It works fine on mine.  Good luck!
20#
21#  Note the lack of the GPL statement.  I'm done with that, this is free
22#  software.  Just let me know if you're using it, I'm curious.
23#
24###########################################################################
25#
26# This script reads a dhcpd.leases file and dynamically updates tinydns with
27# hostname and ip information. 
28#
29# It assumes that your DHCP server recieves hostnames from the
30# clients, and that your clients offer their hostnames to the server.
31# Some versions of Linux DHCP clients don't do that.  I use ISC's
32# DHCPD, found at http://www.isc.org - though others may work just
33# fine.
34#
35# As of version 1.0 you MUST use djbdns. 
36#
37###########################################################################
38#
39# 11/23/1998 - fixed the rarp stuff
40# 02/23/1999 - added support for multiple subnets
41# 02/24/1999 - improved lease file processing
42# 04/15/1999 - switched to dynamic DNS update - BIND 8 dynamic capabilities
43# 04/18/1999 - improved handling of client hostnames, to catch dumb user
44#                               problems improved error handling Thanks to Wayne Roberts
45#                               <wroberts1@cx983858-b.orng1.occa.home.com>
46# 04/20/1999 - bugfix, error messages now show up correctly.
47# 08/24/1999 - switched to using logger for logging to system log files
48#              Thanks to Michael Matsumura <michael@limit.org>
49# 08/27/1999 - Actually figured out how to update the reverse-lookup zones,
50#              Thanks again to Michael Matsumura.
51# 02/13/2001 - Ditched BIND, moved to djbdns
52# 05/25/2001 - Thanks to Nate Keegan <nate.keegan@cityofprescott.net> -
53#                      apparently I didn't think to allow configuring the dnscache
54#                      path in the makefile.  That's been fixed.
55# 12/05/2002 - Thanks to Ryan VanderBijl <rvbijl-dhcpdns@vanderbijlfamily.com>
56#              for noticing that we should make sure that an entry doesn't
57#              exist in the static file!
58#              And thanks for writing his own changelog entry to MY code,
59#              praising himself.  :)
60#
61###########################################################################
62
63use strict;
64$|=1;
65
66###########################################################################
67### Globals - you can change these as needed
68
69# Domain name
70my $domain_name        = `hostname -f`;
71chomp($domain_name);
72
73# DHCPD lease file
74my $lease_file         = "/var/state/dhcp/dhcpd.leases";
75
76## where does tinydns stuff live?
77my $tinydnspath        = "/home/system/tinydns";
78
79# tinydns text database files
80my $dhcp_dnsfile       = "/home/system/tinydns/dhcp.conf";
81my $static_dnsfile     = "/home/system/tinydns/static.conf";
82
83# number of seconds to check the lease file for updates
84my $update_freq        = 5;
85
86my $debug = 0;
87
88###########################################################################
89### Don't mess with anything below unless you REALLY need to modify the
90### code.  And if you do, please let me know, I'm always interested in
91### in improving this program.
92
93# Make a pid file
94`echo $$ > /var/run/djb_update.pid`;
95
96my $logstr;
97
98# last modified time
99my $modtime = 0;
100
101use vars qw (%db %static);
102
103my $version = "1.1.0";
104
105###########################################################################
106# Main Loop
107while (1) {
108
109  # check the file's last updated time, if it's been changed, update
110  # the DNS and save the modified time.  This will ALWAYS run once - on
111  # startup, since $modtime starts at zero.
112
113  my @stats = stat ($lease_file);
114  if ($stats[9] > $modtime) {
115
116        # clear the old hash
117        undef %db;
118
119        printf STDERR "dhcpd.leases changed - updating DNS\n";
120        $modtime = $stats[9];
121
122        ## if error reading static dns file, dont do any update
123        next unless (&read_static_dns); 
124
125        &read_lease_file;
126        &update_dns;
127  }
128
129  # wait till next check time
130  sleep $update_freq;
131
132} # end main
133###########################################################################
134
135
136## read in the static file,  return 1 if we couldn't
137sub read_static_dns {
138    %static = (); ## clear the list
139    unless (open(DNSFILE, $static_dnsfile)) {
140            print STDERR "Can't open static DNS file: won't generate dns from dhcp\n";
141            return 0;
142    }
143    while(defined($_ = <DNSFILE>)) {
144            chop;
145            next if /^\s*#/ || /^\s*$/;  # skip comments/blanks
146            s/^.(([^:]+):([^:]+)):?.*$/$1/;
147            $static{lc $2} = $3;
148    }
149    close(DNSFILE);
150    return 1;
151}
152
153### write out the tinydns import file
154sub update_dns {
155        my ($ip, $hostname);
156
157        unless (open(DNSFILE, ">$dhcp_dnsfile")) {
158                print STDERR "Can't open dhcp DNS file\n";
159                return;
160        }
161
162        while (($hostname,$ip) = each (%db)) {
163                # in the future, set this to the end of the lease time,
164                # i.e. do some math on that.
165                print DNSFILE "=$hostname.$domain_name:$ip:5\n";
166        }
167        close DNSFILE;
168
169        `cd $tinydnspath && make > /dev/null`;
170}
171
172
173### reads the lease file & makes a hash of what's in there.
174sub read_lease_file {
175
176  unless (open(LEASEFILE,$lease_file)) {
177        #`logger -t dns_update.pl error opening dhcpd lease file`;
178        print STDERR "Can't open lease file\n";
179        return;
180  }
181
182  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);
183  my $curdate = sprintf "%04d%02d%02d%02d%02d%02d",
184                ($year+1900),($mon+1),$mday,$hour,$min,$sec;
185
186  ## Loop here, reading from LEASEFILE
187  while (<LEASEFILE>) {
188        my ($ip, $hostname, $mac, $enddate,$endtime);
189
190        if (/^\s*lease/i) {
191               
192          # find ip address
193          $_ =~ /^\s*lease\s+(\S+)/;
194          $ip = $1;
195         
196          # do the rest of the block - we're interested in hostname,
197          # mac address, and the lease time
198          while ($_ !~ /^}/) {
199            $_ = <LEASEFILE>;
200                # find hostname
201                if ($_ =~ /^\s*client/i) {
202                  #chomp $_;
203                  #chop $_;
204                  $_ =~ /\"(.*)\"/;
205                  $hostname = $1;
206                 
207                  # change spaces to dash, remove dots - microsoft
208                  # really needs to not do this crap
209                  $hostname =~ s/\s+/-/g;
210                  $hostname =~ s/\.//g;
211                }
212                # get the lease end date
213                elsif ($_ =~ /^\s*ends/i) {
214                        $_ =~ m/^\s*ends\s+\d\s+([^;]+);/;
215                        $enddate = $1;
216                        $enddate =~ s|[/: ]||g;
217                }
218          }
219          # lowercase it - stupid dhcp clients
220          $hostname = lc $hostname; 
221
222          ($debug < 1 ) || print STDERR "$hostname $ip $enddate $curdate\n";
223         
224          ## if the hostname is defined in the static list, skip it
225          if (exists $static{"$hostname.$domain_name"}) {
226              print STDERR "Skipping $hostname.$domain_name dhcp dns " .
227                           "entry: static entry with same name exists\n";
228              next;
229          }
230
231          # Store hostname/ip in hash - this way we can do easy dupe checking
232          if (($hostname ne "") and ($enddate > $curdate)) {
233              $db{$hostname} = $ip;
234          }
235        }
236  }
237  close LEASEFILE;
238}
239
Note: See TracBrowser for help on using the repository browser.