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