#! /usr/bin/perl -w # # Copyright 2001-2003 August Hoerandl (august.hoerandl@gmx.at) # http://elina.htlw16.ac.at/~hoerandl # # This program is free software. You can redistribute it and/or modify # it under the terms of the GNU General Public License # # create config from database # dhcpd.conf # named forward + reverse # # 1) one entry for each dhcp client # ip addr, name, mac, comment # 172.16.10.17, ws231-a1, 00:05:04:03:02:01, whatever # # you may use a mac 00:00 for to get an entry into dns but # no dhcp entry # # 2) one line for each cname (hostname alias) # CNAME, name, original name # CNAME, time, ns # # the server is assumed to be named ns (but may have some cnames) # # for newer dhcpd versions use # -dhcpopt "ddns-update-style none;" # # History # 0.1 3/2001 initial version # 0.2 added subnetmask detection # 0.21 added params # 0.25 added $cnamefile # 0.30 11/2001 added ARP # 0.31 2003 cleanup $version = "0.31"; $database = "./admin.dat"; # Name of db file. $cnamefile = "./cname.dat"; # additional db file - optional $all_file = "all"; $arp_file = "arp.set"; $debug = 0; $dhcp_file = "dhcpd.conf"; $domain = "htlw16.ac.at"; $dhcp_domain_name = "itz.$domain"; $dhcp_domain_name_servers = "172.16.1.75, 172.16.1.70, 172.16.1.44"; $dhcp_range = "172.16.3.10 172.16.3.250"; $dhcpopt = ""; #guessed: $dhcp_subnet_mask = "255.255.0.0"; #guessed $dhcp_broadcast_address = "172.16.255.255"; $dhcp_time_servers = "time.$dhcp_domain_name"; $dhcp_font_servers = "fs.$dhcp_domain_name"; $forw_file = "$dhcp_domain_name"; #guessed: $rev_file = "16.172.in-addr.arpa"; $dhcp_to = 3600*10; $dhcp_to_fix = 10*$dhcp_to; $dhcp_to_max = 4*$dhcp_to; $dhcp_to_max_fix = 4*$dhcp_to_fix; $bindto = $dhcp_to_fix; # ------------------------------------------------------------------ use Getopt::Long; # ------------------------------------------------------------------ $mask1 = 0; $mask2 = 0; $mask3 = 0; $mask4 = 0; sub do_read { while ($line = ) { print "." if $debug; chop $line; next if ($line =~ /^\#/); if ($line =~ /^CNAME/) { ($cbname, $name, $org) = split(/,/, $line); $cbname = ""; $name =~ s/ //; $cname{$name} = $org; next; } $host = ""; ($addr, $host, $mac, $comm) = split(/,/, $line); next if (! $host); $mac =~ y/a-z/A-Z/; # mac uppercase $host =~ y/A-Z/a-z/; # hostname lowercase $host =~ s/ //; print "read $host ($addr)\n" if $debug; $hostname{$addr} = $host; $macaddr{$addr} = $mac; $comment{$addr} = $comm; ($sub1,$sub2,$sub3,$sub4) = split(/\./, $addr); $subnet{"$sub1.$sub2.$sub3"} ++; $mask1 |= $sub1; $mask2 |= $sub2; $mask3 |= $sub3; $mask4 |= $sub4; print " subnet $sub1.$sub2.$sub3 (.$sub4)\n" if $debug; } } sub read_database { print "open database $database\n" if $debug; open(DB,"<$database") || die ("Can't open $database; $!"); &do_read; close DB; print "open database $cnamefile\n" if $debug; open(DB,"<$cnamefile") && &do_read; close DB; if ($debug) { foreach $sn (keys (%subnet)) { print "$sn count $subnet{$sn}\n"; } } } # ------------------------------------------------------------------ sub guess_nw { if ($mask1 == $sub1) { $class = 1 ; # $dhcp_network = "$mask1.0.0.0"; # $dhcp_subnet_mask = "255.0.0.0"; # $dhcp_broadcast_address = "$mask1.255.255.255"; $rev_file = "$mask1.in-addr.arpa"; $dhcp_network = "$mask1.0.0.0"; $dhcp_subnet_mask = "255.0.0.0"; $dhcp_broadcast_address = "$mask1.255.255.255"; } if ($mask2 == $sub2) { $class = 2; $dhcp_network = "$mask1.$mask2.0.0"; $dhcp_subnet_mask = "255.255.0.0"; $dhcp_broadcast_address = "$mask1.$mask2.255.255"; $rev_file = "$mask2.$mask1.in-addr.arpa" } if ($mask3 == $sub3) { $class = 3; $dhcp_network = "$mask1.$mask2.$mask3.0"; $dhcp_subnet_mask = "255.255.255.0"; $dhcp_broadcast_address = "$mask1.$mask2.$mask3.255"; $rev_file = "$mask3.$mask2.$mask1.in-addr.arpa" } $dhcp_router = $dhcp_network; $dhcp_router =~ s/0$/1/; print "\nMask: $mask1.$mask2.$mask3.$mask4 ($class)\n" if $debug; print " $dhcp_subnet_mask $dhcp_broadcast_address $dhcp_router $rev_file\n" if $debug; } # ------------------------------------------------------------------ # ------------------------------------------------------------------ # unused: convert dhcp file to database sub dump_old_dhcp { while ($line = ) { if ($line =~ /host ([a-zA-Z0-9_-]*)/) { $host = $1; } if ($line =~ /hardware ethernet *(..:..:..:..:..:..)/) { $mac = $1; } if ($line =~ /fixed-address *([0-9.]*)/) { $addr = $1; print "$addr, $host, $mac, -\n" if ($host); $host = ""; $mac = ""; } } } # ------------------------------------------------------------------ sub dump_dhcp { print "\nopen $dhcp_file\n" if $debug; open(DHCP,">$dhcp_file") || die ("Can't open $dhcp_file; $!"); print DHCP <$forw_file") || die ("Can't open $forw_file; $!"); ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $serial = sprintf("%04d%02d%02d%02d", $year+1900, 1+$mon, $mday, $hour); print FORW <$rev_file") || die ("Can't open $rev_file; $!"); ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $serial = sprintf("%04d%02d%02d%02d", $year+1900, 1+$mon, $mday, $hour); print REV <$all_file") || die ("Can't open $all_file; $!"); foreach $addr (sort keys (%hostname)) { print ALL "$addr\n"; } close ALL; } # ------------------------------------------------------------------ sub dump_arp { print "\nopen $arp_file\n" if $debug; open(ARP,">$arp_file") || die ("Can't open $arp_file; $!"); foreach $addr (sort keys (%hostname)) { print ARP "arp -s $addr $macaddr{$addr}\n" unless $macaddr{$addr} eq "00:00"; } close ARP; } # ------------------------------------------------------------------ sub usage { die < \$showhelp, "database=s" => \$database, "debug!" => \$debug, "dhcp-range=s" => \$dhcp_range, "dhcpopt=s" => \$dhcpopt, "arp=s" => \$arp_file, ); &usage if (!$res || $showhelp || $#ARGV >= 0); $time = time; print "$time\n" if $debug; #&dump_old_dhcp; exit (99); &read_database; &guess_nw; &dump_dhcp; &dump_named_forw; &dump_named_rev; &dump_all; &dump_arp;