12b15cb3dSCy Schubert#! @PATH_PERL@ -w 2*f5f40dd6SCy Schubert# @configure_input@ 32b15cb3dSCy Schubert# John Hay -- John.Hay@icomtek.csir.co.za / jhay@FreeBSD.org 42b15cb3dSCy Schubert 52b15cb3dSCy Schubertpackage ntptrace; 62b15cb3dSCy Schubertuse 5.006_000; 72b15cb3dSCy Schubertuse strict; 82b15cb3dSCy Schubertuse lib "@PERLLIBDIR@"; 92b15cb3dSCy Schubertuse NTP::Util qw(ntp_read_vars do_dns); 10*f5f40dd6SCy Schubertuse Scalar::Util qw(looks_like_number); 112b15cb3dSCy Schubert 122b15cb3dSCy Schubertexit run(@ARGV) unless caller; 132b15cb3dSCy Schubert 142b15cb3dSCy Schubertsub run { 152b15cb3dSCy Schubert my $opts; 162b15cb3dSCy Schubert if (!processOptions(\@_, $opts)) { 172b15cb3dSCy Schubert usage(1); 182b15cb3dSCy Schubert }; 192b15cb3dSCy Schubert 202b15cb3dSCy Schubert my $dodns = $opts->{numeric} ? 0 : 1; 212b15cb3dSCy Schubert my $max_hosts = $opts->{'max-hosts'}; 222b15cb3dSCy Schubert my $host = shift || $opts->{host}; 232b15cb3dSCy Schubert my $nb_host = 0; 242b15cb3dSCy Schubert 252b15cb3dSCy Schubert for (;;) { 262b15cb3dSCy Schubert $nb_host++; 272b15cb3dSCy Schubert 282b15cb3dSCy Schubert my %info = get_info($host); 292b15cb3dSCy Schubert last if not %info; 302b15cb3dSCy Schubert 312b15cb3dSCy Schubert my $dhost = $host; 322b15cb3dSCy Schubert if ($dodns) { 332b15cb3dSCy Schubert my $name = do_dns($host); 342b15cb3dSCy Schubert $dhost = $name if defined $name; 352b15cb3dSCy Schubert } 362b15cb3dSCy Schubert 372b15cb3dSCy Schubert printf "%s: stratum %d, offset %f, synch distance %f", 382b15cb3dSCy Schubert $dhost, $info{stratum}, $info{offset}, $info{syncdistance}; 392b15cb3dSCy Schubert printf ", refid '%s'", $info{refid} if $info{stratum} == 1; 402b15cb3dSCy Schubert print "\n"; 412b15cb3dSCy Schubert 422b15cb3dSCy Schubert last if $info{stratum} == 0 || $info{stratum} == 1 || 432b15cb3dSCy Schubert $info{stratum} == 16; 442b15cb3dSCy Schubert last if $info{refid} =~ /^127\.127\.\d{1,3}\.\d{1,3}$/; 452b15cb3dSCy Schubert last if $nb_host == $max_hosts; 462b15cb3dSCy Schubert 472b15cb3dSCy Schubert my $next_host = get_next_host($info{peer}, $host); 482b15cb3dSCy Schubert last if $next_host eq ''; 492b15cb3dSCy Schubert last if $next_host =~ /^127\.127\.\d{1,3}\.\d{1,3}$/; 502b15cb3dSCy Schubert 512b15cb3dSCy Schubert $host = $next_host; 522b15cb3dSCy Schubert } 532b15cb3dSCy Schubert return 0; 542b15cb3dSCy Schubert} 552b15cb3dSCy Schubert 562b15cb3dSCy Schubertsub get_info { 572b15cb3dSCy Schubert my ($host) = @_; 582b15cb3dSCy Schubert my ($rootdelay, $rootdisp, $info) = (0, 0); 592b15cb3dSCy Schubert 602b15cb3dSCy Schubert $info = ntp_read_vars(0, [], $host); 612b15cb3dSCy Schubert return if not defined $info; 622b15cb3dSCy Schubert return if not exists $info->{stratum}; 632b15cb3dSCy Schubert 64*f5f40dd6SCy Schubert if (not (exists $info->{offset} && looks_like_number($info->{offset}))) { 65*f5f40dd6SCy Schubert $info->{offset} = "NaN"; 66*f5f40dd6SCy Schubert } 672b15cb3dSCy Schubert $info->{offset} /= 1000; 68*f5f40dd6SCy Schubert if (not (exists $info->{rootdisp} && looks_like_number($info->{rootdisp}))) { 69*f5f40dd6SCy Schubert $info->{rootdisp} = "NaN"; 70*f5f40dd6SCy Schubert } 71*f5f40dd6SCy Schubert if (not (exists $info->{rootdelay} && looks_like_number($info->{rootdelay}))) { 72*f5f40dd6SCy Schubert $info->{rootdelay} = "NaN"; 73*f5f40dd6SCy Schubert } 742b15cb3dSCy Schubert $info->{syncdistance} = ($info->{rootdisp} + ($info->{rootdelay} / 2)) / 1000; 752b15cb3dSCy Schubert 762b15cb3dSCy Schubert return %$info; 772b15cb3dSCy Schubert} 782b15cb3dSCy Schubert 792b15cb3dSCy Schubert 802b15cb3dSCy Schubertsub get_next_host { 812b15cb3dSCy Schubert my ($peer, $host) = @_; 822b15cb3dSCy Schubert 832b15cb3dSCy Schubert my $info = ntp_read_vars($peer, [qw(srcadr)], $host); 842b15cb3dSCy Schubert return if not defined $info; 852b15cb3dSCy Schubert return $info->{srcadr}; 862b15cb3dSCy Schubert} 872b15cb3dSCy Schubert 882b15cb3dSCy Schubert@ntptrace_opts@ 892b15cb3dSCy Schubert 902b15cb3dSCy Schubert1; 912b15cb3dSCy Schubert__END__ 92