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