This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update Archive-Tar to CPAN version 2.12
[perl5.git] / dist / Net-Ping / lib / Net / Ping.pm
CommitLineData
a0d0e21e
LW
1package Net::Ping;
2
b124990b 3require 5.002;
a0d0e21e
LW
4require Exporter;
5
a3b93737 6use strict;
b124990b 7use vars qw(@ISA @EXPORT $VERSION
9539e94f
JH
8 $def_timeout $def_proto $def_factor
9 $max_datasize $pingstring $hires $source_verify $syn_forking);
f569508e 10use Fcntl qw( F_GETFL F_SETFL O_NONBLOCK );
1bd59f2c 11use Socket qw( SOCK_DGRAM SOCK_STREAM SOCK_RAW PF_INET SOL_SOCKET SO_ERROR IPPROTO_IP IP_TOS IP_TTL
4e0aac35 12 inet_aton getnameinfo NI_NUMERICHOST sockaddr_in );
eb194dd9 13use POSIX qw( ENOTCONN ECONNREFUSED ECONNRESET EINPROGRESS EWOULDBLOCK EAGAIN WNOHANG );
f569508e 14use FileHandle;
a3b93737 15use Carp;
4e0aac35 16use Time::HiRes;
a79c1648 17
a0d0e21e 18@ISA = qw(Exporter);
a3b93737 19@EXPORT = qw(pingecho);
38b4af19 20$VERSION = "2.44";
a0d0e21e 21
a3b93737 22# Constants
a0d0e21e 23
a3b93737 24$def_timeout = 5; # Default timeout to wait for a reply
a5a165b1 25$def_proto = "tcp"; # Default protocol to use for pinging
9539e94f 26$def_factor = 1.2; # Default exponential backoff rate.
a3b93737 27$max_datasize = 1024; # Maximum data bytes in a packet
b124990b
JH
28# The data we exchange with the server for the stream protocol
29$pingstring = "pingschwingping!\n";
5d20095f 30$source_verify = 1; # Default is to verify source endpoint
f569508e 31$syn_forking = 0;
a0d0e21e 32
ef73e1db
JH
33if ($^O =~ /Win32/i) {
34 # Hack to avoid this Win32 spewage:
35 # Your vendor has not defined POSIX macro ECONNREFUSED
5d6b07c5
NC
36 my @pairs = (ECONNREFUSED => 10061, # "Unknown Error" Special Win32 Response?
37 ENOTCONN => 10057,
38 ECONNRESET => 10054,
39 EINPROGRESS => 10036,
40 EWOULDBLOCK => 10035,
41 );
42 while (my $name = shift @pairs) {
43 my $value = shift @pairs;
44 # When defined, these all are non-zero
45 unless (eval $name) {
46 no strict 'refs';
47 *{$name} = defined prototype \&{$name} ? sub () {$value} : sub {$value};
48 }
49 }
eb194dd9 50# $syn_forking = 1; # XXX possibly useful in < Win2K ?
ef73e1db
JH
51};
52
f569508e
HS
53# h2ph "asm/socket.h"
54# require "asm/socket.ph";
55sub SO_BINDTODEVICE {25;}
56
a3b93737
RM
57# Description: The pingecho() subroutine is provided for backward
58# compatibility with the original Net::Ping. It accepts a host
59# name/IP and an optional timeout in seconds. Create a tcp ping
60# object and try pinging the host. The result of the ping is returned.
a0d0e21e 61
a3b93737
RM
62sub pingecho
63{
e82f584b
JH
64 my ($host, # Name or IP number of host to ping
65 $timeout # Optional timeout in seconds
66 ) = @_;
67 my ($p); # A ping object
a0d0e21e 68
e82f584b
JH
69 $p = Net::Ping->new("tcp", $timeout);
70 $p->ping($host); # Going out of scope closes the connection
a3b93737 71}
a0d0e21e 72
a3b93737
RM
73# Description: The new() method creates a new ping object. Optional
74# parameters may be specified for the protocol to use, the timeout in
75# seconds and the size in bytes of additional data which should be
76# included in the packet.
77# After the optional parameters are checked, the data is constructed
78# and a socket is opened if appropriate. The object is returned.
79
80sub new
81{
e82f584b
JH
82 my ($this,
83 $proto, # Optional protocol to use for pinging
84 $timeout, # Optional timeout in seconds
f569508e
HS
85 $data_size, # Optional additional bytes of data
86 $device, # Optional device to use
03550e9d 87 $tos, # Optional ToS to set
1bd59f2c 88 $ttl, # Optional TTL to set
e82f584b
JH
89 ) = @_;
90 my $class = ref($this) || $this;
91 my $self = {};
92 my ($cnt, # Count through data bytes
93 $min_datasize # Minimum data bytes required
94 );
95
96 bless($self, $class);
97
98 $proto = $def_proto unless $proto; # Determine the protocol
f569508e
HS
99 croak('Protocol for ping must be "icmp", "udp", "tcp", "syn", "stream", or "external"')
100 unless $proto =~ m/^(icmp|udp|tcp|syn|stream|external)$/;
e82f584b
JH
101 $self->{"proto"} = $proto;
102
103 $timeout = $def_timeout unless $timeout; # Determine the timeout
104 croak("Default timeout for ping must be greater than 0 seconds")
105 if $timeout <= 0;
106 $self->{"timeout"} = $timeout;
107
f569508e
HS
108 $self->{"device"} = $device;
109
03550e9d
JH
110 $self->{"tos"} = $tos;
111
1bd59f2c
SP
112 if ($self->{"proto"} eq 'icmp') {
113 croak('TTL must be from 0 to 255')
114 if ($ttl && ($ttl < 0 || $ttl > 255));
115 $self->{"ttl"} = $ttl;
116 }
117
e82f584b
JH
118 $min_datasize = ($proto eq "udp") ? 1 : 0; # Determine data size
119 $data_size = $min_datasize unless defined($data_size) && $proto ne "tcp";
120 croak("Data for ping must be from $min_datasize to $max_datasize bytes")
121 if ($data_size < $min_datasize) || ($data_size > $max_datasize);
122 $data_size-- if $self->{"proto"} eq "udp"; # We provide the first byte
123 $self->{"data_size"} = $data_size;
124
125 $self->{"data"} = ""; # Construct data bytes
126 for ($cnt = 0; $cnt < $self->{"data_size"}; $cnt++)
127 {
128 $self->{"data"} .= chr($cnt % 256);
129 }
130
131 $self->{"local_addr"} = undef; # Don't bind by default
9539e94f 132 $self->{"retrans"} = $def_factor; # Default exponential backoff rate
c94ff782 133 $self->{"econnrefused"} = undef; # Default Connection refused behavior
f569508e 134
e82f584b
JH
135 $self->{"seq"} = 0; # For counting packets
136 if ($self->{"proto"} eq "udp") # Open a socket
137 {
a636724d 138 $self->{"proto_num"} = eval { (getprotobyname('udp'))[2] } ||
e82f584b
JH
139 croak("Can't udp protocol by name");
140 $self->{"port_num"} = (getservbyname('echo', 'udp'))[2] ||
141 croak("Can't get udp echo port by name");
142 $self->{"fh"} = FileHandle->new();
143 socket($self->{"fh"}, PF_INET, SOCK_DGRAM,
144 $self->{"proto_num"}) ||
145 croak("udp socket error - $!");
f569508e
HS
146 if ($self->{'device'}) {
147 setsockopt($self->{"fh"}, SOL_SOCKET, SO_BINDTODEVICE(), pack("Z*", $self->{'device'}))
148 or croak "error binding to device $self->{'device'} $!";
149 }
03550e9d 150 if ($self->{'tos'}) {
1bd59f2c 151 setsockopt($self->{"fh"}, IPPROTO_IP, IP_TOS, pack("I*", $self->{'tos'}))
03550e9d
JH
152 or croak "error configuring tos to $self->{'tos'} $!";
153 }
e82f584b
JH
154 }
155 elsif ($self->{"proto"} eq "icmp")
156 {
f569508e 157 croak("icmp ping requires root privilege") if ($> and $^O ne 'VMS' and $^O ne 'cygwin');
a636724d 158 $self->{"proto_num"} = eval { (getprotobyname('icmp'))[2] } ||
e82f584b
JH
159 croak("Can't get icmp protocol by name");
160 $self->{"pid"} = $$ & 0xffff; # Save lower 16 bits of pid
161 $self->{"fh"} = FileHandle->new();
162 socket($self->{"fh"}, PF_INET, SOCK_RAW, $self->{"proto_num"}) ||
163 croak("icmp socket error - $!");
f569508e
HS
164 if ($self->{'device'}) {
165 setsockopt($self->{"fh"}, SOL_SOCKET, SO_BINDTODEVICE(), pack("Z*", $self->{'device'}))
166 or croak "error binding to device $self->{'device'} $!";
167 }
03550e9d 168 if ($self->{'tos'}) {
1bd59f2c 169 setsockopt($self->{"fh"}, IPPROTO_IP, IP_TOS, pack("I*", $self->{'tos'}))
03550e9d
JH
170 or croak "error configuring tos to $self->{'tos'} $!";
171 }
1bd59f2c
SP
172 if ($self->{'ttl'}) {
173 setsockopt($self->{"fh"}, IPPROTO_IP, IP_TTL, pack("I*", $self->{'ttl'}))
174 or croak "error configuring ttl to $self->{'ttl'} $!";
175 }
e82f584b
JH
176 }
177 elsif ($self->{"proto"} eq "tcp" || $self->{"proto"} eq "stream")
178 {
a636724d 179 $self->{"proto_num"} = eval { (getprotobyname('tcp'))[2] } ||
e82f584b
JH
180 croak("Can't get tcp protocol by name");
181 $self->{"port_num"} = (getservbyname('echo', 'tcp'))[2] ||
182 croak("Can't get tcp echo port by name");
183 $self->{"fh"} = FileHandle->new();
184 }
f569508e
HS
185 elsif ($self->{"proto"} eq "syn")
186 {
a636724d 187 $self->{"proto_num"} = eval { (getprotobyname('tcp'))[2] } ||
f569508e
HS
188 croak("Can't get tcp protocol by name");
189 $self->{"port_num"} = (getservbyname('echo', 'tcp'))[2] ||
190 croak("Can't get tcp echo port by name");
191 if ($syn_forking) {
192 $self->{"fork_rd"} = FileHandle->new();
193 $self->{"fork_wr"} = FileHandle->new();
194 pipe($self->{"fork_rd"}, $self->{"fork_wr"});
195 $self->{"fh"} = FileHandle->new();
69c74a9c
HS
196 $self->{"good"} = {};
197 $self->{"bad"} = {};
f569508e
HS
198 } else {
199 $self->{"wbits"} = "";
200 $self->{"bad"} = {};
201 }
202 $self->{"syn"} = {};
203 $self->{"stop_time"} = 0;
204 }
205 elsif ($self->{"proto"} eq "external")
206 {
207 # No preliminary work needs to be done.
208 }
e82f584b
JH
209
210 return($self);
a3b93737 211}
a0d0e21e 212
49afa5f6
JH
213# Description: Set the local IP address from which pings will be sent.
214# For ICMP and UDP pings, this calls bind() on the already-opened socket;
215# for TCP pings, just saves the address to be used when the socket is
216# opened. Returns non-zero if successful; croaks on error.
217sub bind
218{
e82f584b
JH
219 my ($self,
220 $local_addr # Name or IP number of local interface
221 ) = @_;
222 my ($ip # Packed IP number of $local_addr
223 );
224
225 croak("Usage: \$p->bind(\$local_addr)") unless @_ == 2;
226 croak("already bound") if defined($self->{"local_addr"}) &&
227 ($self->{"proto"} eq "udp" || $self->{"proto"} eq "icmp");
228
229 $ip = inet_aton($local_addr);
230 croak("nonexistent local address $local_addr") unless defined($ip);
231 $self->{"local_addr"} = $ip; # Only used if proto is tcp
232
233 if ($self->{"proto"} eq "udp" || $self->{"proto"} eq "icmp")
234 {
235 CORE::bind($self->{"fh"}, sockaddr_in(0, $ip)) ||
236 croak("$self->{'proto'} bind error - $!");
237 }
03550e9d 238 elsif (($self->{"proto"} ne "tcp") && ($self->{"proto"} ne "syn"))
e82f584b
JH
239 {
240 croak("Unknown protocol \"$self->{proto}\" in bind()");
241 }
242
243 return 1;
244}
49afa5f6 245
eb194dd9
GS
246# Description: A select() wrapper that compensates for platform
247# peculiarities.
248sub mselect
249{
250 if ($_[3] > 0 and $^O eq 'MSWin32') {
251 # On windows, select() doesn't process the message loop,
252 # but sleep() will, allowing alarm() to interrupt the latter.
253 # So we chop up the timeout into smaller pieces and interleave
254 # select() and sleep() calls.
255 my $t = $_[3];
256 my $gran = 0.5; # polling granularity in seconds
257 my @args = @_;
258 while (1) {
259 $gran = $t if $gran > $t;
260 my $nfound = select($_[0], $_[1], $_[2], $gran);
95d3daf0 261 undef $nfound if $nfound == -1;
eb194dd9
GS
262 $t -= $gran;
263 return $nfound if $nfound or !defined($nfound) or $t <= 0;
264
265 sleep(0);
266 ($_[0], $_[1], $_[2]) = @args;
267 }
268 }
269 else {
95d3daf0
RGS
270 my $nfound = select($_[0], $_[1], $_[2], $_[3]);
271 undef $nfound if $nfound == -1;
272 return $nfound;
eb194dd9
GS
273 }
274}
49afa5f6 275
3c4b39be 276# Description: Allow UDP source endpoint comparison to be
15d96390
JH
277# skipped for those remote interfaces that do
278# not response from the same endpoint.
279
280sub source_verify
281{
282 my $self = shift;
5d20095f
JH
283 $source_verify = 1 unless defined
284 ($source_verify = ((defined $self) && (ref $self)) ? shift() : $self);
15d96390
JH
285}
286
c94ff782
JH
287# Description: Set whether or not the connect
288# behavior should enforce remote service
289# availability as well as reachability.
f569508e 290
c94ff782 291sub service_check
f569508e
HS
292{
293 my $self = shift;
c94ff782
JH
294 $self->{"econnrefused"} = 1 unless defined
295 ($self->{"econnrefused"} = shift());
296}
297
298sub tcp_service_check
299{
300 service_check(@_);
f569508e
HS
301}
302
9539e94f
JH
303# Description: Set exponential backoff for retransmission.
304# Should be > 1 to retain exponential properties.
305# If set to 0, retransmissions are disabled.
306
307sub retrans
308{
309 my $self = shift;
310 $self->{"retrans"} = shift;
311}
312
e82f584b
JH
313# Description: allows the module to use milliseconds as returned by
314# the Time::HiRes module
49afa5f6 315
4e0aac35 316$hires = 1;
e82f584b
JH
317sub hires
318{
319 my $self = shift;
320 $hires = 1 unless defined
321 ($hires = ((defined $self) && (ref $self)) ? shift() : $self);
49afa5f6
JH
322}
323
e82f584b
JH
324sub time
325{
326 return $hires ? Time::HiRes::time() : CORE::time();
327}
49afa5f6 328
9c36735d
JH
329# Description: Sets or clears the O_NONBLOCK flag on a file handle.
330sub socket_blocking_mode
331{
332 my ($self,
333 $fh, # the file handle whose flags are to be modified
334 $block) = @_; # if true then set the blocking
335 # mode (clear O_NONBLOCK), otherwise
336 # set the non-blocking mode (set O_NONBLOCK)
337
338 my $flags;
d135e082
CB
339 if ($^O eq 'MSWin32' || $^O eq 'VMS') {
340 # FIONBIO enables non-blocking sockets on windows and vms.
341 # FIONBIO is (0x80000000|(4<<16)|(ord('f')<<8)|126), as per winsock.h, ioctl.h
eb194dd9
GS
342 my $f = 0x8004667e;
343 my $v = pack("L", $block ? 0 : 1);
344 ioctl($fh, $f, $v) or croak("ioctl failed: $!");
345 return;
346 }
9c36735d
JH
347 if ($flags = fcntl($fh, F_GETFL, 0)) {
348 $flags = $block ? ($flags & ~O_NONBLOCK) : ($flags | O_NONBLOCK);
349 if (!fcntl($fh, F_SETFL, $flags)) {
350 croak("fcntl F_SETFL: $!");
351 }
352 } else {
353 croak("fcntl F_GETFL: $!");
354 }
355}
356
a3b93737
RM
357# Description: Ping a host name or IP number with an optional timeout.
358# First lookup the host, and return undef if it is not found. Otherwise
b124990b 359# perform the specific ping method based on the protocol. Return the
a3b93737
RM
360# result of the ping.
361
362sub ping
363{
e82f584b
JH
364 my ($self,
365 $host, # Name or IP number of host to ping
366 $timeout, # Seconds after which ping times out
367 ) = @_;
368 my ($ip, # Packed IP number of $host
369 $ret, # The return value
370 $ping_time, # When ping began
371 );
372
373 croak("Usage: \$p->ping(\$host [, \$timeout])") unless @_ == 2 || @_ == 3;
374 $timeout = $self->{"timeout"} unless $timeout;
375 croak("Timeout must be greater than 0 seconds") if $timeout <= 0;
376
377 $ip = inet_aton($host);
c94ff782 378 return () unless defined($ip); # Does host exist?
e82f584b
JH
379
380 # Dispatch to the appropriate routine.
381 $ping_time = &time();
382 if ($self->{"proto"} eq "external") {
383 $ret = $self->ping_external($ip, $timeout);
384 }
385 elsif ($self->{"proto"} eq "udp") {
386 $ret = $self->ping_udp($ip, $timeout);
387 }
388 elsif ($self->{"proto"} eq "icmp") {
389 $ret = $self->ping_icmp($ip, $timeout);
390 }
391 elsif ($self->{"proto"} eq "tcp") {
392 $ret = $self->ping_tcp($ip, $timeout);
393 }
394 elsif ($self->{"proto"} eq "stream") {
395 $ret = $self->ping_stream($ip, $timeout);
f569508e
HS
396 }
397 elsif ($self->{"proto"} eq "syn") {
398 $ret = $self->ping_syn($host, $ip, $ping_time, $ping_time+$timeout);
e82f584b 399 } else {
787ecdfa 400 croak("Unknown protocol \"$self->{proto}\" in ping()");
e82f584b
JH
401 }
402
4e0aac35 403 return wantarray ? ($ret, &time() - $ping_time, $self->ntop($ip)) : $ret;
787ecdfa
JH
404}
405
406# Uses Net::Ping::External to do an external ping.
407sub ping_external {
408 my ($self,
409 $ip, # Packed IP number of the host
410 $timeout # Seconds after which ping times out
411 ) = @_;
412
8901ddee
TC
413 eval {
414 local @INC = @INC;
415 pop @INC if $INC[-1] eq '.';
416 require Net::Ping::External;
417 }
b124990b 418 or croak('Protocol "external" not supported on your system: Net::Ping::External not found');
787ecdfa 419 return Net::Ping::External::ping(ip => $ip, timeout => $timeout);
a3b93737 420}
a0d0e21e 421
46b9c7d8
GA
422use constant ICMP_ECHOREPLY => 0; # ICMP packet types
423use constant ICMP_UNREACHABLE => 3; # ICMP packet types
424use constant ICMP_ECHO => 8;
1bd59f2c
SP
425use constant ICMP_TIME_EXCEEDED => 11; # ICMP packet types
426use constant ICMP_PARAMETER_PROBLEM => 12; # ICMP packet types
46b9c7d8
GA
427use constant ICMP_STRUCT => "C2 n3 A"; # Structure of a minimal ICMP packet
428use constant SUBCODE => 0; # No ICMP subcode for ECHO and ECHOREPLY
429use constant ICMP_FLAGS => 0; # No special flags for send or recv
430use constant ICMP_PORT => 0; # No port with ICMP
49afa5f6 431
a3b93737
RM
432sub ping_icmp
433{
e82f584b
JH
434 my ($self,
435 $ip, # Packed IP number of the host
436 $timeout # Seconds after which ping times out
437 ) = @_;
438
439 my ($saddr, # sockaddr_in with port and ip
440 $checksum, # Checksum of ICMP packet
441 $msg, # ICMP packet to send
442 $len_msg, # Length of $msg
443 $rbits, # Read bits, filehandles for reading
444 $nfound, # Number of ready filehandles found
445 $finish_time, # Time ping should be finished
446 $done, # set to 1 when we are done
447 $ret, # Return value
448 $recv_msg, # Received message including IP header
449 $from_saddr, # sockaddr_in of sender
450 $from_port, # Port packet was sent from
451 $from_ip, # Packed IP of sender
452 $from_type, # ICMP type
453 $from_subcode, # ICMP subcode
454 $from_chk, # ICMP packet checksum
455 $from_pid, # ICMP packet id
456 $from_seq, # ICMP packet sequence
457 $from_msg # ICMP message
458 );
459
460 $self->{"seq"} = ($self->{"seq"} + 1) % 65536; # Increment sequence
461 $checksum = 0; # No checksum for starters
462 $msg = pack(ICMP_STRUCT . $self->{"data_size"}, ICMP_ECHO, SUBCODE,
463 $checksum, $self->{"pid"}, $self->{"seq"}, $self->{"data"});
464 $checksum = Net::Ping->checksum($msg);
465 $msg = pack(ICMP_STRUCT . $self->{"data_size"}, ICMP_ECHO, SUBCODE,
466 $checksum, $self->{"pid"}, $self->{"seq"}, $self->{"data"});
467 $len_msg = length($msg);
468 $saddr = sockaddr_in(ICMP_PORT, $ip);
9c36735d
JH
469 $self->{"from_ip"} = undef;
470 $self->{"from_type"} = undef;
471 $self->{"from_subcode"} = undef;
e82f584b
JH
472 send($self->{"fh"}, $msg, ICMP_FLAGS, $saddr); # Send the message
473
474 $rbits = "";
475 vec($rbits, $self->{"fh"}->fileno(), 1) = 1;
476 $ret = 0;
477 $done = 0;
478 $finish_time = &time() + $timeout; # Must be done by this time
479 while (!$done && $timeout > 0) # Keep trying if we have time
480 {
eb194dd9 481 $nfound = mselect((my $rout=$rbits), undef, undef, $timeout); # Wait for packet
e82f584b 482 $timeout = $finish_time - &time(); # Get remaining time
95d3daf0 483 if (!defined($nfound)) # Hmm, a strange error
a3b93737 484 {
e82f584b
JH
485 $ret = undef;
486 $done = 1;
487 }
488 elsif ($nfound) # Got a packet from somewhere
489 {
490 $recv_msg = "";
9539e94f
JH
491 $from_pid = -1;
492 $from_seq = -1;
e82f584b
JH
493 $from_saddr = recv($self->{"fh"}, $recv_msg, 1500, ICMP_FLAGS);
494 ($from_port, $from_ip) = sockaddr_in($from_saddr);
9c36735d 495 ($from_type, $from_subcode) = unpack("C2", substr($recv_msg, 20, 2));
9539e94f
JH
496 if ($from_type == ICMP_ECHOREPLY) {
497 ($from_pid, $from_seq) = unpack("n3", substr($recv_msg, 24, 4))
498 if length $recv_msg >= 28;
9c36735d 499 } else {
9539e94f
JH
500 ($from_pid, $from_seq) = unpack("n3", substr($recv_msg, 52, 4))
501 if length $recv_msg >= 56;
9c36735d
JH
502 }
503 $self->{"from_ip"} = $from_ip;
504 $self->{"from_type"} = $from_type;
505 $self->{"from_subcode"} = $from_subcode;
1bd59f2c
SP
506 next if ($from_pid != $self->{"pid"});
507 next if ($from_seq != $self->{"seq"});
4e0aac35 508 if (! $source_verify || ($self->ntop($from_ip) eq $self->ntop($ip))) { # Does the packet check out?
46b9c7d8 509 if ($from_type == ICMP_ECHOREPLY) {
9c36735d 510 $ret = 1;
1bd59f2c 511 $done = 1;
46b9c7d8
GA
512 } elsif ($from_type == ICMP_UNREACHABLE) {
513 $done = 1;
1bd59f2c
SP
514 } elsif ($from_type == ICMP_TIME_EXCEEDED) {
515 $ret = 0;
516 $done = 1;
9c36735d 517 }
e82f584b 518 }
9c36735d 519 } else { # Oops, timed out
e82f584b
JH
520 $done = 1;
521 }
522 }
523 return $ret;
a3b93737
RM
524}
525
9c36735d
JH
526sub icmp_result {
527 my ($self) = @_;
528 my $ip = $self->{"from_ip"} || "";
529 $ip = "\0\0\0\0" unless 4 == length $ip;
4e0aac35 530 return ($self->ntop($ip),($self->{"from_type"} || 0), ($self->{"from_subcode"} || 0));
9c36735d
JH
531}
532
a3b93737
RM
533# Description: Do a checksum on the message. Basically sum all of
534# the short words and fold the high order bits into the low order bits.
535
536sub checksum
537{
e82f584b
JH
538 my ($class,
539 $msg # The message to checksum
540 ) = @_;
541 my ($len_msg, # Length of the message
542 $num_short, # The number of short words in the message
543 $short, # One short word
544 $chk # The checksum
545 );
546
547 $len_msg = length($msg);
548 $num_short = int($len_msg / 2);
549 $chk = 0;
9c36735d 550 foreach $short (unpack("n$num_short", $msg))
e82f584b
JH
551 {
552 $chk += $short;
553 } # Add the odd byte in
554 $chk += (unpack("C", substr($msg, $len_msg - 1, 1)) << 8) if $len_msg % 2;
555 $chk = ($chk >> 16) + ($chk & 0xffff); # Fold high into low
556 return(~(($chk >> 16) + $chk) & 0xffff); # Again and complement
a3b93737
RM
557}
558
787ecdfa 559
b124990b
JH
560# Description: Perform a tcp echo ping. Since a tcp connection is
561# host specific, we have to open and close each connection here. We
562# can't just leave a socket open. Because of the robust nature of
563# tcp, it will take a while before it gives up trying to establish a
564# connection. Therefore, we use select() on a non-blocking socket to
565# check against our timeout. No data bytes are actually
566# sent since the successful establishment of a connection is proof
567# enough of the reachability of the remote host. Also, tcp is
568# expensive and doesn't need our help to add to the overhead.
569
570sub ping_tcp
787ecdfa 571{
e82f584b
JH
572 my ($self,
573 $ip, # Packed IP number of the host
574 $timeout # Seconds after which ping times out
575 ) = @_;
576 my ($ret # The return value
577 );
578
9c36735d 579 $! = 0;
e82f584b 580 $ret = $self -> tcp_connect( $ip, $timeout);
c94ff782 581 if (!$self->{"econnrefused"} &&
f569508e
HS
582 $! == ECONNREFUSED) {
583 $ret = 1; # "Connection refused" means reachable
584 }
e82f584b
JH
585 $self->{"fh"}->close();
586 return $ret;
787ecdfa
JH
587}
588
b124990b 589sub tcp_connect
787ecdfa 590{
e82f584b
JH
591 my ($self,
592 $ip, # Packed IP number of the host
593 $timeout # Seconds after which connect times out
594 ) = @_;
595 my ($saddr); # Packed IP and Port
b124990b 596
e82f584b 597 $saddr = sockaddr_in($self->{"port_num"}, $ip);
b124990b 598
e82f584b 599 my $ret = 0; # Default to unreachable
b124990b 600
e82f584b
JH
601 my $do_socket = sub {
602 socket($self->{"fh"}, PF_INET, SOCK_STREAM, $self->{"proto_num"}) ||
603 croak("tcp socket error - $!");
604 if (defined $self->{"local_addr"} &&
605 !CORE::bind($self->{"fh"}, sockaddr_in(0, $self->{"local_addr"}))) {
606 croak("tcp bind error - $!");
607 }
f569508e
HS
608 if ($self->{'device'}) {
609 setsockopt($self->{"fh"}, SOL_SOCKET, SO_BINDTODEVICE(), pack("Z*", $self->{'device'}))
610 or croak("error binding to device $self->{'device'} $!");
611 }
03550e9d 612 if ($self->{'tos'}) {
1bd59f2c 613 setsockopt($self->{"fh"}, IPPROTO_IP, IP_TOS, pack("I*", $self->{'tos'}))
03550e9d
JH
614 or croak "error configuring tos to $self->{'tos'} $!";
615 }
e82f584b
JH
616 };
617 my $do_connect = sub {
9c36735d 618 $self->{"ip"} = $ip;
6dbac12b
GS
619 # ECONNREFUSED is 10061 on MSWin32. If we pass it as child error through $?,
620 # we'll get (10061 & 255) = 77, so we cannot check it in the parent process.
621 return ($ret = connect($self->{"fh"}, $saddr) || ($! == ECONNREFUSED && !$self->{"econnrefused"}));
e82f584b 622 };
9c36735d
JH
623 my $do_connect_nb = sub {
624 # Set O_NONBLOCK property on filehandle
625 $self->socket_blocking_mode($self->{"fh"}, 0);
626
627 # start the connection attempt
628 if (!connect($self->{"fh"}, $saddr)) {
629 if ($! == ECONNREFUSED) {
c94ff782 630 $ret = 1 unless $self->{"econnrefused"};
eb194dd9 631 } elsif ($! != EINPROGRESS && ($^O ne 'MSWin32' || $! != EWOULDBLOCK)) {
9c36735d 632 # EINPROGRESS is the expected error code after a connect()
c94ff782
JH
633 # on a non-blocking socket. But if the kernel immediately
634 # determined that this connect() will never work,
635 # Simply respond with "unreachable" status.
636 # (This can occur on some platforms with errno
637 # EHOSTUNREACH or ENETUNREACH.)
638 return 0;
639 } else {
640 # Got the expected EINPROGRESS.
641 # Just wait for connection completion...
eb194dd9
GS
642 my ($wbits, $wout, $wexc);
643 $wout = $wexc = $wbits = "";
9c36735d
JH
644 vec($wbits, $self->{"fh"}->fileno, 1) = 1;
645
eb194dd9
GS
646 my $nfound = mselect(undef,
647 ($wout = $wbits),
648 ($^O eq 'MSWin32' ? ($wexc = $wbits) : undef),
649 $timeout);
9c36735d
JH
650 warn("select: $!") unless defined $nfound;
651
652 if ($nfound && vec($wout, $self->{"fh"}->fileno, 1)) {
653 # the socket is ready for writing so the connection
654 # attempt completed. test whether the connection
655 # attempt was successful or not
656
657 if (getpeername($self->{"fh"})) {
658 # Connection established to remote host
659 $ret = 1;
660 } else {
661 # TCP ACK will never come from this host
662 # because there was an error connecting.
e82f584b 663
9c36735d
JH
664 # This should set $! to the correct error.
665 my $char;
666 sysread($self->{"fh"},$char,1);
667 $! = ECONNREFUSED if ($! == EAGAIN && $^O =~ /cygwin/i);
e82f584b 668
c94ff782 669 $ret = 1 if (!$self->{"econnrefused"}
9c36735d
JH
670 && $! == ECONNREFUSED);
671 }
672 } else {
eb194dd9
GS
673 # the connection attempt timed out (or there were connect
674 # errors on Windows)
675 if ($^O =~ 'MSWin32') {
676 # If the connect will fail on a non-blocking socket,
677 # winsock reports ECONNREFUSED as an exception, and we
678 # need to fetch the socket-level error code via getsockopt()
679 # instead of using the thread-level error code that is in $!.
680 if ($nfound && vec($wexc, $self->{"fh"}->fileno, 1)) {
681 $! = unpack("i", getsockopt($self->{"fh"}, SOL_SOCKET,
682 SO_ERROR));
683 }
684 }
9c36735d
JH
685 }
686 }
687 } else {
688 # Connection established to remote host
689 $ret = 1;
690 }
691
692 # Unset O_NONBLOCK property on filehandle
693 $self->socket_blocking_mode($self->{"fh"}, 1);
694 $self->{"ip"} = $ip;
695 return $ret;
696 };
697
698 if ($syn_forking) {
699 # Buggy Winsock API doesn't allow nonblocking connect.
e82f584b
JH
700 # Hence, if our OS is Windows, we need to create a separate
701 # process to do the blocking connect attempt.
eb194dd9
GS
702 # XXX Above comments are not true at least for Win2K, where
703 # nonblocking connect works.
e82f584b
JH
704
705 $| = 1; # Clear buffer prior to fork to prevent duplicate flushing.
9c36735d
JH
706 $self->{'tcp_chld'} = fork;
707 if (!$self->{'tcp_chld'}) {
708 if (!defined $self->{'tcp_chld'}) {
e82f584b 709 # Fork did not work
9c36735d 710 warn "Fork error: $!";
e82f584b 711 return 0;
b124990b 712 }
b124990b
JH
713 &{ $do_socket }();
714
e82f584b 715 # Try a slow blocking connect() call
9c36735d 716 # and report the status to the parent.
e82f584b
JH
717 if ( &{ $do_connect }() ) {
718 $self->{"fh"}->close();
719 # No error
720 exit 0;
b124990b 721 } else {
e82f584b 722 # Pass the error status to the parent
6dbac12b
GS
723 # Make sure that $! <= 255
724 exit($! <= 255 ? $! : 255);
b124990b 725 }
e82f584b 726 }
b124990b 727
e82f584b
JH
728 &{ $do_socket }();
729
730 my $patience = &time() + $timeout;
731
9c36735d
JH
732 my ($child, $child_errno);
733 $? = 0; $child_errno = 0;
e82f584b
JH
734 # Wait up to the timeout
735 # And clean off the zombie
736 do {
9c36735d
JH
737 $child = waitpid($self->{'tcp_chld'}, &WNOHANG());
738 $child_errno = $? >> 8;
e82f584b 739 select(undef, undef, undef, 0.1);
9c36735d
JH
740 } while &time() < $patience && $child != $self->{'tcp_chld'};
741
742 if ($child == $self->{'tcp_chld'}) {
743 if ($self->{"proto"} eq "stream") {
744 # We need the socket connected here, in parent
745 # Should be safe to connect because the child finished
746 # within the timeout
747 &{ $do_connect }();
748 }
6dbac12b
GS
749 # $ret cannot be set by the child process
750 $ret = !$child_errno;
e82f584b
JH
751 } else {
752 # Time must have run out.
e82f584b 753 # Put that choking client out of its misery
9c36735d 754 kill "KILL", $self->{'tcp_chld'};
e82f584b 755 # Clean off the zombie
9c36735d 756 waitpid($self->{'tcp_chld'}, 0);
e82f584b 757 $ret = 0;
b124990b 758 }
9c36735d
JH
759 delete $self->{'tcp_chld'};
760 $! = $child_errno;
761 } else {
e82f584b
JH
762 # Otherwise don't waste the resources to fork
763
764 &{ $do_socket }();
765
9c36735d 766 &{ $do_connect_nb }();
e82f584b 767 }
787ecdfa 768
e82f584b 769 return $ret;
787ecdfa
JH
770}
771
9c36735d
JH
772sub DESTROY {
773 my $self = shift;
774 if ($self->{'proto'} eq 'tcp' &&
775 $self->{'tcp_chld'}) {
776 # Put that choking client out of its misery
777 kill "KILL", $self->{'tcp_chld'};
778 # Clean off the zombie
779 waitpid($self->{'tcp_chld'}, 0);
780 }
781}
782
787ecdfa
JH
783# This writes the given string to the socket and then reads it
784# back. It returns 1 on success, 0 on failure.
785sub tcp_echo
786{
e82f584b
JH
787 my $self = shift;
788 my $timeout = shift;
789 my $pingstring = shift;
790
791 my $ret = undef;
792 my $time = &time();
793 my $wrstr = $pingstring;
794 my $rdstr = "";
795
796 eval <<'EOM';
797 do {
798 my $rin = "";
799 vec($rin, $self->{"fh"}->fileno(), 1) = 1;
800
801 my $rout = undef;
802 if($wrstr) {
803 $rout = "";
804 vec($rout, $self->{"fh"}->fileno(), 1) = 1;
805 }
806
eb194dd9 807 if(mselect($rin, $rout, undef, ($time + $timeout) - &time())) {
e82f584b
JH
808
809 if($rout && vec($rout,$self->{"fh"}->fileno(),1)) {
9c36735d 810 my $num = syswrite($self->{"fh"}, $wrstr, length $wrstr);
e82f584b
JH
811 if($num) {
812 # If it was a partial write, update and try again.
813 $wrstr = substr($wrstr,$num);
814 } else {
815 # There was an error.
816 $ret = 0;
817 }
818 }
819
820 if(vec($rin,$self->{"fh"}->fileno(),1)) {
821 my $reply;
822 if(sysread($self->{"fh"},$reply,length($pingstring)-length($rdstr))) {
823 $rdstr .= $reply;
824 $ret = 1 if $rdstr eq $pingstring;
825 } else {
826 # There was an error.
827 $ret = 0;
828 }
829 }
830
831 }
832 } until &time() > ($time + $timeout) || defined($ret);
787ecdfa
JH
833EOM
834
e82f584b 835 return $ret;
787ecdfa
JH
836}
837
787ecdfa 838
787ecdfa 839
787ecdfa
JH
840
841# Description: Perform a stream ping. If the tcp connection isn't
842# already open, it opens it. It then sends some data and waits for
843# a reply. It leaves the stream open on exit.
844
845sub ping_stream
846{
e82f584b
JH
847 my ($self,
848 $ip, # Packed IP number of the host
849 $timeout # Seconds after which ping times out
850 ) = @_;
072620d9 851
e82f584b
JH
852 # Open the stream if it's not already open
853 if(!defined $self->{"fh"}->fileno()) {
854 $self->tcp_connect($ip, $timeout) or return 0;
855 }
787ecdfa 856
e82f584b
JH
857 croak "tried to switch servers while stream pinging"
858 if $self->{"ip"} ne $ip;
859
860 return $self->tcp_echo($timeout, $pingstring);
787ecdfa
JH
861}
862
863# Description: opens the stream. You would do this if you want to
864# separate the overhead of opening the stream from the first ping.
865
866sub open
867{
e82f584b
JH
868 my ($self,
869 $host, # Host or IP address
870 $timeout # Seconds after which open times out
871 ) = @_;
872
873 my ($ip); # Packed IP number of the host
874 $ip = inet_aton($host);
875 $timeout = $self->{"timeout"} unless $timeout;
876
877 if($self->{"proto"} eq "stream") {
878 if(defined($self->{"fh"}->fileno())) {
879 croak("socket is already open");
880 } else {
881 $self->tcp_connect($ip, $timeout);
b124990b 882 }
e82f584b 883 }
072620d9
SB
884}
885
b124990b 886
a3b93737
RM
887# Description: Perform a udp echo ping. Construct a message of
888# at least the one-byte sequence number and any additional data bytes.
889# Send the message out and wait for a message to come back. If we
890# get a message, make sure all of its parts match. If they do, we are
891# done. Otherwise go back and wait for the message until we run out
892# of time. Return the result of our efforts.
893
49afa5f6 894use constant UDP_FLAGS => 0; # Nothing special on send or recv
a3b93737
RM
895sub ping_udp
896{
e82f584b
JH
897 my ($self,
898 $ip, # Packed IP number of the host
899 $timeout # Seconds after which ping times out
900 ) = @_;
901
902 my ($saddr, # sockaddr_in with port and ip
903 $ret, # The return value
904 $msg, # Message to be echoed
905 $finish_time, # Time ping should be finished
9539e94f
JH
906 $flush, # Whether socket needs to be disconnected
907 $connect, # Whether socket needs to be connected
e82f584b
JH
908 $done, # Set to 1 when we are done pinging
909 $rbits, # Read bits, filehandles for reading
910 $nfound, # Number of ready filehandles found
911 $from_saddr, # sockaddr_in of sender
912 $from_msg, # Characters echoed by $host
913 $from_port, # Port message was echoed from
914 $from_ip # Packed IP number of sender
915 );
916
917 $saddr = sockaddr_in($self->{"port_num"}, $ip);
918 $self->{"seq"} = ($self->{"seq"} + 1) % 256; # Increment sequence
919 $msg = chr($self->{"seq"}) . $self->{"data"}; # Add data if any
9539e94f
JH
920
921 if ($self->{"connected"}) {
922 if ($self->{"connected"} ne $saddr) {
923 # Still connected to wrong destination.
924 # Need to flush out the old one.
925 $flush = 1;
926 }
927 } else {
928 # Not connected yet.
929 # Need to connect() before send()
930 $connect = 1;
931 }
932
c94ff782
JH
933 # Have to connect() and send() instead of sendto()
934 # in order to pick up on the ECONNREFUSED setting
935 # from recv() or double send() errno as utilized in
936 # the concept by rdw @ perlmonks. See:
937 # http://perlmonks.thepen.com/42898.html
9539e94f
JH
938 if ($flush) {
939 # Need to socket() again to flush the descriptor
940 # This will disconnect from the old saddr.
941 socket($self->{"fh"}, PF_INET, SOCK_DGRAM,
942 $self->{"proto_num"});
943 }
944 # Connect the socket if it isn't already connected
945 # to the right destination.
946 if ($flush || $connect) {
947 connect($self->{"fh"}, $saddr); # Tie destination to socket
948 $self->{"connected"} = $saddr;
949 }
c94ff782 950 send($self->{"fh"}, $msg, UDP_FLAGS); # Send it
e82f584b
JH
951
952 $rbits = "";
953 vec($rbits, $self->{"fh"}->fileno(), 1) = 1;
954 $ret = 0; # Default to unreachable
955 $done = 0;
c94ff782 956 my $retrans = 0.01;
9539e94f 957 my $factor = $self->{"retrans"};
e82f584b
JH
958 $finish_time = &time() + $timeout; # Ping needs to be done by then
959 while (!$done && $timeout > 0)
960 {
9539e94f
JH
961 if ($factor > 1)
962 {
963 $timeout = $retrans if $timeout > $retrans;
964 $retrans*= $factor; # Exponential backoff
965 }
eb194dd9 966 $nfound = mselect((my $rout=$rbits), undef, undef, $timeout); # Wait for response
c94ff782 967 my $why = $!;
e82f584b
JH
968 $timeout = $finish_time - &time(); # Get remaining time
969
970 if (!defined($nfound)) # Hmm, a strange error
a3b93737 971 {
e82f584b
JH
972 $ret = undef;
973 $done = 1;
a3b93737 974 }
e82f584b
JH
975 elsif ($nfound) # A packet is waiting
976 {
977 $from_msg = "";
c94ff782
JH
978 $from_saddr = recv($self->{"fh"}, $from_msg, 1500, UDP_FLAGS);
979 if (!$from_saddr) {
980 # For example an unreachable host will make recv() fail.
981 if (!$self->{"econnrefused"} &&
9539e94f
JH
982 ($! == ECONNREFUSED ||
983 $! == ECONNRESET)) {
c94ff782
JH
984 # "Connection refused" means reachable
985 # Good, continue
986 $ret = 1;
987 }
e82f584b 988 $done = 1;
c94ff782
JH
989 } else {
990 ($from_port, $from_ip) = sockaddr_in($from_saddr);
991 if (!$source_verify ||
992 (($from_ip eq $ip) && # Does the packet check out?
993 ($from_port == $self->{"port_num"}) &&
994 ($from_msg eq $msg)))
995 {
996 $ret = 1; # It's a winner
997 $done = 1;
998 }
e82f584b
JH
999 }
1000 }
c94ff782 1001 elsif ($timeout <= 0) # Oops, timed out
e82f584b
JH
1002 {
1003 $done = 1;
1004 }
c94ff782
JH
1005 else
1006 {
1007 # Send another in case the last one dropped
1008 if (send($self->{"fh"}, $msg, UDP_FLAGS)) {
1009 # Another send worked? The previous udp packet
1010 # must have gotten lost or is still in transit.
1011 # Hopefully this new packet will arrive safely.
1012 } else {
1013 if (!$self->{"econnrefused"} &&
1014 $! == ECONNREFUSED) {
1015 # "Connection refused" means reachable
1016 # Good, continue
1017 $ret = 1;
1018 }
1019 $done = 1;
1020 }
1021 }
e82f584b 1022 }
a5a165b1 1023 return $ret;
b124990b 1024}
a0d0e21e 1025
f569508e
HS
1026# Description: Send a TCP SYN packet to host specified.
1027sub ping_syn
1028{
1029 my $self = shift;
1030 my $host = shift;
1031 my $ip = shift;
1032 my $start_time = shift;
1033 my $stop_time = shift;
1034
1035 if ($syn_forking) {
1036 return $self->ping_syn_fork($host, $ip, $start_time, $stop_time);
1037 }
1038
1039 my $fh = FileHandle->new();
1040 my $saddr = sockaddr_in($self->{"port_num"}, $ip);
1041
1042 # Create TCP socket
1043 if (!socket ($fh, PF_INET, SOCK_STREAM, $self->{"proto_num"})) {
1044 croak("tcp socket error - $!");
1045 }
1046
1047 if (defined $self->{"local_addr"} &&
1048 !CORE::bind($fh, sockaddr_in(0, $self->{"local_addr"}))) {
1049 croak("tcp bind error - $!");
1050 }
1051
1052 if ($self->{'device'}) {
1053 setsockopt($fh, SOL_SOCKET, SO_BINDTODEVICE(), pack("Z*", $self->{'device'}))
1054 or croak("error binding to device $self->{'device'} $!");
1055 }
03550e9d 1056 if ($self->{'tos'}) {
1bd59f2c 1057 setsockopt($fh, IPPROTO_IP, IP_TOS, pack("I*", $self->{'tos'}))
03550e9d
JH
1058 or croak "error configuring tos to $self->{'tos'} $!";
1059 }
f569508e 1060 # Set O_NONBLOCK property on filehandle
9c36735d 1061 $self->socket_blocking_mode($fh, 0);
f569508e
HS
1062
1063 # Attempt the non-blocking connect
1064 # by just sending the TCP SYN packet
1065 if (connect($fh, $saddr)) {
1066 # Non-blocking, yet still connected?
69c74a9c
HS
1067 # Must have connected very quickly,
1068 # or else it wasn't very non-blocking.
1069 #warn "WARNING: Nonblocking connect connected anyway? ($^O)";
1070 } else {
f569508e 1071 # Error occurred connecting.
eb194dd9 1072 if ($! == EINPROGRESS || ($^O eq 'MSWin32' && $! == EWOULDBLOCK)) {
69c74a9c
HS
1073 # The connection is just still in progress.
1074 # This is the expected condition.
1075 } else {
1076 # Just save the error and continue on.
1077 # The ack() can check the status later.
f569508e 1078 $self->{"bad"}->{$host} = $!;
f569508e
HS
1079 }
1080 }
1081
1082 my $entry = [ $host, $ip, $fh, $start_time, $stop_time ];
1083 $self->{"syn"}->{$fh->fileno} = $entry;
1084 if ($self->{"stop_time"} < $stop_time) {
1085 $self->{"stop_time"} = $stop_time;
1086 }
1087 vec($self->{"wbits"}, $fh->fileno, 1) = 1;
1088
1089 return 1;
1090}
1091
1092sub ping_syn_fork {
1093 my ($self, $host, $ip, $start_time, $stop_time) = @_;
1094
1095 # Buggy Winsock API doesn't allow nonblocking connect.
1096 # Hence, if our OS is Windows, we need to create a separate
1097 # process to do the blocking connect attempt.
1098 my $pid = fork();
1099 if (defined $pid) {
1100 if ($pid) {
1101 # Parent process
1102 my $entry = [ $host, $ip, $pid, $start_time, $stop_time ];
1103 $self->{"syn"}->{$pid} = $entry;
1104 if ($self->{"stop_time"} < $stop_time) {
1105 $self->{"stop_time"} = $stop_time;
1106 }
1107 } else {
1108 # Child process
1109 my $saddr = sockaddr_in($self->{"port_num"}, $ip);
1110
1111 # Create TCP socket
1112 if (!socket ($self->{"fh"}, PF_INET, SOCK_STREAM, $self->{"proto_num"})) {
1113 croak("tcp socket error - $!");
1114 }
1115
1116 if (defined $self->{"local_addr"} &&
1117 !CORE::bind($self->{"fh"}, sockaddr_in(0, $self->{"local_addr"}))) {
1118 croak("tcp bind error - $!");
1119 }
1120
1121 if ($self->{'device'}) {
1122 setsockopt($self->{"fh"}, SOL_SOCKET, SO_BINDTODEVICE(), pack("Z*", $self->{'device'}))
1123 or croak("error binding to device $self->{'device'} $!");
1124 }
03550e9d 1125 if ($self->{'tos'}) {
1bd59f2c 1126 setsockopt($self->{"fh"}, IPPROTO_IP, IP_TOS, pack("I*", $self->{'tos'}))
03550e9d
JH
1127 or croak "error configuring tos to $self->{'tos'} $!";
1128 }
f569508e
HS
1129
1130 $!=0;
1131 # Try to connect (could take a long time)
1132 connect($self->{"fh"}, $saddr);
1133 # Notify parent of connect error status
1134 my $err = $!+0;
1135 my $wrstr = "$$ $err";
9c36735d
JH
1136 # Force to 16 chars including \n
1137 $wrstr .= " "x(15 - length $wrstr). "\n";
1138 syswrite($self->{"fork_wr"}, $wrstr, length $wrstr);
f569508e
HS
1139 exit;
1140 }
1141 } else {
1142 # fork() failed?
1143 die "fork: $!";
1144 }
1145 return 1;
1146}
1147
1148# Description: Wait for TCP ACK from host specified
1149# from ping_syn above. If no host is specified, wait
1150# for TCP ACK from any of the hosts in the SYN queue.
1151sub ack
1152{
1153 my $self = shift;
1154
1155 if ($self->{"proto"} eq "syn") {
1156 if ($syn_forking) {
1157 my @answer = $self->ack_unfork(shift);
1158 return wantarray ? @answer : $answer[0];
1159 }
1160 my $wbits = "";
1161 my $stop_time = 0;
1162 if (my $host = shift) {
1163 # Host passed as arg
1164 if (exists $self->{"bad"}->{$host}) {
c94ff782 1165 if (!$self->{"econnrefused"} &&
69c74a9c
HS
1166 $self->{"bad"}->{ $host } &&
1167 (($! = ECONNREFUSED)>0) &&
1168 $self->{"bad"}->{ $host } eq "$!") {
1169 # "Connection refused" means reachable
1170 # Good, continue
1171 } else {
1172 # ECONNREFUSED means no good
1173 return ();
1174 }
f569508e
HS
1175 }
1176 my $host_fd = undef;
1177 foreach my $fd (keys %{ $self->{"syn"} }) {
1178 my $entry = $self->{"syn"}->{$fd};
1179 if ($entry->[0] eq $host) {
1180 $host_fd = $fd;
1181 $stop_time = $entry->[4]
1182 || croak("Corrupted SYN entry for [$host]");
1183 last;
1184 }
1185 }
1186 croak("ack called on [$host] without calling ping first!")
1187 unless defined $host_fd;
1188 vec($wbits, $host_fd, 1) = 1;
1189 } else {
1190 # No $host passed so scan all hosts
1191 # Use the latest stop_time
1192 $stop_time = $self->{"stop_time"};
1193 # Use all the bits
1194 $wbits = $self->{"wbits"};
1195 }
1196
9c36735d 1197 while ($wbits !~ /^\0*\z/) {
f569508e
HS
1198 my $timeout = $stop_time - &time();
1199 # Force a minimum of 10 ms timeout.
69c74a9c
HS
1200 $timeout = 0.01 if $timeout <= 0.01;
1201
1202 my $winner_fd = undef;
1203 my $wout = $wbits;
1204 my $fd = 0;
1205 # Do "bad" fds from $wbits first
9c36735d 1206 while ($wout !~ /^\0*\z/) {
69c74a9c
HS
1207 if (vec($wout, $fd, 1)) {
1208 # Wipe it from future scanning.
1209 vec($wout, $fd, 1) = 0;
1210 if (my $entry = $self->{"syn"}->{$fd}) {
1211 if ($self->{"bad"}->{ $entry->[0] }) {
1212 $winner_fd = $fd;
1213 last;
1214 }
1215 }
1216 }
1217 $fd++;
1218 }
1219
eb194dd9 1220 if (defined($winner_fd) or my $nfound = mselect(undef, ($wout=$wbits), undef, $timeout)) {
69c74a9c
HS
1221 if (defined $winner_fd) {
1222 $fd = $winner_fd;
1223 } else {
1224 # Done waiting for one of the ACKs
1225 $fd = 0;
1226 # Determine which one
9c36735d 1227 while ($wout !~ /^\0*\z/ &&
69c74a9c
HS
1228 !vec($wout, $fd, 1)) {
1229 $fd++;
1230 }
f569508e
HS
1231 }
1232 if (my $entry = $self->{"syn"}->{$fd}) {
69c74a9c
HS
1233 # Wipe it from future scanning.
1234 delete $self->{"syn"}->{$fd};
1235 vec($self->{"wbits"}, $fd, 1) = 0;
1236 vec($wbits, $fd, 1) = 0;
c94ff782 1237 if (!$self->{"econnrefused"} &&
69c74a9c
HS
1238 $self->{"bad"}->{ $entry->[0] } &&
1239 (($! = ECONNREFUSED)>0) &&
1240 $self->{"bad"}->{ $entry->[0] } eq "$!") {
1241 # "Connection refused" means reachable
1242 # Good, continue
1243 } elsif (getpeername($entry->[2])) {
f569508e 1244 # Connection established to remote host
69c74a9c 1245 # Good, continue
f569508e
HS
1246 } else {
1247 # TCP ACK will never come from this host
1248 # because there was an error connecting.
1249
f569508e
HS
1250 # This should set $! to the correct error.
1251 my $char;
9c36735d 1252 sysread($entry->[2],$char,1);
f569508e
HS
1253 # Store the excuse why the connection failed.
1254 $self->{"bad"}->{$entry->[0]} = $!;
c94ff782 1255 if (!$self->{"econnrefused"} &&
69c74a9c
HS
1256 (($! == ECONNREFUSED) ||
1257 ($! == EAGAIN && $^O =~ /cygwin/i))) {
f569508e 1258 # "Connection refused" means reachable
69c74a9c
HS
1259 # Good, continue
1260 } else {
1261 # No good, try the next socket...
1262 next;
f569508e 1263 }
f569508e 1264 }
69c74a9c
HS
1265 # Everything passed okay, return the answer
1266 return wantarray ?
4e0aac35 1267 ($entry->[0], &time() - $entry->[3], $self->ntop($entry->[1]))
69c74a9c 1268 : $entry->[0];
f569508e
HS
1269 } else {
1270 warn "Corrupted SYN entry: unknown fd [$fd] ready!";
1271 vec($wbits, $fd, 1) = 0;
1272 vec($self->{"wbits"}, $fd, 1) = 0;
1273 }
1274 } elsif (defined $nfound) {
1275 # Timed out waiting for ACK
1276 foreach my $fd (keys %{ $self->{"syn"} }) {
1277 if (vec($wbits, $fd, 1)) {
1278 my $entry = $self->{"syn"}->{$fd};
1279 $self->{"bad"}->{$entry->[0]} = "Timed out";
1280 vec($wbits, $fd, 1) = 0;
1281 vec($self->{"wbits"}, $fd, 1) = 0;
1282 delete $self->{"syn"}->{$fd};
1283 }
1284 }
1285 } else {
1286 # Weird error occurred with select()
1287 warn("select: $!");
1288 $self->{"syn"} = {};
1289 $wbits = "";
1290 }
1291 }
1292 }
1293 return ();
1294}
1295
1296sub ack_unfork {
69c74a9c 1297 my ($self,$host) = @_;
f569508e 1298 my $stop_time = $self->{"stop_time"};
69c74a9c 1299 if ($host) {
f569508e 1300 # Host passed as arg
69c74a9c
HS
1301 if (my $entry = $self->{"good"}->{$host}) {
1302 delete $self->{"good"}->{$host};
4e0aac35 1303 return ($entry->[0], &time() - $entry->[3], $self->ntop($entry->[1]));
69c74a9c 1304 }
f569508e
HS
1305 }
1306
1307 my $rbits = "";
1308 my $timeout;
69c74a9c 1309
f569508e
HS
1310 if (keys %{ $self->{"syn"} }) {
1311 # Scan all hosts that are left
1312 vec($rbits, fileno($self->{"fork_rd"}), 1) = 1;
1313 $timeout = $stop_time - &time();
69c74a9c
HS
1314 # Force a minimum of 10 ms timeout.
1315 $timeout = 0.01 if $timeout < 0.01;
f569508e
HS
1316 } else {
1317 # No hosts left to wait for
1318 $timeout = 0;
1319 }
1320
1321 if ($timeout > 0) {
69c74a9c
HS
1322 my $nfound;
1323 while ( keys %{ $self->{"syn"} } and
eb194dd9 1324 $nfound = mselect((my $rout=$rbits), undef, undef, $timeout)) {
f569508e 1325 # Done waiting for one of the ACKs
9c36735d 1326 if (!sysread($self->{"fork_rd"}, $_, 16)) {
f569508e
HS
1327 # Socket closed, which means all children are done.
1328 return ();
1329 }
1330 my ($pid, $how) = split;
1331 if ($pid) {
1332 # Flush the zombie
1333 waitpid($pid, 0);
1334 if (my $entry = $self->{"syn"}->{$pid}) {
1335 # Connection attempt to remote host is done
1336 delete $self->{"syn"}->{$pid};
1337 if (!$how || # If there was no error connecting
c94ff782 1338 (!$self->{"econnrefused"} &&
f569508e 1339 $how == ECONNREFUSED)) { # "Connection refused" means reachable
69c74a9c
HS
1340 if ($host && $entry->[0] ne $host) {
1341 # A good connection, but not the host we need.
1342 # Move it from the "syn" hash to the "good" hash.
1343 $self->{"good"}->{$entry->[0]} = $entry;
1344 # And wait for the next winner
1345 next;
1346 }
4e0aac35 1347 return ($entry->[0], &time() - $entry->[3], $self->ntop($entry->[1]));
f569508e
HS
1348 }
1349 } else {
1350 # Should never happen
1351 die "Unknown ping from pid [$pid]";
1352 }
1353 } else {
1354 die "Empty response from status socket?";
1355 }
69c74a9c
HS
1356 }
1357 if (defined $nfound) {
f569508e
HS
1358 # Timed out waiting for ACK status
1359 } else {
1360 # Weird error occurred with select()
1361 warn("select: $!");
1362 }
1363 }
1364 if (my @synners = keys %{ $self->{"syn"} }) {
1365 # Kill all the synners
1366 kill 9, @synners;
1367 foreach my $pid (@synners) {
1368 # Wait for the deaths to finish
1369 # Then flush off the zombie
1370 waitpid($pid, 0);
1371 }
1372 }
1373 $self->{"syn"} = {};
1374 return ();
1375}
1376
1377# Description: Tell why the ack() failed
1378sub nack {
1379 my $self = shift;
1380 my $host = shift || croak('Usage> nack($failed_ack_host)');
1381 return $self->{"bad"}->{$host} || undef;
1382}
1383
1384# Description: Close the connection.
a3b93737
RM
1385
1386sub close
1387{
e82f584b 1388 my ($self) = @_;
a3b93737 1389
f569508e
HS
1390 if ($self->{"proto"} eq "syn") {
1391 delete $self->{"syn"};
1392 } elsif ($self->{"proto"} eq "tcp") {
1393 # The connection will already be closed
ad0c015e
SP
1394 } elsif ($self->{"proto"} eq "external") {
1395 # Nothing to close
f569508e
HS
1396 } else {
1397 $self->{"fh"}->close();
1398 }
a3b93737
RM
1399}
1400
af96568d
RGS
1401sub port_number {
1402 my $self = shift;
1403 if(@_) {
1404 $self->{port_num} = shift @_;
1405 $self->service_check(1);
1406 }
1407 return $self->{port_num};
1408}
1409
4e0aac35
MM
1410sub ntop {
1411 my($self, $ip) = @_;
1412
1413 # Vista doesn't define a inet_ntop. It has InetNtop instead.
1414 # Not following ANSI... priceless. getnameinfo() is defined
1415 # for Windows 2000 and later, so that may be the choice.
1416
1417 # Any port will work, even undef, but this will work for now.
1418 # Socket warns when undef is passed in, but it still works.
1419 my $port = getservbyname('echo', 'udp');
1420 my $sockaddr = sockaddr_in $port, $ip;
1421 my ($error, $address) = getnameinfo($sockaddr, NI_NUMERICHOST);
1422 if($error) {
1423 croak $error;
1424 }
1425 return $address;
1426}
a3b93737 1427
a0d0e21e 14281;
8e07c86e
AD
1429__END__
1430
8e07c86e
AD
1431=head1 NAME
1432
a3b93737 1433Net::Ping - check a remote host for reachability
8e07c86e
AD
1434
1435=head1 SYNOPSIS
1436
1437 use Net::Ping;
8e07c86e 1438
a3b93737
RM
1439 $p = Net::Ping->new();
1440 print "$host is alive.\n" if $p->ping($host);
1441 $p->close();
1442
1443 $p = Net::Ping->new("icmp");
49afa5f6 1444 $p->bind($my_addr); # Specify source interface of pings
a3b93737
RM
1445 foreach $host (@host_array)
1446 {
1447 print "$host is ";
1448 print "NOT " unless $p->ping($host, 2);
1449 print "reachable.\n";
1450 sleep(1);
1451 }
1452 $p->close();
b124990b 1453
a3b93737 1454 $p = Net::Ping->new("tcp", 2);
b124990b 1455 # Try connecting to the www port instead of the echo port
1bd59f2c 1456 $p->port_number(scalar(getservbyname("http", "tcp")));
a3b93737
RM
1457 while ($stop_time > time())
1458 {
1459 print "$host not reachable ", scalar(localtime()), "\n"
1460 unless $p->ping($host);
1461 sleep(300);
1462 }
1463 undef($p);
b124990b 1464
f569508e
HS
1465 # Like tcp protocol, but with many hosts
1466 $p = Net::Ping->new("syn");
af96568d 1467 $p->port_number(getservbyname("http", "tcp"));
f569508e
HS
1468 foreach $host (@host_array) {
1469 $p->ping($host);
1470 }
1471 while (($host,$rtt,$ip) = $p->ack) {
1472 print "HOST: $host [$ip] ACKed in $rtt seconds.\n";
1473 }
1474
e82f584b
JH
1475 # High precision syntax (requires Time::HiRes)
1476 $p = Net::Ping->new();
1477 $p->hires();
1478 ($ret, $duration, $ip) = $p->ping($host, 5.5);
b08c27cd
FC
1479 printf("$host [ip: $ip] is alive (packet return time: %.2f ms)\n",
1480 1000 * $duration)
e82f584b
JH
1481 if $ret;
1482 $p->close();
1483
a3b93737
RM
1484 # For backward compatibility
1485 print "$host is alive.\n" if pingecho($host);
8e07c86e 1486
a3b93737 1487=head1 DESCRIPTION
8e07c86e 1488
a3b93737
RM
1489This module contains methods to test the reachability of remote
1490hosts on a network. A ping object is first created with optional
1491parameters, a variable number of hosts may be pinged multiple
1492times and then the connection is closed.
1493
f569508e
HS
1494You may choose one of six different protocols to use for the
1495ping. The "tcp" protocol is the default. Note that a live remote host
b124990b 1496may still fail to be pingable by one or more of these protocols. For
f569508e 1497example, www.microsoft.com is generally alive but not "icmp" pingable.
787ecdfa 1498
b124990b
JH
1499With the "tcp" protocol the ping() method attempts to establish a
1500connection to the remote host's echo port. If the connection is
1501successfully established, the remote host is considered reachable. No
1502data is actually echoed. This protocol does not require any special
9c36735d 1503privileges but has higher overhead than the "udp" and "icmp" protocols.
072620d9 1504
b124990b 1505Specifying the "udp" protocol causes the ping() method to send a udp
a3b93737
RM
1506packet to the remote host's echo port. If the echoed packet is
1507received from the remote host and the received packet contains the
1508same data as the packet that was sent, the remote host is considered
1509reachable. This protocol does not require any special privileges.
b124990b 1510It should be borne in mind that, for a udp ping, a host
787ecdfa 1511will be reported as unreachable if it is not running the
b124990b
JH
1512appropriate echo service. For Unix-like systems see L<inetd(8)>
1513for more information.
787ecdfa 1514
b124990b
JH
1515If the "icmp" protocol is specified, the ping() method sends an icmp
1516echo message to the remote host, which is what the UNIX ping program
1517does. If the echoed message is received from the remote host and
1518the echoed information is correct, the remote host is considered
1519reachable. Specifying the "icmp" protocol requires that the program
1520be run as root or that the program be setuid to root.
787ecdfa 1521
b124990b
JH
1522If the "external" protocol is specified, the ping() method attempts to
1523use the C<Net::Ping::External> module to ping the remote host.
1524C<Net::Ping::External> interfaces with your system's default C<ping>
1525utility to perform the ping, and generally produces relatively
787ecdfa
JH
1526accurate results. If C<Net::Ping::External> if not installed on your
1527system, specifying the "external" protocol will result in an error.
edc5bd88 1528
f569508e
HS
1529If the "syn" protocol is specified, the ping() method will only
1530send a TCP SYN packet to the remote host then immediately return.
1531If the syn packet was sent successfully, it will return a true value,
1532otherwise it will return false. NOTE: Unlike the other protocols,
1533the return value does NOT determine if the remote host is alive or
1534not since the full TCP three-way handshake may not have completed
1535yet. The remote host is only considered reachable if it receives
3c4b39be 1536a TCP ACK within the timeout specified. To begin waiting for the
f569508e
HS
1537ACK packets, use the ack() method as explained below. Use the
1538"syn" protocol instead the "tcp" protocol to determine reachability
1539of multiple destinations simultaneously by sending parallel TCP
1540SYN packets. It will not block while testing each remote host.
1541demo/fping is provided in this distribution to demonstrate the
1542"syn" protocol as an example.
1543This protocol does not require any special privileges.
1544
a3b93737
RM
1545=head2 Functions
1546
1547=over 4
1548
1bd59f2c 1549=item Net::Ping->new([$proto [, $def_timeout [, $bytes [, $device [, $tos [, $ttl ]]]]]]);
a3b93737
RM
1550
1551Create a new ping object. All of the parameters are optional. $proto
1552specifies the protocol to use when doing a ping. The current choices
f569508e
HS
1553are "tcp", "udp", "icmp", "stream", "syn", or "external".
1554The default is "tcp".
a3b93737
RM
1555
1556If a default timeout ($def_timeout) in seconds is provided, it is used
1557when a timeout is not given to the ping() method (below). The timeout
1558must be greater than 0 and the default, if not specified, is 5 seconds.
1559
1560If the number of data bytes ($bytes) is given, that many data bytes
1561are included in the ping packet sent to the remote host. The number of
1562data bytes is ignored if the protocol is "tcp". The minimum (and
1563default) number of data bytes is 1 if the protocol is "udp" and 0
1564otherwise. The maximum number of data bytes that can be specified is
15651024.
1566
f569508e 1567If $device is given, this device is used to bind the source endpoint
3c4b39be 1568before sending the ping packet. I believe this only works with
f569508e
HS
1569superuser privileges and with udp and icmp protocols at this time.
1570
3c4b39be 1571If $tos is given, this ToS is configured into the socket.
03550e9d 1572
1bd59f2c
SP
1573For icmp, $ttl can be specified to set the TTL of the outgoing packet.
1574
5d20095f
JH
1575=item $p->ping($host [, $timeout]);
1576
1577Ping the remote host and wait for a response. $host can be either the
1578hostname or the IP number of the remote host. The optional timeout
1579must be greater than 0 seconds and defaults to whatever was specified
1580when the ping object was created. Returns a success flag. If the
1581hostname cannot be found or there is a problem with the IP number, the
1582success flag returned will be undef. Otherwise, the success flag will
1583be 1 if the host is reachable and 0 if it is not. For most practical
1584purposes, undef and 0 and can be treated as the same case. In array
f569508e
HS
1585context, the elapsed time as well as the string form of the ip the
1586host resolved to are also returned. The elapsed time value will
c4a6f826 1587be a float, as returned by the Time::HiRes::time() function, if hires()
5d20095f
JH
1588has been previously called, otherwise it is returned as an integer.
1589
15d96390
JH
1590=item $p->source_verify( { 0 | 1 } );
1591
1592Allows source endpoint verification to be enabled or disabled.
1593This is useful for those remote destinations with multiples
1594interfaces where the response may not originate from the same
1595endpoint that the original destination endpoint was sent to.
5d20095f 1596This only affects udp and icmp protocol pings.
15d96390
JH
1597
1598This is enabled by default.
1599
c94ff782 1600=item $p->service_check( { 0 | 1 } );
f569508e 1601
c94ff782 1602Set whether or not the connect behavior should enforce
f569508e
HS
1603remote service availability as well as reachability. Normally,
1604if the remote server reported ECONNREFUSED, it must have been
1605reachable because of the status packet that it reported.
1606With this option enabled, the full three-way tcp handshake
1607must have been established successfully before it will
1608claim it is reachable. NOTE: It still does nothing more
1609than connect and disconnect. It does not speak any protocol
1610(i.e., HTTP or FTP) to ensure the remote server is sane in
1611any way. The remote server CPU could be grinding to a halt
1612and unresponsive to any clients connecting, but if the kernel
1613throws the ACK packet, it is considered alive anyway. To
1614really determine if the server is responding well would be
1615application specific and is beyond the scope of Net::Ping.
c94ff782
JH
1616For udp protocol, enabling this option demands that the
1617remote server replies with the same udp data that it was sent
1618as defined by the udp echo service.
f569508e 1619
c94ff782 1620This affects the "udp", "tcp", and "syn" protocols.
f569508e
HS
1621
1622This is disabled by default.
1623
c94ff782
JH
1624=item $p->tcp_service_check( { 0 | 1 } );
1625
3c4b39be 1626Deprecated method, but does the same as service_check() method.
c94ff782 1627
e82f584b
JH
1628=item $p->hires( { 0 | 1 } );
1629
1630Causes this module to use Time::HiRes module, allowing milliseconds
1631to be returned by subsequent calls to ping().
1632
15d96390
JH
1633This is disabled by default.
1634
49afa5f6
JH
1635=item $p->bind($local_addr);
1636
1637Sets the source address from which pings will be sent. This must be
1638the address of one of the interfaces on the local host. $local_addr
1639may be specified as a hostname or as a text IP address such as
1640"192.168.1.1".
1641
1642If the protocol is set to "tcp", this method may be called any
1643number of times, and each call to the ping() method (below) will use
1644the most recent $local_addr. If the protocol is "icmp" or "udp",
1645then bind() must be called at most once per object, and (if it is
1646called at all) must be called before the first call to ping() for that
1647object.
1648
b124990b
JH
1649=item $p->open($host);
1650
f569508e 1651When you are using the "stream" protocol, this call pre-opens the
b124990b
JH
1652tcp socket. It's only necessary to do this if you want to
1653provide a different timeout when creating the connection, or
1654remove the overhead of establishing the connection from the
1655first ping. If you don't call C<open()>, the connection is
1656automatically opened the first time C<ping()> is called.
787ecdfa
JH
1657This call simply does nothing if you are using any protocol other
1658than stream.
1659
f569508e
HS
1660=item $p->ack( [ $host ] );
1661
1662When using the "syn" protocol, use this method to determine
1663the reachability of the remote host. This method is meant
1664to be called up to as many times as ping() was called. Each
1665call returns the host (as passed to ping()) that came back
1666with the TCP ACK. The order in which the hosts are returned
1667may not necessarily be the same order in which they were
1668SYN queued using the ping() method. If the timeout is
1669reached before the TCP ACK is received, or if the remote
1670host is not listening on the port attempted, then the TCP
1671connection will not be established and ack() will return
1672undef. In list context, the host, the ack time, and the
1673dotted ip string will be returned instead of just the host.
1674If the optional $host argument is specified, the return
3c4b39be 1675value will be pertaining to that host only.
f569508e
HS
1676This call simply does nothing if you are using any protocol
1677other than syn.
1678
1679=item $p->nack( $failed_ack_host );
1680
1681The reason that host $failed_ack_host did not receive a
1682valid ACK. Useful to find out why when ack( $fail_ack_host )
1683returns a false value.
1684
a3b93737
RM
1685=item $p->close();
1686
1687Close the network connection for this ping object. The network
1688connection is also closed by "undef $p". The network connection is
1689automatically closed if the ping object goes out of scope (e.g. $p is
1690local to a subroutine and you leave the subroutine).
1691
af96568d
RGS
1692=item $p->port_number([$port_number])
1693
1694When called with a port number, the port number used to ping is set to
1695$port_number rather than using the echo port. It also has the effect
1696of calling C<$p-E<gt>service_check(1)> causing a ping to return a successful
1697response only if that specific port is accessible. This function returns
1698the value of the port that C<ping()> will connect to.
1699
a3b93737
RM
1700=item pingecho($host [, $timeout]);
1701
1702To provide backward compatibility with the previous version of
1703Net::Ping, a pingecho() subroutine is available with the same
1704functionality as before. pingecho() uses the tcp protocol. The
1705return values and parameters are the same as described for the ping()
1706method. This subroutine is obsolete and may be removed in a future
1707version of Net::Ping.
8e07c86e 1708
a3b93737 1709=back
8e07c86e 1710
a3b93737 1711=head1 NOTES
8e07c86e 1712
a3b93737
RM
1713There will be less network overhead (and some efficiency in your
1714program) if you specify either the udp or the icmp protocol. The tcp
1715protocol will generate 2.5 times or more traffic for each ping than
1716either udp or icmp. If many hosts are pinged frequently, you may wish
1717to implement a small wait (e.g. 25ms or more) between each ping to
1718avoid flooding your network with packets.
8e07c86e 1719
a3b93737 1720The icmp protocol requires that the program be run as root or that it
787ecdfa
JH
1721be setuid to root. The other protocols do not require special
1722privileges, but not all network devices implement tcp or udp echo.
8e07c86e 1723
a3b93737
RM
1724Local hosts should normally respond to pings within milliseconds.
1725However, on a very congested network it may take up to 3 seconds or
1726longer to receive an echo packet from the remote host. If the timeout
1727is set too low under these conditions, it will appear that the remote
1728host is not reachable (which is almost the truth).
8e07c86e 1729
a3b93737 1730Reachability doesn't necessarily mean that the remote host is actually
787ecdfa
JH
1731functioning beyond its ability to echo packets. tcp is slightly better
1732at indicating the health of a system than icmp because it uses more
1733of the networking stack to respond.
8e07c86e 1734
a3b93737
RM
1735Because of a lack of anything better, this module uses its own
1736routines to pack and unpack ICMP packets. It would be better for a
1737separate module to be written which understands all of the different
1738kinds of ICMP packets.
8e07c86e 1739
5d20095f
JH
1740=head1 INSTALL
1741
1742The latest source tree is available via cvs:
1743
b08c27cd
FC
1744 cvs -z3 -q -d \
1745 :pserver:anonymous@cvs.roobik.com.:/usr/local/cvsroot/freeware \
1746 checkout Net-Ping
5d20095f
JH
1747 cd Net-Ping
1748
1749The tarball can be created as follows:
1750
1751 perl Makefile.PL ; make ; make dist
1752
1753The latest Net::Ping release can be found at CPAN:
1754
1755 $CPAN/modules/by-module/Net/
1756
17571) Extract the tarball
1758
1759 gtar -zxvf Net-Ping-xxxx.tar.gz
1760 cd Net-Ping-xxxx
1761
17622) Build:
1763
1764 make realclean
1765 perl Makefile.PL
1766 make
1767 make test
1768
17693) Install
1770
1771 make install
1772
1773Or install it RPM Style:
1774
1775 rpm -ta SOURCES/Net-Ping-xxxx.tar.gz
1776
1777 rpm -ih RPMS/noarch/perl-Net-Ping-xxxx.rpm
1778
c94ff782
JH
1779=head1 BUGS
1780
1781For a list of known issues, visit:
1782
1783https://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-Ping
1784
1785To report a new bug, visit:
1786
1787https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-Ping
1788
49afa5f6 1789=head1 AUTHORS
b124990b 1790
e82f584b 1791 Current maintainer:
49afa5f6 1792 bbb@cpan.org (Rob Brown)
b124990b 1793
e82f584b
JH
1794 External protocol:
1795 colinm@cpan.org (Colin McMillen)
1796
b124990b
JH
1797 Stream protocol:
1798 bronson@trestle.com (Scott Bronson)
1799
1800 Original pingecho():
1801 karrer@bernina.ethz.ch (Andreas Karrer)
1802 pmarquess@bfsec.bt.co.uk (Paul Marquess)
1803
1804 Original Net::Ping author:
1805 mose@ns.ccsn.edu (Russell Mosemann)
1806
b124990b
JH
1807=head1 COPYRIGHT
1808
9c36735d 1809Copyright (c) 2002-2003, Rob Brown. All rights reserved.
49afa5f6 1810
e82f584b 1811Copyright (c) 2001, Colin McMillen. All rights reserved.
b124990b
JH
1812
1813This program is free software; you may redistribute it and/or
1814modify it under the same terms as Perl itself.
1815
a3b93737 1816=cut