📄 dns2hosts
字号:
#!/usr/bin/perl## $Id: dns2hosts,v 2.0 90/09/11 11:07:27 hakanson Rel $## Convert DNS master (RFC-1035) files to /etc/hosts format.# Marion Hakanson (hakanson@cse.ogi.edu)# Oregon Graduate Institute of Science and Technology## Copyright (c) 1990, Marion Hakanson.## You may distribute under the terms of the GNU General Public License# as specified in the README file that comes with the dnsparse kit.## Other than "-d defdom" (to specify a default domain different from that# found in /etc/resolv.conf), command line args are DNS master file names,# as described for the dns_init() subroutine in dnsparse.pl. The output# is printed to the standard output stream.## This Perl program looks at the A and CNAME records encountered in the# DNS master files, and produces an /etc/hosts file which includes the# same host-to-address, address-to-host, and alias-to-host mappings.# Note that some such mappings are necessarily dependent on the order in# which they are encountered in the DNS master files. The DNS system# is not sensitive to the order, but /etc/hosts files are, thus one# should take care that the command line arguments are presented in# the same order from one invocation to the next, if one expects the# two resulting output files to be comparable.## A large part of the complication of this program is due to the notion# of the "default domain" that the BIND implementation of a DNS resolver# provides. Namely, this allows a user to type a short alias and have# it match to a fully qualified domain name (FQDN) somewhere in the# machine's default domain. E.g. given "admin" and a default domain# of "cse.ogi.edu", the resolver will try "admin.cse.ogi.edu" -- if no# match is found, it will try "admin.ogi.edu" (but it will not try# just the first-level domain, "admin.edu").## Thus, the aliases and canonical names are set up in the output file# to mimic the behavior of a system using the BIND resolver. Among# other things, this means that host numbers will always be resolved# to the FQDN of the host. Instead of using PTR records to provide# the number-to-name mappings, this program assumes that the PTR records# would be automatically generated from the A records. It further assumes# that a host is considered to have a single, unique FQDN, and that all# of its addresses (interfaces) will resolve back to that FQDN. To my# knowledge, this is the only area where the output hosts file may not# quite mimic the behavior of the BIND resolver. I would be willing to# consider a design change if demand warrants it.do 'getopts.pl'; die "$@, aborted" if $@;do 'dnsparse.pl'; die "$@, aborted" if $@;do Getopts('d:');# Get default domainif ( defined($opt_d) ) { $defdom = $opt_d;} elsif ( open(F, '</etc/resolv.conf') ) { while ( <F> ) { $defdom = $1 if ( /\s*domain\s+([^\s]+)/ ); } close(F);}# Set up domains the resolver would tryif ( defined($defdom) ) { $defdom =~ s/^\.//; # strip leading dot $defdom = do dns_makefqdn($defdom,''); @domparts = split(/\./,$defdom); # escaped dots? while ( $#domparts > 0 ) { push(@defdoms, join('.',@domparts)); shift(@domparts); }}# Parse the dns db file, collecting names & addrs.do dns_init(@ARGV);open(OFILE, ">&STDOUT") || die "Cannot dupe 'STDOUT', aborted";# Treat loopback address specially, since the DNS is usually set# up to resolve loopback to "localhost".$hostsbyaddr{'127.0.0.1'} = 'localhost';push(@addrs,'127.0.0.1');rr: while ( (@rr = do dns_getrr()) && @rr ) { ($domain, $ttl, $class, $type, @data) = @rr; next rr if ( $class ne 'IN' ); case: { if ( $type eq 'A' ) { $list = ''; if ( defined($hostsbyaddr{$data[0]}) ) { $list = $hostsbyaddr{$data[0]} . $dns'delim; } else { push(@addrs,$data[0]); } $list .= $domain; $hostsbyaddr{$data[0]} = $list; $fqdnseen{$domain}++; last case; } elsif ( $type eq 'CNAME' ) { $list = ''; if ( defined($cnamesbyhost{$data[0]}) ) { $list = $cnamesbyhost{$data[0]} . $dns'delim; } $list .= $domain; $cnamesbyhost{$data[0]} = $list; $fqdnseen{$domain}++; last case; } }}# Go through the names encountered, building abbreviations,# and attaching them to their fully-qualified forms.while ( ($fqdn,$cnt) = each %fqdnseen ) { #print STDERR "$fqdn seen $cnt times\n"; foreach $truncdom (@defdoms) { $abbrev = $fqdn; # don't generate abbrev's which wouldn't resolve if ( $abbrev =~ s/\.$truncdom// ) { # now we mimic what the resolver would do foreach $dom (@defdoms) { if ( defined($fqdnseen{"$abbrev.$dom"}) ) { $abbrevsbyhost{"$abbrev.$dom"} .= $abbrev . $dns'delim; #print STDERR "$abbrev -> $abbrev.$dom\n"; # stop with the first one last; } } } }}# for debugging#while ( ($key,$val) = each(%abbrevsbyhost) ) {# print STDERR "|$key";# @vals = split(/$dns'delim/,$val);# foreach $val (@vals) {# print STDERR "|$val";# }# print STDERR "|\n";#}# Write out the hosts file.# First write out some commentary about the input source, etc.$datefmt = '%02d/%02d/%02d %02d:%02d:%02d';($sec,$min,$hour,$mday,$mon,$year,@rest) = localtime();$mon++; # 0 == January$date = sprintf($datefmt, $year, $mon, $mday, $hour, $min, $sec);chop($host = `hostname`);print OFILE "#\n";print OFILE "# Host table (/etc/hosts)\n";print OFILE "#\n";print OFILE "# Created on host '$host' at $date\n";print OFILE "#\n";print OFILE "# Abbreviations set up for default domain '$defdom'\n";print OFILE "#\n";print OFILE "# THIS TABLE WAS GENERATED AUTOMATICALLY.\n";print OFILE "# ANY CHANGES OR ADDITIONS TO IT WILL BE\n";print OFILE "# LOST WHEN THE NEXT UPDATE TAKES PLACE.\n";print OFILE "#\n";print OFILE "# Built from the following DNS master files:\n";print OFILE "#\n";print OFILE "# ModTime\t\tFile\n";print OFILE "#\tOrigin\n";while ( $#ARGV >= $[ ) { ($file,$origin) = do dns_commasplit(shift(@ARGV)); $origin = '.' unless ( $origin ); # root if ( $file eq '' || $file eq '-' ) { $file eq 'Standard Input'; @ARGV = (); # STDIN is last $date = 'See Above'; } else { if ( -r $file ) { ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat(_); ($sec,$min,$hour,$mday,$mon,$year,@rest) = localtime($mtime); $mon++; # 0 == January $date = sprintf($datefmt, $year, $mon, $mday, $hour, $min, $sec); } else { $date = "Not Found"; $origin = $!; # the error message } } print OFILE "# $date\t$file\n"; print OFILE "#\t$origin\n";}print OFILE "#\n";print OFILE "#\n";# Build up an output record and then write it out using a# format which may break a long record into multiple lines,# all starting with the same address and canonical name.format OFILE =@<<<<<<<<<<<<<< ~^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<$addr, $names.$: = ' '; # OK to break $names on a blankforeach $addr ( @addrs ) { @hosts = split(/$dns'delim/, $hostsbyaddr{$addr}); %nameseen = (); $names = ''; $canon = $hosts[0]; # save the first one foreach $host ( @hosts ) { unless ( defined($nameseen{$host}) ) { $nameseen{$host} = 1; $names .= " $host"; if ( defined($abbrevsbyhost{$host}) ) { @abbrevs = split(/$dns'delim/, $abbrevsbyhost{$host}); foreach $abbrev ( @abbrevs ) { unless ( defined($nameseen{$abbrev}) ) { $nameseen{$abbrev} = 1; $names .= " $abbrev"; } } } } if ( defined($cnamesbyhost{$host}) ) { @aliases = split(/$dns'delim/, $cnamesbyhost{$host}); foreach $alias ( @aliases ) { unless ( defined($nameseen{$alias}) ) { $nameseen{$alias} = 1; $names .= " $alias"; if ( defined($abbrevsbyhost{$alias}) ) { @abbrevs = split(/$dns'delim/, $abbrevsbyhost{$alias}); foreach $abbrev ( @abbrevs ) { unless ( defined($nameseen{$abbrev}) ) { $nameseen{$abbrev} = 1; $names .= " $abbrev"; } } } } } } } $names =~ s/^ $canon *//; # we'll put it back below do { #print STDERR "|$names|\n"; $names = "$canon $names"; write(OFILE); # has side effect of shortening $names } while ( $names );}exit(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -