diff options
Diffstat (limited to 'nagios-plugins/check_etc_hosts')
-rwxr-xr-x | nagios-plugins/check_etc_hosts | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/nagios-plugins/check_etc_hosts b/nagios-plugins/check_etc_hosts new file mode 100755 index 0000000..8704965 --- /dev/null +++ b/nagios-plugins/check_etc_hosts @@ -0,0 +1,247 @@ +#!/usr/bin/perl -w +# +# Author: Petter Reinholdtsen <pere@hungry.com> +# Date: 2002-07-08 +# +# Check /etc/hosts, and make sure the content matches the information +# in DNS. Lookup IP, and check if the names listed in /etc/hosts +# maches the one in DNS. + +use vars qw($use_perl_resolver $debug $returnvalue $nagiosmsg); + +$debug = 0; +$returnvalue = 0; # all ok +$nagiosmsg = ""; + +# Report missing reverse lookup. This will ignore CNAME entries +# pointing to the IP address, and report error in these cases. +$use_reverse = 0; + +# Report missing forward-lookup. This will complain on private +# network IP addresses using the same name as a DNS entry. +$use_forward = 1; + +eval 'use Net::DNS;'; +if ($@) { + print "Using /etc/hosts\n" if $debug; + $use_perl_resolver = 0; +} else { + print "Using Net::DNS\n" if $debug; + $use_perl_resolver = 1; +} + +$host = '/local/bin/host'; + +# Look up ip address, and return ($error status, @DNS names, @DNS addresses) +sub dns_lookup_ext { + local $address = shift; + + # Stupid Tru64 Unix give me two copies of the error messages from + # host. Throw away one of them. + close(STDERR); + + print "Looking up $address using $host\n" if $debug; + + my @names = (); + my @addresses = (); + + my $lookup = ""; + # Some versions need -i to make sure it uses reverse DNS lookup, + # and not /etc/hosts. + # This option will confuse 'host' on Irix and HP/UX, and make the + # program loop forever. Avoiding it for now [pere 2002-08-06] + for $options ("") { + open(HOST, "$host $options $address 2>&1 |") + || die "Unable to execute host"; + while (<HOST>) { + $lookup .= $_; + chomp; + print "host: $_\n" if $debug; + + push(@names, lc($1)) if (/^Name: (.+)$/); + push(@names, lc($1)) if (/^Aliases: (.+)$/); + + # 10.6.240.129.in-addr.arpa PTR perleporten.uio.no + push(@names, lc($1)) if (/\s+PTR\s+(.+)$/); + + # spheniscus.uio.no has address 129.240.148.19 + if (/^\S+ has address (\S+)$/) { + print "Match addr $1\n" if $debug; + push(@addresses, lc($1)) + } + + # 10.6.240.129.IN-ADDR.ARPA domain name pointer perleporten.uio.no + if (/IN-ADDR.ARPA domain name pointer\s+(.+)$/) { + print "Match name $1\n" if $debug; + push(@names, lc($1)) + } + + push(@addresses, $1) if (/^Address: (.+)$/); + push(@addresses, $1) if (/\s+A\s+(\d+.+)$/) + } + close(HOST); + if ($lookup =~ /Usage: /) { + # Probably unknown parameter, try again without -i + $lookup = ""; + } else { + last; + } + } + return ("no/bad reply from DNS server", undef, undef) + if ($lookup !~ /domain name pointer/ + && $lookup !~ /\shas address\s/ + && $lookup !~ /\sPTR\s/ + && $lookup !~ /Name:/); + + if ( $address =~ m/^\d+\.\d+\.\d+\.\d+/ + && ! grep /$address/, @addresses ) { + print "Adding $address to list of addresses\n" if $debug; + unshift(@addresses, $address) ; + } + + return (undef, \@names, \@addresses); +} + +sub dns_lookup_int { + my $address = shift; + + print "Looking up $address using Net::DNS\n" if $debug; + + my @names = (); + my @addresses = (); + + my $res = new Net::DNS::Resolver; + my $query; + if ($address =~ m/\d+\.\d+\.\d+\.\d+/) { + $query = $res->query($address); + } else { + $query = $res->search($address); + } + if ($query) { + foreach $rr ($query->answer) { + print "Type: $rr->type\n" if $debug; + if ($rr->type eq "A") { + print $rr->address, " - A\n" if $debug; + push(@addresses, $rr->address); + } + if ($rr->type eq "CNAME") { + print $rr->cname, " - CNAME\n" if $debug; + push(@addresses, $rr->cname); + } + if ($rr->type eq "PTR") { + print $rr->ptrdname, " - PTR\n" if $debug; + push(@names, lc($rr->ptrdname)); + } + } + return (undef, \@names, \@addresses); + } + else { + print "query failed: ", $res->errorstring, "\n" if $debug; + return ($res->errorstring, (), ()); + } +} + +sub dns_lookup { + my $entry = shift; + + if ($use_perl_resolver) { + return dns_lookup_int($entry); + } else { + return dns_lookup_ext($entry); + } +} + +sub error { + local ($level, $error) = @_; + + $returnvalue = 1 if ($level =~ /^W$/ && $returnvalue <= 1); + $returnvalue = 2 if ($level =~ /^C$/); + + $nagiosmsg = $nagiosmsg . "<br>" unless ($nagiosmsg =~ /^$/); + $nagiosmsg = $nagiosmsg . "$error"; +} + +sub is_ip_private { + my $ip = shift; + + return 1 if ($ip =~ m/^10\./); + return 1 if ($ip =~ m/^192\.168\./); + + return 0; +} + +sub is_names_ip_matching { + local ($ip, @names) = @_; + + my $level = "W"; + + # Ignore IPv6 addresses for now. + return if ($ip =~ m/:/); + + # Ignore private network + return if (is_ip_private($ip)); + + my $name; + for $name (sort @names) { + if ($use_reverse) { + # Check reverse + my ($retval, $revnames) = dns_lookup($ip); + + return if ( $retval ); # Ignore unknown IP addresses + + if ( ! $retval && ! grep /$name/, @{$revnames} ) { + error $level, "Incorrect /etc/hosts for $ip: ". + "$name not in reverse DNS list"; + } + } + + if ($use_forward) { + # Check forward + my ($retval, $revnames, $forwip); + + ($retval, $revnames) = dns_lookup($ip); + ($retval, undef, $forwip) = dns_lookup($name); + + print "Forward DNS $name/$ip: ", join(" ", @{$forwip}), "\n" + if $debug; + + # Ignore entry if both IP and hostname fail to resolve in DNS + return if ( ! defined $revnames && ! defined $forwip ); + + if ( ! grep /$ip/, @{$forwip} ) { + error $level, "Incorrect /etc/hosts for $ip: ". + "IP not in forward DNS list for '$name'"; + } + } + } +} + +sub check_etc_hosts { + open(HOSTS, "< /etc/hosts") || die "Unable to open /etc/hosts"; + while (<HOSTS>) { + chomp; + s/\#.+//; # Skip comments + next if (/^\s*$/); # Skip empty lines + + print "Testing $_\n" if $debug; + + $_ = lc($_); + + local ($ip, @names) = split(/\s+/); + + # Skip localhost, it is different on some platforms. + next if ($ip eq '127.0.0.1'); + + is_names_ip_matching($ip, @names); + } + close(HOSTS); +} + +check_etc_hosts() if ( -f "/etc/hosts" ); + +if ($nagiosmsg =~ /^$/) { + print "/etc/hosts OK\n"; +} else { + print $nagiosmsg . "\n"; +} +exit $returnvalue; |