1275970Scy#! @PATH_PERL@ -w
2275970Scy# John Hay -- John.Hay@icomtek.csir.co.za / jhay@FreeBSD.org
3275970Scy
4275970Scypackage ntptrace;
5275970Scyuse 5.006_000;
6275970Scyuse strict;
7275970Scyuse lib "@PERLLIBDIR@";
8275970Scyuse NTP::Util qw(ntp_read_vars do_dns);
9275970Scy
10275970Scyexit run(@ARGV) unless caller;
11275970Scy
12275970Scysub run {
13275970Scy    my $opts;
14275970Scy    if (!processOptions(\@_, $opts)) {
15275970Scy        usage(1);
16275970Scy    };
17275970Scy
18275970Scy    my $dodns     = $opts->{numeric} ? 0 : 1;
19275970Scy    my $max_hosts = $opts->{'max-hosts'};
20275970Scy    my $host      = shift || $opts->{host};
21275970Scy    my $nb_host   = 0;
22275970Scy
23275970Scy    for (;;) {
24275970Scy        $nb_host++;
25275970Scy
26275970Scy        my %info = get_info($host);
27275970Scy        last if not %info;
28275970Scy
29275970Scy        my $dhost = $host;
30275970Scy        if ($dodns) {
31275970Scy            my $name = do_dns($host);
32275970Scy            $dhost = $name if defined $name;
33275970Scy        }
34275970Scy
35275970Scy        printf "%s: stratum %d, offset %f, synch distance %f",
36275970Scy            $dhost, $info{stratum}, $info{offset}, $info{syncdistance};
37275970Scy        printf ", refid '%s'", $info{refid} if $info{stratum} == 1;
38275970Scy        print "\n";
39275970Scy
40275970Scy        last if $info{stratum} == 0 || $info{stratum} == 1 || 
41275970Scy                $info{stratum} == 16;
42275970Scy        last if $info{refid} =~ /^127\.127\.\d{1,3}\.\d{1,3}$/;
43275970Scy        last if $nb_host == $max_hosts;
44275970Scy
45275970Scy        my $next_host = get_next_host($info{peer}, $host);
46275970Scy        last if $next_host eq '';
47275970Scy        last if $next_host  =~ /^127\.127\.\d{1,3}\.\d{1,3}$/;
48275970Scy
49275970Scy        $host = $next_host;
50275970Scy    }
51275970Scy    return 0;
52275970Scy}
53275970Scy
54275970Scysub get_info {
55275970Scy    my ($host) = @_;
56275970Scy    my ($rootdelay, $rootdisp, $info) = (0, 0);
57275970Scy
58275970Scy    $info = ntp_read_vars(0, [], $host);
59275970Scy    return if not defined $info;
60275970Scy    return if not exists $info->{stratum};
61275970Scy
62275970Scy    $info->{offset} /= 1000;
63275970Scy    $info->{syncdistance} = ($info->{rootdisp} + ($info->{rootdelay} / 2)) / 1000;
64275970Scy
65275970Scy    return %$info;
66275970Scy}
67275970Scy
68275970Scy
69275970Scysub get_next_host {
70275970Scy    my ($peer, $host) = @_;
71275970Scy
72275970Scy    my $info = ntp_read_vars($peer, [qw(srcadr)], $host);
73275970Scy    return if not defined $info;
74275970Scy    return $info->{srcadr};
75275970Scy}
76275970Scy
77275970Scy@ntptrace_opts@
78275970Scy
79275970Scy1;
80275970Scy__END__
81