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