ntpsweep.in revision 1.1.1.4
1234285Sdim#! @PATH_PERL@ -w 2234285Sdim# 3234285Sdim# Id 4234285Sdim# 5234285Sdim# DISCLAIMER 6234285Sdim# 7234285Sdim# Copyright (C) 1999,2000 Hans Lambermont and Origin B.V. 8234285Sdim# 9234285Sdim# Permission to use, copy, modify and distribute this software and its 10234285Sdim# documentation for any purpose and without fee is hereby granted, 11234285Sdim# provided that the above copyright notice appears in all copies and 12234285Sdim# that both the copyright notice and this permission notice appear in 13234285Sdim# supporting documentation. This software is supported as is and without 14234285Sdim# any express or implied warranties, including, without limitation, the 15234285Sdim# implied warranties of merchantability and fitness for a particular 16234285Sdim# purpose. The name Origin B.V. must not be used to endorse or promote 17234285Sdim# products derived from this software without prior written permission. 18234285Sdim# 19234285Sdim# Hans Lambermont <ntpsweep@lambermont.dyndns.org> 20234285Sdim 21234285Sdimpackage ntpsweep; 22234285Sdimuse 5.006_000; 23234285Sdimuse strict; 24234285Sdimuse lib "@PERLLIBDIR@"; 25234285Sdimuse NTP::Util qw(do_dns ntp_read_vars ntp_peers ntp_sntp_line); 26234285Sdim 27234285Sdim(my $program = $0) =~ s%.*/(.+?)(.pl)?$%$1%; 28234285Sdimmy ($showpeers, $maxlevel, $strip); 29234285Sdimmy (%known_host_info, %known_host_peers); 30234285Sdim 31234285Sdimexit run(@ARGV) unless caller; 32234285Sdim 33234285Sdimsub run { 34234285Sdim my $opts; 35234285Sdim if (!processOptions(\@_, $opts) || 36234285Sdim (((@_ != 1) && !$opts->{host} && !@{$opts->{'host-list'}}))) { 37234285Sdim usage(1); 38234285Sdim }; 39234285Sdim 40234285Sdim # no STDOUT buffering 41234285Sdim $| = 1; 42234285Sdim ($showpeers, $maxlevel, $strip) = 43234285Sdim ($opts->{peers}, $opts->{maxlevel}, $opts->{strip}); 44234285Sdim 45234285Sdim my $hostsfile = shift; 46234285Sdim 47234285Sdim # Main program 48234285Sdim 49234285Sdim my @hosts; 50234285Sdim 51234285Sdim if ($opts->{host}) { 52234285Sdim push @hosts, $opts->{host}; 53234285Sdim } 54234285Sdim else { 55234285Sdim @hosts = read_hosts($hostsfile) if $hostsfile; 56234285Sdim push @hosts, @{$opts->{'host-list'}}; 57234285Sdim } 58234285Sdim 59234285Sdim # Print header 60234285Sdim print <<EOF; 61234285SdimHost st offset(s) version system processor 62234285Sdim--------------------------------+--+---------+-----------+------------+--------- 63234285SdimEOF 64234285Sdim 65234285Sdim %known_host_info = (); 66234285Sdim %known_host_peers = (); 67234285Sdim scan_hosts(@hosts); 68234285Sdim 69234285Sdim return 0; 70234285Sdim} 71234285Sdim 72234285Sdimsub scan_hosts { 73234285Sdim my (@hosts) = @_; 74234285Sdim 75234285Sdim my $host; 76234285Sdim for $host (@hosts) { 77234285Sdim scan_host($host, 0, $host => 1); 78234285Sdim } 79234285Sdim} 80234285Sdim 81234285Sdimsub read_hosts { 82234285Sdim my ($hostsfile) = @_; 83234285Sdim my @hosts; 84234285Sdim 85234285Sdim open my $hosts, $hostsfile 86234285Sdim or die "$program: FATAL: unable to read $hostsfile: $!\n"; 87234285Sdim 88234285Sdim while (<$hosts>) { 89234285Sdim next if /^\s*(#|$)/; # comment/empty 90234285Sdim chomp; 91234285Sdim push @hosts, $_; 92234285Sdim } 93234285Sdim 94234285Sdim close $hosts; 95234285Sdim return @hosts; 96234285Sdim} 97234285Sdim 98234285Sdimsub scan_host { 99234285Sdim my ($host, $level, %trace) = @_; 100234285Sdim my $stratum = 0; 101234285Sdim my $offset = 0; 102234285Sdim my $daemonversion = ""; 103234285Sdim my $system = ""; 104234285Sdim my $processor = ""; 105234285Sdim my @peers; 106234285Sdim my $known_host = 0; 107234285Sdim 108234285Sdim if (exists $known_host_info{$host}) { 109239462Sdim $known_host = 1; 110234285Sdim } 111234285Sdim else { 112234285Sdim ($offset, $stratum) = ntp_sntp_line($host); 113234285Sdim 114234285Sdim # got answers ? If so, go on. 115234285Sdim if ($stratum) { 116234285Sdim my $vars = ntp_read_vars(0, [qw(processor system daemon_version)], $host) || {}; 117234285Sdim $daemonversion = $vars->{daemon_version}; 118234285Sdim $system = $vars->{system}; 119234285Sdim $processor = $vars->{processor}; 120234285Sdim 121234285Sdim # Shorten daemon_version string. 122234285Sdim $daemonversion =~ s/(;|Mon|Tue|Wed|Thu|Fri|Sat|Sun).*$//; 123234285Sdim $daemonversion =~ s/version=//; 124234285Sdim $daemonversion =~ s/(x|)ntpd //; 125234285Sdim $daemonversion =~ s/(\(|\))//g; 126234285Sdim $daemonversion =~ s/beta/b/; 127234285Sdim $daemonversion =~ s/multicast/mc/; 128234285Sdim 129234285Sdim # Shorten system string 130234285Sdim $system =~ s/UNIX\///; 131234285Sdim $system =~ s/RELEASE/r/; 132234285Sdim $system =~ s/CURRENT/c/; 133234285Sdim 134234285Sdim # Shorten processor string 135234285Sdim $processor =~ s/unknown//; 136234285Sdim } 137234285Sdim 138234285Sdim # got answers ? If so, go on. 139234285Sdim if ($daemonversion) { 140234285Sdim if ($showpeers) { 141234285Sdim my $peers_ref = ntp_peers($host); 142234285Sdim my @peers_tmp = @$peers_ref; 143234285Sdim for (@peers_tmp) { 144234285Sdim $_->{remote} =~ s/^(?: |x|\.|-|\+|#|\*|o)([^ ]+)/$1/; 145234285Sdim push @peers, $_->{remote}; 146234285Sdim } 147234285Sdim } 148234285Sdim } 149234285Sdim 150234285Sdim # Add scanned host to known_hosts array 151234285Sdim #push @known_hosts, $host; 152234285Sdim if ($stratum) { 153234285Sdim $known_host_info{$host} = sprintf "%2d %9.3f %-11s %-12s %s", 154234285Sdim $stratum, $offset, (substr $daemonversion, 0, 11), 155234285Sdim (substr $system, 0, 12), (substr $processor, 0, 9); 156234285Sdim } 157234285Sdim else { 158234285Sdim # Stratum level 0 is consider invalid 159234285Sdim $known_host_info{$host} = " ?"; 160234285Sdim } 161234285Sdim $known_host_peers{$host} = [@peers]; 162234285Sdim } 163234285Sdim 164234285Sdim if ($stratum || $known_host) { # Valid or known host 165234285Sdim my $printhost = ' ' x $level . (do_dns($host) || $host); 166234285Sdim # Shorten host string 167234285Sdim if ($strip) { 168234285Sdim $printhost =~ s/$strip//; 169234285Sdim } 170234285Sdim # append number of peers in brackets if requested and valid 171234285Sdim if ($showpeers && ($known_host_info{$host} ne " ?")) { 172234285Sdim $printhost .= " (" . @{$known_host_peers{$host}} . ")"; 173234285Sdim } 174234285Sdim # Finally print complete host line 175234285Sdim printf "%-32s %s\n", 176234285Sdim (substr $printhost, 0, 32), $known_host_info{$host}; 177234285Sdim if ($showpeers && ($maxlevel ? $level < $maxlevel : 1)) { 178234285Sdim $trace{$host} = 1; 179234285Sdim # Loop through peers 180234285Sdim foreach my $peer (@{$known_host_peers{$host}}) { 181234285Sdim if (exists $trace{$peer}) { 182234285Sdim # we've detected a loop ! 183234285Sdim $printhost = ' ' x ($level + 1) . "= " . $peer; 184234285Sdim # Shorten host string 185234285Sdim $printhost =~ s/$strip// if $strip; 186234285Sdim printf "%-32s\n", substr $printhost, 0, 32; 187234285Sdim } else { 188234285Sdim if ((substr $peer, 0, 3) ne "127") { 189234285Sdim scan_host($peer, $level + 1, %trace); 190234285Sdim } 191234285Sdim } 192234285Sdim } 193234285Sdim } 194234285Sdim } 195234285Sdim else { # We did not get answers from this host 196234285Sdim my $printhost = ' ' x $level . (do_dns($host) || $host); 197234285Sdim $printhost =~ s/$strip// if $strip; 198234285Sdim printf "%-32s ?\n", substr $printhost, 0, 32; 199234285Sdim } 200234285Sdim} 201234285Sdim 202234285Sdim@ntpsweep_opts@ 203234285Sdim 204234285Sdim1; 205234285Sdim__END__ 206234285Sdim