summaryrefslogtreecommitdiffstats
path: root/lib/probes/AnotherDNS.pm
blob: 7acc36d2ba485f606d4fdabb5a99da525abf9f5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package probes::AnotherDNS;

=head1 NAME

probes::AnotherDNS - Alternate DNS Probe

=head1 SYNOPSIS

 *** Probes ***
 + AnotherDNS

 *** Targets *** 
 probe = AnotherDNS
 forks = 10

 + First
 menu = First
 title = First Target
 # .... 

 ++ PROBE_CONF
 lookup = www.mozilla.org

=head1 DESCRIPTION

Like DNS, but uses Net::DNS and Time::HiRes instead of dig. This probe does
*not* retry the request three times before it is considerd "lost", like dig and
other resolver do by default. If operating as caching Nameserver, BIND (and
maybe others) expect clients to retry the request if the answer is not in the
cache. So, ask the nameserver for something that he is authorative for if you
want measure the network packet loss correctly. 

If you have a really fast network and nameserver, you will notice that this
probe reports the query time in microsecond resolution. :-)

=over

=item forks

The number of concurrent processes to be run. See probes::basefork(3pm)
for details.

=back

Supported target-level probe variables:

=over

=item lookup

Name of the host to look up in the dns.

=item sleeptime

Time to sleep between two lookups in microseconds. Default is 500000.

=item recordtype

Record type to look up. Default is "A".

=item timeout

Timeout for a single request in seconds. Default is 5.

=item port

UDP Port to use. Default is 53. (Surprise!)

=back


=head1 AUTHOR

Christoph Heine E<lt>Christoph.Heine@HaDiKo.DEE<gt>

=cut

use strict;

# And now, an extra ugly hack
# Reason: Net::DNS does an eval("use Win32:Registry") to
# find out if it is running on Windows. This triggers the signal
# handler in the cgi mode. 

my $tmp = $SIG{__DIE__};
$SIG{__DIE__} = sub { };
eval("use Net::DNS;");
$SIG{__DIE__} = $tmp;

use base qw(probes::basefork);
use IPC::Open3;
use Symbol;
use Carp;
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
use IO::Socket;
use IO::Select;

sub new($$$) {
    my $proto = shift;
    my $class = ref($proto) || $proto;
    my $self  = $class->SUPER::new(@_);
    return $self;
}

sub ProbeDesc($) {
    my $self = shift;
    return "DNS requests";
}

sub pingone ($) {
    my $self   = shift;
    my $target = shift;

    my $host       = $target->{addr};
    my $lookuphost = $target->{vars}{lookup};
    my $sleeptime  = $target->{vars}{sleeptime};
    my $recordtype = $target->{vars}{recordtype};
    my $timeout = $target->{vars}{timeout};
    my $port = $target->{vars}{port};
    $recordtype = "A"    unless defined $recordtype;
    $timeout = 5    unless defined $timeout;
    $port = 53    unless defined $port;
    $sleeptime  = 500000 unless defined $sleeptime;
    $lookuphost = $target->{addr} unless defined $lookuphost;

    my $packet = Net::DNS::Packet->new( $lookuphost, $recordtype )->data;
    my $sock = IO::Socket::INET->new(
        "PeerAddr" => $host,
        "PeerPort" => $port,
        "Proto"    => "udp",
    );
    my $sel = IO::Select->new($sock);

    my @times;

    for ( my $run = 0 ; $run < $self->pings($target) ; $run++ ) {
        my $t0 = [gettimeofday];
        $sock->send($packet);
        my ($ready) = $sel->can_read($timeout);
        my $t1 = [gettimeofday];
        if ( defined $ready ) {
            my $time = tv_interval( $t0, $t1 );
            push @times, $time;
            my $buf = '';
            $ready->recv( $buf, &Net::DNS::PACKETSZ );
        }
        usleep($sleeptime);
    }
    @times =
      map { sprintf "%.10e", $_ } sort { $a <=> $b } grep { $_ ne "-" } @times;

    return @times;
}

1;