1 1.1 christos #! @PATH_PERL@ -w 2 1.1.1.2 christos # @configure_input@ 3 1.1 christos # John Hay -- John.Hay (at] icomtek.csir.co.za / jhay (at] FreeBSD.org 4 1.1 christos 5 1.1 christos package ntptrace; 6 1.1 christos use 5.006_000; 7 1.1 christos use strict; 8 1.1 christos use lib "@PERLLIBDIR@"; 9 1.1 christos use NTP::Util qw(ntp_read_vars do_dns); 10 1.1.1.2 christos use Scalar::Util qw(looks_like_number); 11 1.1 christos 12 1.1 christos exit run(@ARGV) unless caller; 13 1.1 christos 14 1.1 christos sub run { 15 1.1 christos my $opts; 16 1.1 christos if (!processOptions(\@_, $opts)) { 17 1.1 christos usage(1); 18 1.1 christos }; 19 1.1 christos 20 1.1 christos my $dodns = $opts->{numeric} ? 0 : 1; 21 1.1 christos my $max_hosts = $opts->{'max-hosts'}; 22 1.1 christos my $host = shift || $opts->{host}; 23 1.1 christos my $nb_host = 0; 24 1.1 christos 25 1.1 christos for (;;) { 26 1.1 christos $nb_host++; 27 1.1 christos 28 1.1 christos my %info = get_info($host); 29 1.1 christos last if not %info; 30 1.1 christos 31 1.1 christos my $dhost = $host; 32 1.1 christos if ($dodns) { 33 1.1 christos my $name = do_dns($host); 34 1.1 christos $dhost = $name if defined $name; 35 1.1 christos } 36 1.1 christos 37 1.1 christos printf "%s: stratum %d, offset %f, synch distance %f", 38 1.1 christos $dhost, $info{stratum}, $info{offset}, $info{syncdistance}; 39 1.1 christos printf ", refid '%s'", $info{refid} if $info{stratum} == 1; 40 1.1 christos print "\n"; 41 1.1 christos 42 1.1 christos last if $info{stratum} == 0 || $info{stratum} == 1 || 43 1.1 christos $info{stratum} == 16; 44 1.1 christos last if $info{refid} =~ /^127\.127\.\d{1,3}\.\d{1,3}$/; 45 1.1 christos last if $nb_host == $max_hosts; 46 1.1 christos 47 1.1 christos my $next_host = get_next_host($info{peer}, $host); 48 1.1 christos last if $next_host eq ''; 49 1.1 christos last if $next_host =~ /^127\.127\.\d{1,3}\.\d{1,3}$/; 50 1.1 christos 51 1.1 christos $host = $next_host; 52 1.1 christos } 53 1.1 christos return 0; 54 1.1 christos } 55 1.1 christos 56 1.1 christos sub get_info { 57 1.1 christos my ($host) = @_; 58 1.1 christos my ($rootdelay, $rootdisp, $info) = (0, 0); 59 1.1 christos 60 1.1 christos $info = ntp_read_vars(0, [], $host); 61 1.1 christos return if not defined $info; 62 1.1 christos return if not exists $info->{stratum}; 63 1.1 christos 64 1.1.1.2 christos if (not (exists $info->{offset} && looks_like_number($info->{offset}))) { 65 1.1.1.2 christos $info->{offset} = "NaN"; 66 1.1.1.2 christos } 67 1.1 christos $info->{offset} /= 1000; 68 1.1.1.2 christos if (not (exists $info->{rootdisp} && looks_like_number($info->{rootdisp}))) { 69 1.1.1.2 christos $info->{rootdisp} = "NaN"; 70 1.1.1.2 christos } 71 1.1.1.2 christos if (not (exists $info->{rootdelay} && looks_like_number($info->{rootdelay}))) { 72 1.1.1.2 christos $info->{rootdelay} = "NaN"; 73 1.1.1.2 christos } 74 1.1 christos $info->{syncdistance} = ($info->{rootdisp} + ($info->{rootdelay} / 2)) / 1000; 75 1.1 christos 76 1.1 christos return %$info; 77 1.1 christos } 78 1.1 christos 79 1.1 christos 80 1.1 christos sub get_next_host { 81 1.1 christos my ($peer, $host) = @_; 82 1.1 christos 83 1.1 christos my $info = ntp_read_vars($peer, [qw(srcadr)], $host); 84 1.1 christos return if not defined $info; 85 1.1 christos return $info->{srcadr}; 86 1.1 christos } 87 1.1 christos 88 1.1 christos @ntptrace_opts@ 89 1.1 christos 90 1.1 christos 1; 91 1.1 christos __END__ 92