1package Net::Ping; 2 3require 5.002; 4require Exporter; 5 6use strict; 7our $hires; 8use Fcntl qw( F_GETFL F_SETFL O_NONBLOCK ); 9use Socket qw( SOCK_DGRAM SOCK_STREAM SOCK_RAW AF_INET PF_INET IPPROTO_TCP 10 SOL_SOCKET SO_ERROR SO_BROADCAST 11 IPPROTO_IP IP_TOS IP_TTL 12 inet_ntoa inet_aton getnameinfo sockaddr_in ); 13use POSIX qw( ENOTCONN ECONNREFUSED ECONNRESET EINPROGRESS EWOULDBLOCK EAGAIN 14 WNOHANG ); 15use FileHandle; 16use Carp; 17use Time::HiRes; 18 19our @ISA = qw(Exporter); 20our @EXPORT = qw(pingecho); 21our @EXPORT_OK = qw(wakeonlan); 22our $VERSION = "2.71"; 23 24# Globals 25 26our $def_timeout = 5; # Default timeout to wait for a reply 27our $def_proto = "tcp"; # Default protocol to use for pinging 28our $def_factor = 1.2; # Default exponential backoff rate. 29our $def_family = AF_INET; # Default family. 30our $max_datasize = 65535; # Maximum data bytes. recommended: 1472 (Ethernet MTU: 1500) 31# The data we exchange with the server for the stream protocol 32our $pingstring = "pingschwingping!\n"; 33our $source_verify = 1; # Default is to verify source endpoint 34our $syn_forking = 0; 35 36# Constants 37 38my $AF_INET6 = eval { Socket::AF_INET6() } || 30; 39my $AF_UNSPEC = eval { Socket::AF_UNSPEC() }; 40my $AI_NUMERICHOST = eval { Socket::AI_NUMERICHOST() } || 4; 41my $NI_NUMERICHOST = eval { Socket::NI_NUMERICHOST() } || 2; 42my $IPPROTO_IPV6 = eval { Socket::IPPROTO_IPV6() } || 41; 43my $NIx_NOSERV = eval { Socket::NIx_NOSERV() } || 2; 44#my $IPV6_HOPLIMIT = eval { Socket::IPV6_HOPLIMIT() }; # ping6 -h 0-255 45my $qr_family = qr/^(?:(?:(:?ip)?v?(?:4|6))|${\AF_INET}|$AF_INET6)$/; 46my $qr_family4 = qr/^(?:(?:(:?ip)?v?4)|${\AF_INET})$/; 47my $Socket_VERSION = eval { $Socket::VERSION }; 48 49if ($^O =~ /Win32/i) { 50 # Hack to avoid this Win32 spewage: 51 # Your vendor has not defined POSIX macro ECONNREFUSED 52 my @pairs = (ECONNREFUSED => 10061, # "Unknown Error" Special Win32 Response? 53 ENOTCONN => 10057, 54 ECONNRESET => 10054, 55 EINPROGRESS => 10036, 56 EWOULDBLOCK => 10035, 57 ); 58 while (my $name = shift @pairs) { 59 my $value = shift @pairs; 60 # When defined, these all are non-zero 61 unless (eval $name) { 62 no strict 'refs'; 63 *{$name} = defined prototype \&{$name} ? sub () {$value} : sub {$value}; 64 } 65 } 66# $syn_forking = 1; # XXX possibly useful in < Win2K ? 67}; 68 69# Description: The pingecho() subroutine is provided for backward 70# compatibility with the original Net::Ping. It accepts a host 71# name/IP and an optional timeout in seconds. Create a tcp ping 72# object and try pinging the host. The result of the ping is returned. 73 74sub pingecho 75{ 76 my ($host, # Name or IP number of host to ping 77 $timeout # Optional timeout in seconds 78 ) = @_; 79 my ($p); # A ping object 80 81 $p = Net::Ping->new("tcp", $timeout); 82 $p->ping($host); # Going out of scope closes the connection 83} 84 85# Description: The new() method creates a new ping object. Optional 86# parameters may be specified for the protocol to use, the timeout in 87# seconds and the size in bytes of additional data which should be 88# included in the packet. 89# After the optional parameters are checked, the data is constructed 90# and a socket is opened if appropriate. The object is returned. 91 92sub new 93{ 94 my ($this, 95 $proto, # Optional protocol to use for pinging 96 $timeout, # Optional timeout in seconds 97 $data_size, # Optional additional bytes of data 98 $device, # Optional device to use 99 $tos, # Optional ToS to set 100 $ttl, # Optional TTL to set 101 $family, # Optional address family (AF_INET) 102 ) = @_; 103 my $class = ref($this) || $this; 104 my $self = {}; 105 my ($cnt, # Count through data bytes 106 $min_datasize # Minimum data bytes required 107 ); 108 109 bless($self, $class); 110 if (ref $proto eq 'HASH') { # support named args 111 for my $k (qw(proto timeout data_size device tos ttl family 112 gateway host port bind retrans pingstring source_verify 113 econnrefused dontfrag 114 IPV6_USE_MIN_MTU IPV6_RECVPATHMTU IPV6_HOPLIMIT)) 115 { 116 if (exists $proto->{$k}) { 117 $self->{$k} = $proto->{$k}; 118 # some are still globals 119 if ($k eq 'pingstring') { $pingstring = $proto->{$k} } 120 if ($k eq 'source_verify') { $source_verify = $proto->{$k} } 121 delete $proto->{$k}; 122 } 123 } 124 if (%$proto) { 125 croak("Invalid named argument: ",join(" ",keys (%$proto))); 126 } 127 $proto = $self->{'proto'}; 128 } 129 130 $proto = $def_proto unless $proto; # Determine the protocol 131 croak('Protocol for ping must be "icmp", "icmpv6", "udp", "tcp", "syn", "stream" or "external"') 132 unless $proto =~ m/^(icmp|icmpv6|udp|tcp|syn|stream|external)$/; 133 $self->{proto} = $proto; 134 135 $timeout = $def_timeout unless defined $timeout; # Determine the timeout 136 croak("Default timeout for ping must be greater than 0 seconds") 137 if $timeout <= 0; 138 $self->{timeout} = $timeout; 139 140 $self->{device} = $device; 141 142 $self->{tos} = $tos; 143 144 if ($self->{'host'}) { 145 my $host = $self->{'host'}; 146 my $ip = _resolv($host) or 147 carp("could not resolve host $host"); 148 $self->{host} = $ip; 149 $self->{family} = $ip->{family}; 150 } 151 152 if ($self->{bind}) { 153 my $addr = $self->{bind}; 154 my $ip = _resolv($addr) 155 or carp("could not resolve local addr $addr"); 156 $self->{local_addr} = $ip; 157 } else { 158 $self->{local_addr} = undef; # Don't bind by default 159 } 160 161 if ($self->{proto} eq 'icmp') { 162 croak('TTL must be from 0 to 255') 163 if ($ttl && ($ttl < 0 || $ttl > 255)); 164 $self->{ttl} = $ttl; 165 } 166 167 if ($family) { 168 if ($family =~ $qr_family) { 169 if ($family =~ $qr_family4) { 170 $self->{family} = AF_INET; 171 } else { 172 $self->{family} = $AF_INET6; 173 } 174 } else { 175 croak('Family must be "ipv4" or "ipv6"') 176 } 177 } else { 178 if ($self->{proto} eq 'icmpv6') { 179 $self->{family} = $AF_INET6; 180 } else { 181 $self->{family} = $def_family; 182 } 183 } 184 185 $min_datasize = ($proto eq "udp") ? 1 : 0; # Determine data size 186 $data_size = $min_datasize unless defined($data_size) && $proto ne "tcp"; 187 # allow for fragmented packets if data_size>1472 (MTU 1500) 188 croak("Data for ping must be from $min_datasize to $max_datasize bytes") 189 if ($data_size < $min_datasize) || ($data_size > $max_datasize); 190 $data_size-- if $self->{proto} eq "udp"; # We provide the first byte 191 $self->{data_size} = $data_size; 192 193 $self->{data} = ""; # Construct data bytes 194 for ($cnt = 0; $cnt < $self->{data_size}; $cnt++) 195 { 196 $self->{data} .= chr($cnt % 256); 197 } 198 199 # Default exponential backoff rate 200 $self->{retrans} = $def_factor unless exists $self->{retrans}; 201 # Default Connection refused behavior 202 $self->{econnrefused} = undef unless exists $self->{econnrefused}; 203 204 $self->{seq} = 0; # For counting packets 205 if ($self->{proto} eq "udp") # Open a socket 206 { 207 $self->{proto_num} = eval { (getprotobyname('udp'))[2] } || 208 croak("Can't udp protocol by name"); 209 $self->{port_num} = $self->{port} 210 || (getservbyname('echo', 'udp'))[2] 211 || croak("Can't get udp echo port by name"); 212 $self->{fh} = FileHandle->new(); 213 socket($self->{fh}, PF_INET, SOCK_DGRAM, 214 $self->{proto_num}) || 215 croak("udp socket error - $!"); 216 $self->_setopts(); 217 } 218 elsif ($self->{proto} eq "icmp") 219 { 220 croak("icmp ping requires root privilege") if !_isroot(); 221 $self->{proto_num} = eval { (getprotobyname('icmp'))[2] } || 222 croak("Can't get icmp protocol by name"); 223 $self->{pid} = $$ & 0xffff; # Save lower 16 bits of pid 224 $self->{fh} = FileHandle->new(); 225 socket($self->{fh}, PF_INET, SOCK_RAW, $self->{proto_num}) || 226 croak("icmp socket error - $!"); 227 $self->_setopts(); 228 if ($self->{'ttl'}) { 229 setsockopt($self->{fh}, IPPROTO_IP, IP_TTL, pack("I*", $self->{'ttl'})) 230 or croak "error configuring ttl to $self->{'ttl'} $!"; 231 } 232 } 233 elsif ($self->{proto} eq "icmpv6") 234 { 235 #croak("icmpv6 ping requires root privilege") if !_isroot(); 236 croak("Wrong family $self->{family} for icmpv6 protocol") 237 if $self->{family} and $self->{family} != $AF_INET6; 238 $self->{family} = $AF_INET6; 239 $self->{proto_num} = eval { (getprotobyname('ipv6-icmp'))[2] } || 240 croak("Can't get ipv6-icmp protocol by name"); # 58 241 $self->{pid} = $$ & 0xffff; # Save lower 16 bits of pid 242 $self->{fh} = FileHandle->new(); 243 socket($self->{fh}, $AF_INET6, SOCK_RAW, $self->{proto_num}) || 244 croak("icmp socket error - $!"); 245 $self->_setopts(); 246 if ($self->{'gateway'}) { 247 my $g = $self->{gateway}; 248 my $ip = _resolv($g) 249 or croak("nonexistent gateway $g"); 250 $self->{family} eq $AF_INET6 251 or croak("gateway requires the AF_INET6 family"); 252 $ip->{family} eq $AF_INET6 253 or croak("gateway address needs to be IPv6"); 254 my $IPV6_NEXTHOP = eval { Socket::IPV6_NEXTHOP() } || 48; # IPV6_3542NEXTHOP, or 21 255 setsockopt($self->{fh}, $IPPROTO_IPV6, $IPV6_NEXTHOP, _pack_sockaddr_in($ip)) 256 or croak "error configuring gateway to $g NEXTHOP $!"; 257 } 258 if (exists $self->{IPV6_USE_MIN_MTU}) { 259 my $IPV6_USE_MIN_MTU = eval { Socket::IPV6_USE_MIN_MTU() } || 42; 260 setsockopt($self->{fh}, $IPPROTO_IPV6, $IPV6_USE_MIN_MTU, 261 pack("I*", $self->{'IPV6_USE_MIN_MT'})) 262 or croak "error configuring IPV6_USE_MIN_MT} $!"; 263 } 264 if (exists $self->{IPV6_RECVPATHMTU}) { 265 my $IPV6_RECVPATHMTU = eval { Socket::IPV6_RECVPATHMTU() } || 43; 266 setsockopt($self->{fh}, $IPPROTO_IPV6, $IPV6_RECVPATHMTU, 267 pack("I*", $self->{'RECVPATHMTU'})) 268 or croak "error configuring IPV6_RECVPATHMTU $!"; 269 } 270 if ($self->{'tos'}) { 271 my $proto = $self->{family} == AF_INET ? IPPROTO_IP : $IPPROTO_IPV6; 272 setsockopt($self->{fh}, $proto, IP_TOS, pack("I*", $self->{'tos'})) 273 or croak "error configuring tos to $self->{'tos'} $!"; 274 } 275 if ($self->{'ttl'}) { 276 my $proto = $self->{family} == AF_INET ? IPPROTO_IP : $IPPROTO_IPV6; 277 setsockopt($self->{fh}, $proto, IP_TTL, pack("I*", $self->{'ttl'})) 278 or croak "error configuring ttl to $self->{'ttl'} $!"; 279 } 280 } 281 elsif ($self->{proto} eq "tcp" || $self->{proto} eq "stream") 282 { 283 $self->{proto_num} = eval { (getprotobyname('tcp'))[2] } || 284 croak("Can't get tcp protocol by name"); 285 $self->{port_num} = $self->{port} 286 || (getservbyname('echo', 'tcp'))[2] 287 || croak("Can't get tcp echo port by name"); 288 $self->{fh} = FileHandle->new(); 289 } 290 elsif ($self->{proto} eq "syn") 291 { 292 $self->{proto_num} = eval { (getprotobyname('tcp'))[2] } || 293 croak("Can't get tcp protocol by name"); 294 $self->{port_num} = (getservbyname('echo', 'tcp'))[2] || 295 croak("Can't get tcp echo port by name"); 296 if ($syn_forking) { 297 $self->{fork_rd} = FileHandle->new(); 298 $self->{fork_wr} = FileHandle->new(); 299 pipe($self->{fork_rd}, $self->{fork_wr}); 300 $self->{fh} = FileHandle->new(); 301 $self->{good} = {}; 302 $self->{bad} = {}; 303 } else { 304 $self->{wbits} = ""; 305 $self->{bad} = {}; 306 } 307 $self->{syn} = {}; 308 $self->{stop_time} = 0; 309 } 310 311 return($self); 312} 313 314# Description: Set the local IP address from which pings will be sent. 315# For ICMP, UDP and TCP pings, just saves the address to be used when 316# the socket is opened. Returns non-zero if successful; croaks on error. 317sub bind 318{ 319 my ($self, 320 $local_addr # Name or IP number of local interface 321 ) = @_; 322 my ($ip, # Hash of addr (string), addr_in (packed), family 323 $h # resolved hash 324 ); 325 326 croak("Usage: \$p->bind(\$local_addr)") unless @_ == 2; 327 croak("already bound") if defined($self->{local_addr}) && 328 ($self->{proto} eq "udp" || $self->{proto} eq "icmp"); 329 330 $ip = $self->_resolv($local_addr); 331 carp("nonexistent local address $local_addr") unless defined($ip); 332 $self->{local_addr} = $ip; 333 334 if (($self->{proto} ne "udp") && 335 ($self->{proto} ne "icmp") && 336 ($self->{proto} ne "tcp") && 337 ($self->{proto} ne "syn")) 338 { 339 croak("Unknown protocol \"$self->{proto}\" in bind()"); 340 } 341 342 return 1; 343} 344 345# Description: A select() wrapper that compensates for platform 346# peculiarities. 347sub mselect 348{ 349 if ($_[3] > 0 and $^O eq 'MSWin32') { 350 # On windows, select() doesn't process the message loop, 351 # but sleep() will, allowing alarm() to interrupt the latter. 352 # So we chop up the timeout into smaller pieces and interleave 353 # select() and sleep() calls. 354 my $t = $_[3]; 355 my $gran = 0.5; # polling granularity in seconds 356 my @args = @_; 357 while (1) { 358 $gran = $t if $gran > $t; 359 my $nfound = select($_[0], $_[1], $_[2], $gran); 360 undef $nfound if $nfound == -1; 361 $t -= $gran; 362 return $nfound if $nfound or !defined($nfound) or $t <= 0; 363 364 sleep(0); 365 ($_[0], $_[1], $_[2]) = @args; 366 } 367 } 368 else { 369 my $nfound = select($_[0], $_[1], $_[2], $_[3]); 370 undef $nfound if $nfound == -1; 371 return $nfound; 372 } 373} 374 375# Description: Allow UDP source endpoint comparison to be 376# skipped for those remote interfaces that do 377# not response from the same endpoint. 378 379sub source_verify 380{ 381 my $self = shift; 382 $source_verify = 1 unless defined 383 ($source_verify = ((defined $self) && (ref $self)) ? shift() : $self); 384} 385 386# Description: Set whether or not the connect 387# behavior should enforce remote service 388# availability as well as reachability. 389 390sub service_check 391{ 392 my $self = shift; 393 $self->{econnrefused} = 1 unless defined 394 ($self->{econnrefused} = shift()); 395} 396 397sub tcp_service_check 398{ 399 service_check(@_); 400} 401 402# Description: Set exponential backoff for retransmission. 403# Should be > 1 to retain exponential properties. 404# If set to 0, retransmissions are disabled. 405 406sub retrans 407{ 408 my $self = shift; 409 $self->{retrans} = shift; 410} 411 412sub _IsAdminUser { 413 return unless $^O eq 'MSWin32' or $^O eq "cygwin"; 414 return unless eval { require Win32 }; 415 return unless defined &Win32::IsAdminUser; 416 return Win32::IsAdminUser(); 417} 418 419sub _isroot { 420 if (($> and $^O ne 'VMS' and $^O ne 'cygwin') 421 or (($^O eq 'MSWin32' or $^O eq 'cygwin') 422 and !_IsAdminUser()) 423 or ($^O eq 'VMS' 424 and (`write sys\$output f\$privilege("SYSPRV")` =~ m/FALSE/))) { 425 return 0; 426 } 427 else { 428 return 1; 429 } 430} 431 432# Description: Sets ipv6 reachability 433# REACHCONF was removed in RFC3542, ping6 -R supports it. requires root. 434 435sub IPV6_REACHCONF 436{ 437 my $self = shift; 438 my $on = shift; 439 if ($on) { 440 my $reachconf = eval { Socket::IPV6_REACHCONF() }; 441 if (!$reachconf) { 442 carp "IPV6_REACHCONF not supported on this platform"; 443 return 0; 444 } 445 if (!_isroot()) { 446 carp "IPV6_REACHCONF requires root permissions"; 447 return 0; 448 } 449 $self->{IPV6_REACHCONF} = 1; 450 } 451 else { 452 return $self->{IPV6_REACHCONF}; 453 } 454} 455 456# Description: set it on or off. 457 458sub IPV6_USE_MIN_MTU 459{ 460 my $self = shift; 461 my $on = shift; 462 if (defined $on) { 463 my $IPV6_USE_MIN_MTU = eval { Socket::IPV6_USE_MIN_MTU() } || 43; 464 #if (!$IPV6_USE_MIN_MTU) { 465 # carp "IPV6_USE_MIN_MTU not supported on this platform"; 466 # return 0; 467 #} 468 $self->{IPV6_USE_MIN_MTU} = $on ? 1 : 0; 469 setsockopt($self->{fh}, $IPPROTO_IPV6, $IPV6_USE_MIN_MTU, 470 pack("I*", $self->{'IPV6_USE_MIN_MT'})) 471 or croak "error configuring IPV6_USE_MIN_MT} $!"; 472 } 473 else { 474 return $self->{IPV6_USE_MIN_MTU}; 475 } 476} 477 478# Description: notify an according MTU 479 480sub IPV6_RECVPATHMTU 481{ 482 my $self = shift; 483 my $on = shift; 484 if ($on) { 485 my $IPV6_RECVPATHMTU = eval { Socket::IPV6_RECVPATHMTU() } || 43; 486 #if (!$RECVPATHMTU) { 487 # carp "IPV6_RECVPATHMTU not supported on this platform"; 488 # return 0; 489 #} 490 $self->{IPV6_RECVPATHMTU} = 1; 491 setsockopt($self->{fh}, $IPPROTO_IPV6, $IPV6_RECVPATHMTU, 492 pack("I*", $self->{'IPV6_RECVPATHMTU'})) 493 or croak "error configuring IPV6_RECVPATHMTU} $!"; 494 } 495 else { 496 return $self->{IPV6_RECVPATHMTU}; 497 } 498} 499 500# Description: allows the module to use milliseconds as returned by 501# the Time::HiRes module 502 503$hires = 1; 504sub hires 505{ 506 my $self = shift; 507 $hires = 1 unless defined 508 ($hires = ((defined $self) && (ref $self)) ? shift() : $self); 509} 510 511sub time 512{ 513 return $hires ? Time::HiRes::time() : CORE::time(); 514} 515 516# Description: Sets or clears the O_NONBLOCK flag on a file handle. 517sub socket_blocking_mode 518{ 519 my ($self, 520 $fh, # the file handle whose flags are to be modified 521 $block) = @_; # if true then set the blocking 522 # mode (clear O_NONBLOCK), otherwise 523 # set the non-blocking mode (set O_NONBLOCK) 524 525 my $flags; 526 if ($^O eq 'MSWin32' || $^O eq 'VMS') { 527 # FIONBIO enables non-blocking sockets on windows and vms. 528 # FIONBIO is (0x80000000|(4<<16)|(ord('f')<<8)|126), as per winsock.h, ioctl.h 529 my $f = 0x8004667e; 530 my $v = pack("L", $block ? 0 : 1); 531 ioctl($fh, $f, $v) or croak("ioctl failed: $!"); 532 return; 533 } 534 if ($flags = fcntl($fh, F_GETFL, 0)) { 535 $flags = $block ? ($flags & ~O_NONBLOCK) : ($flags | O_NONBLOCK); 536 if (!fcntl($fh, F_SETFL, $flags)) { 537 croak("fcntl F_SETFL: $!"); 538 } 539 } else { 540 croak("fcntl F_GETFL: $!"); 541 } 542} 543 544# Description: Ping a host name or IP number with an optional timeout. 545# First lookup the host, and return undef if it is not found. Otherwise 546# perform the specific ping method based on the protocol. Return the 547# result of the ping. 548 549sub ping 550{ 551 my ($self, 552 $host, # Name or IP number of host to ping 553 $timeout, # Seconds after which ping times out 554 $family, # Address family 555 ) = @_; 556 my ($ip, # Hash of addr (string), addr_in (packed), family 557 $ret, # The return value 558 $ping_time, # When ping began 559 ); 560 561 $host = $self->{host} if !defined $host and $self->{host}; 562 croak("Usage: \$p->ping([ \$host [, \$timeout [, \$family]]])") if @_ > 4 or !$host; 563 $timeout = $self->{timeout} unless $timeout; 564 croak("Timeout must be greater than 0 seconds") if $timeout <= 0; 565 566 if ($family) { 567 if ($family =~ $qr_family) { 568 if ($family =~ $qr_family4) { 569 $self->{family_local} = AF_INET; 570 } else { 571 $self->{family_local} = $AF_INET6; 572 } 573 } else { 574 croak('Family must be "ipv4" or "ipv6"') 575 } 576 } else { 577 $self->{family_local} = $self->{family}; 578 } 579 580 $ip = $self->_resolv($host); 581 return () unless defined($ip); # Does host exist? 582 583 # Dispatch to the appropriate routine. 584 $ping_time = &time(); 585 if ($self->{proto} eq "external") { 586 $ret = $self->ping_external($ip, $timeout); 587 } 588 elsif ($self->{proto} eq "udp") { 589 $ret = $self->ping_udp($ip, $timeout); 590 } 591 elsif ($self->{proto} eq "icmp") { 592 $ret = $self->ping_icmp($ip, $timeout); 593 } 594 elsif ($self->{proto} eq "icmpv6") { 595 $ret = $self->ping_icmpv6($ip, $timeout); 596 } 597 elsif ($self->{proto} eq "tcp") { 598 $ret = $self->ping_tcp($ip, $timeout); 599 } 600 elsif ($self->{proto} eq "stream") { 601 $ret = $self->ping_stream($ip, $timeout); 602 } 603 elsif ($self->{proto} eq "syn") { 604 $ret = $self->ping_syn($host, $ip, $ping_time, $ping_time+$timeout); 605 } else { 606 croak("Unknown protocol \"$self->{proto}\" in ping()"); 607 } 608 609 return wantarray ? ($ret, &time() - $ping_time, $self->ntop($ip)) : $ret; 610} 611 612# Uses Net::Ping::External to do an external ping. 613sub ping_external { 614 my ($self, 615 $ip, # Hash of addr (string), addr_in (packed), family 616 $timeout, # Seconds after which ping times out 617 $family 618 ) = @_; 619 620 $ip = $self->{host} if !defined $ip and $self->{host}; 621 $timeout = $self->{timeout} if !defined $timeout and $self->{timeout}; 622 my @addr = exists $ip->{addr_in} 623 ? ('ip' => $ip->{addr_in}) 624 : ('host' => $ip->{host}); 625 626 eval { 627 local @INC = @INC; 628 pop @INC if $INC[-1] eq '.'; 629 require Net::Ping::External; 630 } or croak('Protocol "external" not supported on your system: Net::Ping::External not found'); 631 return Net::Ping::External::ping(@addr, timeout => $timeout, 632 family => $family); 633} 634 635# h2ph "asm/socket.h" 636# require "asm/socket.ph"; 637use constant SO_BINDTODEVICE => 25; 638use constant ICMP_ECHOREPLY => 0; # ICMP packet types 639use constant ICMPv6_ECHOREPLY => 129; # ICMP packet types 640use constant ICMP_UNREACHABLE => 3; # ICMP packet types 641use constant ICMPv6_UNREACHABLE => 1; # ICMP packet types 642use constant ICMP_ECHO => 8; 643use constant ICMPv6_ECHO => 128; 644use constant ICMP_TIME_EXCEEDED => 11; # ICMP packet types 645use constant ICMP_PARAMETER_PROBLEM => 12; # ICMP packet types 646use constant ICMP_TIMESTAMP => 13; 647use constant ICMP_TIMESTAMP_REPLY => 14; 648use constant ICMP_STRUCT => "C2 n3 A"; # Structure of a minimal ICMP packet 649use constant ICMP_TIMESTAMP_STRUCT => "C2 n3 N3"; # Structure of a minimal timestamp ICMP packet 650use constant SUBCODE => 0; # No ICMP subcode for ECHO and ECHOREPLY 651use constant ICMP_FLAGS => 0; # No special flags for send or recv 652use constant ICMP_PORT => 0; # No port with ICMP 653use constant IP_MTU_DISCOVER => 10; # linux only 654 655sub message_type 656{ 657 my ($self, 658 $type 659 ) = @_; 660 661 croak "Setting message type only supported on 'icmp' protocol" 662 unless $self->{proto} eq 'icmp'; 663 664 return $self->{message_type} || 'echo' 665 unless defined($type); 666 667 croak "Supported icmp message type are limited to 'echo' and 'timestamp': '$type' not supported" 668 unless $type =~ /^echo|timestamp$/i; 669 670 $self->{message_type} = lc($type); 671} 672 673sub ping_icmp 674{ 675 my ($self, 676 $ip, # Hash of addr (string), addr_in (packed), family 677 $timeout # Seconds after which ping times out 678 ) = @_; 679 680 my ($saddr, # sockaddr_in with port and ip 681 $checksum, # Checksum of ICMP packet 682 $msg, # ICMP packet to send 683 $len_msg, # Length of $msg 684 $rbits, # Read bits, filehandles for reading 685 $nfound, # Number of ready filehandles found 686 $finish_time, # Time ping should be finished 687 $done, # set to 1 when we are done 688 $ret, # Return value 689 $recv_msg, # Received message including IP header 690 $from_saddr, # sockaddr_in of sender 691 $from_port, # Port packet was sent from 692 $from_ip, # Packed IP of sender 693 $timestamp_msg, # ICMP timestamp message type 694 $from_type, # ICMP type 695 $from_subcode, # ICMP subcode 696 $from_chk, # ICMP packet checksum 697 $from_pid, # ICMP packet id 698 $from_seq, # ICMP packet sequence 699 $from_msg # ICMP message 700 ); 701 702 $ip = $self->{host} if !defined $ip and $self->{host}; 703 $timeout = $self->{timeout} if !defined $timeout and $self->{timeout}; 704 $timestamp_msg = $self->{message_type} && $self->{message_type} eq 'timestamp' ? 1 : 0; 705 706 socket($self->{fh}, $ip->{family}, SOCK_RAW, $self->{proto_num}) || 707 croak("icmp socket error - $!"); 708 709 if (defined $self->{local_addr} && 710 !CORE::bind($self->{fh}, _pack_sockaddr_in(0, $self->{local_addr}))) { 711 croak("icmp bind error - $!"); 712 } 713 $self->_setopts(); 714 715 $self->{seq} = ($self->{seq} + 1) % 65536; # Increment sequence 716 $checksum = 0; # No checksum for starters 717 if ($ip->{family} == AF_INET) { 718 if ($timestamp_msg) { 719 $msg = pack(ICMP_TIMESTAMP_STRUCT, ICMP_TIMESTAMP, SUBCODE, 720 $checksum, $self->{pid}, $self->{seq}, 0, 0, 0); 721 } else { 722 $msg = pack(ICMP_STRUCT . $self->{data_size}, ICMP_ECHO, SUBCODE, 723 $checksum, $self->{pid}, $self->{seq}, $self->{data}); 724 } 725 } else { 726 # how to get SRC 727 my $pseudo_header = pack('a16a16Nnn', $ip->{addr_in}, $ip->{addr_in}, 8+length($self->{data}), 0, 0x003a); 728 $msg = pack(ICMP_STRUCT . $self->{data_size}, ICMPv6_ECHO, SUBCODE, 729 $checksum, $self->{pid}, $self->{seq}, $self->{data}); 730 $msg = $pseudo_header.$msg 731 } 732 $checksum = Net::Ping->checksum($msg); 733 if ($ip->{family} == AF_INET) { 734 if ($timestamp_msg) { 735 $msg = pack(ICMP_TIMESTAMP_STRUCT, ICMP_TIMESTAMP, SUBCODE, 736 $checksum, $self->{pid}, $self->{seq}, 0, 0, 0); 737 } else { 738 $msg = pack(ICMP_STRUCT . $self->{data_size}, ICMP_ECHO, SUBCODE, 739 $checksum, $self->{pid}, $self->{seq}, $self->{data}); 740 } 741 } else { 742 $msg = pack(ICMP_STRUCT . $self->{data_size}, ICMPv6_ECHO, SUBCODE, 743 $checksum, $self->{pid}, $self->{seq}, $self->{data}); 744 } 745 $len_msg = length($msg); 746 $saddr = _pack_sockaddr_in(ICMP_PORT, $ip); 747 $self->{from_ip} = undef; 748 $self->{from_type} = undef; 749 $self->{from_subcode} = undef; 750 send($self->{fh}, $msg, ICMP_FLAGS, $saddr); # Send the message 751 752 $rbits = ""; 753 vec($rbits, $self->{fh}->fileno(), 1) = 1; 754 $ret = 0; 755 $done = 0; 756 $finish_time = &time() + $timeout; # Must be done by this time 757 while (!$done && $timeout > 0) # Keep trying if we have time 758 { 759 $nfound = mselect((my $rout=$rbits), undef, undef, $timeout); # Wait for packet 760 $timeout = $finish_time - &time(); # Get remaining time 761 if (!defined($nfound)) # Hmm, a strange error 762 { 763 $ret = undef; 764 $done = 1; 765 } 766 elsif ($nfound) # Got a packet from somewhere 767 { 768 $recv_msg = ""; 769 $from_pid = -1; 770 $from_seq = -1; 771 $from_saddr = recv($self->{fh}, $recv_msg, 1500, ICMP_FLAGS); 772 ($from_port, $from_ip) = _unpack_sockaddr_in($from_saddr, $ip->{family}); 773 ($from_type, $from_subcode) = unpack("C2", substr($recv_msg, 20, 2)); 774 if ($from_type == ICMP_TIMESTAMP_REPLY) { 775 ($from_pid, $from_seq) = unpack("n3", substr($recv_msg, 24, 4)) 776 if length $recv_msg >= 28; 777 } elsif ($from_type == ICMP_ECHOREPLY) { 778 #warn "ICMP_ECHOREPLY: ", $ip->{family}, " ",$recv_msg, ":", length($recv_msg); 779 ($from_pid, $from_seq) = unpack("n2", substr($recv_msg, 24, 4)) 780 if ($ip->{family} == AF_INET && length $recv_msg == 28); 781 ($from_pid, $from_seq) = unpack("n2", substr($recv_msg, 4, 4)) 782 if ($ip->{family} == $AF_INET6 && length $recv_msg == 8); 783 } elsif ($from_type == ICMPv6_ECHOREPLY) { 784 #($from_pid, $from_seq) = unpack("n3", substr($recv_msg, 24, 4)) 785 # if length $recv_msg >= 28; 786 #($from_pid, $from_seq) = unpack("n2", substr($recv_msg, 24, 4)) 787 # if ($ip->{family} == AF_INET && length $recv_msg == 28); 788 #warn "ICMPv6_ECHOREPLY: ", $ip->{family}, " ",$recv_msg, ":", length($recv_msg); 789 ($from_pid, $from_seq) = unpack("n2", substr($recv_msg, 4, 4)) 790 if ($ip->{family} == $AF_INET6 && length $recv_msg == 8); 791 #} elsif ($from_type == ICMPv6_NI_REPLY) { 792 # ($from_pid, $from_seq) = unpack("n2", substr($recv_msg, 4, 4)) 793 # if ($ip->{family} == $AF_INET6 && length $recv_msg == 8); 794 } else { 795 #warn "ICMP: ", $from_type, " ",$ip->{family}, " ",$recv_msg, ":", length($recv_msg); 796 ($from_pid, $from_seq) = unpack("n2", substr($recv_msg, 52, 4)) 797 if length $recv_msg >= 56; 798 } 799 $self->{from_ip} = $from_ip; 800 $self->{from_type} = $from_type; 801 $self->{from_subcode} = $from_subcode; 802 next if ($from_pid != $self->{pid}); 803 next if ($from_seq != $self->{seq}); 804 if (! $source_verify || ($self->ntop($from_ip) eq $self->ntop($ip))) { # Does the packet check out? 805 if (!$timestamp_msg && (($from_type == ICMP_ECHOREPLY) || ($from_type == ICMPv6_ECHOREPLY))) { 806 $ret = 1; 807 $done = 1; 808 } elsif ($timestamp_msg && $from_type == ICMP_TIMESTAMP_REPLY) { 809 $ret = 1; 810 $done = 1; 811 } elsif (($from_type == ICMP_UNREACHABLE) || ($from_type == ICMPv6_UNREACHABLE)) { 812 $done = 1; 813 } elsif ($from_type == ICMP_TIME_EXCEEDED) { 814 $ret = 0; 815 $done = 1; 816 } 817 } 818 } else { # Oops, timed out 819 $done = 1; 820 } 821 } 822 return $ret; 823} 824 825sub ping_icmpv6 826{ 827 shift->ping_icmp(@_); 828} 829 830sub icmp_result { 831 my ($self) = @_; 832 my $addr = $self->{from_ip} || ""; 833 $addr = "\0\0\0\0" unless 4 == length $addr; 834 return ($self->ntop($addr),($self->{from_type} || 0), ($self->{from_subcode} || 0)); 835} 836 837# Description: Do a checksum on the message. Basically sum all of 838# the short words and fold the high order bits into the low order bits. 839 840sub checksum 841{ 842 my ($class, 843 $msg # The message to checksum 844 ) = @_; 845 my ($len_msg, # Length of the message 846 $num_short, # The number of short words in the message 847 $short, # One short word 848 $chk # The checksum 849 ); 850 851 $len_msg = length($msg); 852 $num_short = int($len_msg / 2); 853 $chk = 0; 854 foreach $short (unpack("n$num_short", $msg)) 855 { 856 $chk += $short; 857 } # Add the odd byte in 858 $chk += (unpack("C", substr($msg, $len_msg - 1, 1)) << 8) if $len_msg % 2; 859 $chk = ($chk >> 16) + ($chk & 0xffff); # Fold high into low 860 return(~(($chk >> 16) + $chk) & 0xffff); # Again and complement 861} 862 863 864# Description: Perform a tcp echo ping. Since a tcp connection is 865# host specific, we have to open and close each connection here. We 866# can't just leave a socket open. Because of the robust nature of 867# tcp, it will take a while before it gives up trying to establish a 868# connection. Therefore, we use select() on a non-blocking socket to 869# check against our timeout. No data bytes are actually 870# sent since the successful establishment of a connection is proof 871# enough of the reachability of the remote host. Also, tcp is 872# expensive and doesn't need our help to add to the overhead. 873 874sub ping_tcp 875{ 876 my ($self, 877 $ip, # Hash of addr (string), addr_in (packed), family 878 $timeout # Seconds after which ping times out 879 ) = @_; 880 my ($ret # The return value 881 ); 882 883 $ip = $self->{host} if !defined $ip and $self->{host}; 884 $timeout = $self->{timeout} if !defined $timeout and $self->{timeout}; 885 886 $! = 0; 887 $ret = $self -> tcp_connect( $ip, $timeout); 888 if (!$self->{econnrefused} && 889 $! == ECONNREFUSED) { 890 $ret = 1; # "Connection refused" means reachable 891 } 892 $self->{fh}->close(); 893 return $ret; 894} 895 896sub tcp_connect 897{ 898 my ($self, 899 $ip, # Hash of addr (string), addr_in (packed), family 900 $timeout # Seconds after which connect times out 901 ) = @_; 902 my ($saddr); # Packed IP and Port 903 904 $ip = $self->{host} if !defined $ip and $self->{host}; 905 $timeout = $self->{timeout} if !defined $timeout and $self->{timeout}; 906 907 $saddr = _pack_sockaddr_in($self->{port_num}, $ip); 908 909 my $ret = 0; # Default to unreachable 910 911 my $do_socket = sub { 912 socket($self->{fh}, $ip->{family}, SOCK_STREAM, $self->{proto_num}) || 913 croak("tcp socket error - $!"); 914 if (defined $self->{local_addr} && 915 !CORE::bind($self->{fh}, _pack_sockaddr_in(0, $self->{local_addr}))) { 916 croak("tcp bind error - $!"); 917 } 918 $self->_setopts(); 919 }; 920 my $do_connect = sub { 921 $self->{ip} = $ip->{addr_in}; 922 # ECONNREFUSED is 10061 on MSWin32. If we pass it as child error through $?, 923 # we'll get (10061 & 255) = 77, so we cannot check it in the parent process. 924 return ($ret = connect($self->{fh}, $saddr) || ($! == ECONNREFUSED && !$self->{econnrefused})); 925 }; 926 my $do_connect_nb = sub { 927 # Set O_NONBLOCK property on filehandle 928 $self->socket_blocking_mode($self->{fh}, 0); 929 930 # start the connection attempt 931 if (!connect($self->{fh}, $saddr)) { 932 if ($! == ECONNREFUSED) { 933 $ret = 1 unless $self->{econnrefused}; 934 } elsif ($! != EINPROGRESS && ($^O ne 'MSWin32' || $! != EWOULDBLOCK)) { 935 # EINPROGRESS is the expected error code after a connect() 936 # on a non-blocking socket. But if the kernel immediately 937 # determined that this connect() will never work, 938 # Simply respond with "unreachable" status. 939 # (This can occur on some platforms with errno 940 # EHOSTUNREACH or ENETUNREACH.) 941 return 0; 942 } else { 943 # Got the expected EINPROGRESS. 944 # Just wait for connection completion... 945 my ($wbits, $wout, $wexc); 946 $wout = $wexc = $wbits = ""; 947 vec($wbits, $self->{fh}->fileno, 1) = 1; 948 949 my $nfound = mselect(undef, 950 ($wout = $wbits), 951 ($^O eq 'MSWin32' ? ($wexc = $wbits) : undef), 952 $timeout); 953 warn("select: $!") unless defined $nfound; 954 955 if ($nfound && vec($wout, $self->{fh}->fileno, 1)) { 956 # the socket is ready for writing so the connection 957 # attempt completed. test whether the connection 958 # attempt was successful or not 959 960 if (getpeername($self->{fh})) { 961 # Connection established to remote host 962 $ret = 1; 963 } else { 964 # TCP ACK will never come from this host 965 # because there was an error connecting. 966 967 # This should set $! to the correct error. 968 my $char; 969 sysread($self->{fh},$char,1); 970 $! = ECONNREFUSED if ($! == EAGAIN && $^O =~ /cygwin/i); 971 972 $ret = 1 if (!$self->{econnrefused} 973 && $! == ECONNREFUSED); 974 } 975 } else { 976 # the connection attempt timed out (or there were connect 977 # errors on Windows) 978 if ($^O =~ 'MSWin32') { 979 # If the connect will fail on a non-blocking socket, 980 # winsock reports ECONNREFUSED as an exception, and we 981 # need to fetch the socket-level error code via getsockopt() 982 # instead of using the thread-level error code that is in $!. 983 if ($nfound && vec($wexc, $self->{fh}->fileno, 1)) { 984 $! = unpack("i", getsockopt($self->{fh}, SOL_SOCKET, 985 SO_ERROR)); 986 } 987 } 988 } 989 } 990 } else { 991 # Connection established to remote host 992 $ret = 1; 993 } 994 995 # Unset O_NONBLOCK property on filehandle 996 $self->socket_blocking_mode($self->{fh}, 1); 997 $self->{ip} = $ip->{addr_in}; 998 return $ret; 999 }; 1000 1001 if ($syn_forking) { 1002 # Buggy Winsock API doesn't allow nonblocking connect. 1003 # Hence, if our OS is Windows, we need to create a separate 1004 # process to do the blocking connect attempt. 1005 # XXX Above comments are not true at least for Win2K, where 1006 # nonblocking connect works. 1007 1008 $| = 1; # Clear buffer prior to fork to prevent duplicate flushing. 1009 $self->{'tcp_chld'} = fork; 1010 if (!$self->{'tcp_chld'}) { 1011 if (!defined $self->{'tcp_chld'}) { 1012 # Fork did not work 1013 warn "Fork error: $!"; 1014 return 0; 1015 } 1016 &{ $do_socket }(); 1017 1018 # Try a slow blocking connect() call 1019 # and report the status to the parent. 1020 if ( &{ $do_connect }() ) { 1021 $self->{fh}->close(); 1022 # No error 1023 exit 0; 1024 } else { 1025 # Pass the error status to the parent 1026 # Make sure that $! <= 255 1027 exit($! <= 255 ? $! : 255); 1028 } 1029 } 1030 1031 &{ $do_socket }(); 1032 1033 my $patience = &time() + $timeout; 1034 1035 my ($child, $child_errno); 1036 $? = 0; $child_errno = 0; 1037 # Wait up to the timeout 1038 # And clean off the zombie 1039 do { 1040 $child = waitpid($self->{'tcp_chld'}, &WNOHANG()); 1041 $child_errno = $? >> 8; 1042 select(undef, undef, undef, 0.1); 1043 } while &time() < $patience && $child != $self->{'tcp_chld'}; 1044 1045 if ($child == $self->{'tcp_chld'}) { 1046 if ($self->{proto} eq "stream") { 1047 # We need the socket connected here, in parent 1048 # Should be safe to connect because the child finished 1049 # within the timeout 1050 &{ $do_connect }(); 1051 } 1052 # $ret cannot be set by the child process 1053 $ret = !$child_errno; 1054 } else { 1055 # Time must have run out. 1056 # Put that choking client out of its misery 1057 kill "KILL", $self->{'tcp_chld'}; 1058 # Clean off the zombie 1059 waitpid($self->{'tcp_chld'}, 0); 1060 $ret = 0; 1061 } 1062 delete $self->{'tcp_chld'}; 1063 $! = $child_errno; 1064 } else { 1065 # Otherwise don't waste the resources to fork 1066 1067 &{ $do_socket }(); 1068 1069 &{ $do_connect_nb }(); 1070 } 1071 1072 return $ret; 1073} 1074 1075sub DESTROY { 1076 my $self = shift; 1077 if ($self->{'proto'} eq 'tcp' && 1078 $self->{'tcp_chld'}) { 1079 # Put that choking client out of its misery 1080 kill "KILL", $self->{'tcp_chld'}; 1081 # Clean off the zombie 1082 waitpid($self->{'tcp_chld'}, 0); 1083 } 1084} 1085 1086# This writes the given string to the socket and then reads it 1087# back. It returns 1 on success, 0 on failure. 1088sub tcp_echo 1089{ 1090 my ($self, $timeout, $pingstring) = @_; 1091 1092 $timeout = $self->{timeout} if !defined $timeout and $self->{timeout}; 1093 $pingstring = $self->{pingstring} if !defined $pingstring and $self->{pingstring}; 1094 1095 my $ret = undef; 1096 my $time = &time(); 1097 my $wrstr = $pingstring; 1098 my $rdstr = ""; 1099 1100 eval <<'EOM'; 1101 do { 1102 my $rin = ""; 1103 vec($rin, $self->{fh}->fileno(), 1) = 1; 1104 1105 my $rout = undef; 1106 if($wrstr) { 1107 $rout = ""; 1108 vec($rout, $self->{fh}->fileno(), 1) = 1; 1109 } 1110 1111 if(mselect($rin, $rout, undef, ($time + $timeout) - &time())) { 1112 1113 if($rout && vec($rout,$self->{fh}->fileno(),1)) { 1114 my $num = syswrite($self->{fh}, $wrstr, length $wrstr); 1115 if($num) { 1116 # If it was a partial write, update and try again. 1117 $wrstr = substr($wrstr,$num); 1118 } else { 1119 # There was an error. 1120 $ret = 0; 1121 } 1122 } 1123 1124 if(vec($rin,$self->{fh}->fileno(),1)) { 1125 my $reply; 1126 if(sysread($self->{fh},$reply,length($pingstring)-length($rdstr))) { 1127 $rdstr .= $reply; 1128 $ret = 1 if $rdstr eq $pingstring; 1129 } else { 1130 # There was an error. 1131 $ret = 0; 1132 } 1133 } 1134 1135 } 1136 } until &time() > ($time + $timeout) || defined($ret); 1137EOM 1138 1139 return $ret; 1140} 1141 1142# Description: Perform a stream ping. If the tcp connection isn't 1143# already open, it opens it. It then sends some data and waits for 1144# a reply. It leaves the stream open on exit. 1145 1146sub ping_stream 1147{ 1148 my ($self, 1149 $ip, # Hash of addr (string), addr_in (packed), family 1150 $timeout # Seconds after which ping times out 1151 ) = @_; 1152 1153 # Open the stream if it's not already open 1154 if(!defined $self->{fh}->fileno()) { 1155 $self->tcp_connect($ip, $timeout) or return 0; 1156 } 1157 1158 croak "tried to switch servers while stream pinging" 1159 if $self->{ip} ne $ip->{addr_in}; 1160 1161 return $self->tcp_echo($timeout, $pingstring); 1162} 1163 1164# Description: opens the stream. You would do this if you want to 1165# separate the overhead of opening the stream from the first ping. 1166 1167sub open 1168{ 1169 my ($self, 1170 $host, # Host or IP address 1171 $timeout, # Seconds after which open times out 1172 $family 1173 ) = @_; 1174 my $ip; # Hash of addr (string), addr_in (packed), family 1175 $host = $self->{host} unless defined $host; 1176 1177 if ($family) { 1178 if ($family =~ $qr_family) { 1179 if ($family =~ $qr_family4) { 1180 $self->{family_local} = AF_INET; 1181 } else { 1182 $self->{family_local} = $AF_INET6; 1183 } 1184 } else { 1185 croak('Family must be "ipv4" or "ipv6"') 1186 } 1187 } else { 1188 $self->{family_local} = $self->{family}; 1189 } 1190 1191 $timeout = $self->{timeout} unless $timeout; 1192 $ip = $self->_resolv($host); 1193 1194 if ($self->{proto} eq "stream") { 1195 if (defined($self->{fh}->fileno())) { 1196 croak("socket is already open"); 1197 } else { 1198 return () unless $ip; 1199 $self->tcp_connect($ip, $timeout); 1200 } 1201 } 1202} 1203 1204sub _dontfrag { 1205 my $self = shift; 1206 # bsd solaris 1207 my $IP_DONTFRAG = eval { Socket::IP_DONTFRAG() }; 1208 if ($IP_DONTFRAG) { 1209 my $i = 1; 1210 setsockopt($self->{fh}, IPPROTO_IP, $IP_DONTFRAG, pack("I*", $i)) 1211 or croak "error configuring IP_DONTFRAG $!"; 1212 # Linux needs more: Path MTU Discovery as defined in RFC 1191 1213 # For non SOCK_STREAM sockets it is the user's responsibility to packetize 1214 # the data in MTU sized chunks and to do the retransmits if necessary. 1215 # The kernel will reject packets that are bigger than the known path 1216 # MTU if this flag is set (with EMSGSIZE). 1217 if ($^O eq 'linux') { 1218 my $i = 2; # IP_PMTUDISC_DO 1219 setsockopt($self->{fh}, IPPROTO_IP, IP_MTU_DISCOVER, pack("I*", $i)) 1220 or croak "error configuring IP_MTU_DISCOVER $!"; 1221 } 1222 } 1223} 1224 1225# SO_BINDTODEVICE + IP_TOS 1226sub _setopts { 1227 my $self = shift; 1228 if ($self->{'device'}) { 1229 setsockopt($self->{fh}, SOL_SOCKET, SO_BINDTODEVICE, pack("Z*", $self->{'device'})) 1230 or croak "error binding to device $self->{'device'} $!"; 1231 } 1232 if ($self->{'tos'}) { # need to re-apply ToS (RT #6706) 1233 setsockopt($self->{fh}, IPPROTO_IP, IP_TOS, pack("I*", $self->{'tos'})) 1234 or croak "error applying tos to $self->{'tos'} $!"; 1235 } 1236 if ($self->{'dontfrag'}) { 1237 $self->_dontfrag; 1238 } 1239} 1240 1241 1242# Description: Perform a udp echo ping. Construct a message of 1243# at least the one-byte sequence number and any additional data bytes. 1244# Send the message out and wait for a message to come back. If we 1245# get a message, make sure all of its parts match. If they do, we are 1246# done. Otherwise go back and wait for the message until we run out 1247# of time. Return the result of our efforts. 1248 1249use constant UDP_FLAGS => 0; # Nothing special on send or recv 1250sub ping_udp 1251{ 1252 my ($self, 1253 $ip, # Hash of addr (string), addr_in (packed), family 1254 $timeout # Seconds after which ping times out 1255 ) = @_; 1256 1257 my ($saddr, # sockaddr_in with port and ip 1258 $ret, # The return value 1259 $msg, # Message to be echoed 1260 $finish_time, # Time ping should be finished 1261 $flush, # Whether socket needs to be disconnected 1262 $connect, # Whether socket needs to be connected 1263 $done, # Set to 1 when we are done pinging 1264 $rbits, # Read bits, filehandles for reading 1265 $nfound, # Number of ready filehandles found 1266 $from_saddr, # sockaddr_in of sender 1267 $from_msg, # Characters echoed by $host 1268 $from_port, # Port message was echoed from 1269 $from_ip # Packed IP number of sender 1270 ); 1271 1272 $saddr = _pack_sockaddr_in($self->{port_num}, $ip); 1273 $self->{seq} = ($self->{seq} + 1) % 256; # Increment sequence 1274 $msg = chr($self->{seq}) . $self->{data}; # Add data if any 1275 1276 socket($self->{fh}, $ip->{family}, SOCK_DGRAM, 1277 $self->{proto_num}) || 1278 croak("udp socket error - $!"); 1279 1280 if (defined $self->{local_addr} && 1281 !CORE::bind($self->{fh}, _pack_sockaddr_in(0, $self->{local_addr}))) { 1282 croak("udp bind error - $!"); 1283 } 1284 1285 $self->_setopts(); 1286 1287 if ($self->{connected}) { 1288 if ($self->{connected} ne $saddr) { 1289 # Still connected to wrong destination. 1290 # Need to flush out the old one. 1291 $flush = 1; 1292 } 1293 } else { 1294 # Not connected yet. 1295 # Need to connect() before send() 1296 $connect = 1; 1297 } 1298 1299 # Have to connect() and send() instead of sendto() 1300 # in order to pick up on the ECONNREFUSED setting 1301 # from recv() or double send() errno as utilized in 1302 # the concept by rdw @ perlmonks. See: 1303 # http://perlmonks.thepen.com/42898.html 1304 if ($flush) { 1305 # Need to socket() again to flush the descriptor 1306 # This will disconnect from the old saddr. 1307 socket($self->{fh}, $ip->{family}, SOCK_DGRAM, 1308 $self->{proto_num}); 1309 $self->_setopts(); 1310 } 1311 # Connect the socket if it isn't already connected 1312 # to the right destination. 1313 if ($flush || $connect) { 1314 connect($self->{fh}, $saddr); # Tie destination to socket 1315 $self->{connected} = $saddr; 1316 } 1317 send($self->{fh}, $msg, UDP_FLAGS); # Send it 1318 1319 $rbits = ""; 1320 vec($rbits, $self->{fh}->fileno(), 1) = 1; 1321 $ret = 0; # Default to unreachable 1322 $done = 0; 1323 my $retrans = 0.01; 1324 my $factor = $self->{retrans}; 1325 $finish_time = &time() + $timeout; # Ping needs to be done by then 1326 while (!$done && $timeout > 0) 1327 { 1328 if ($factor > 1) 1329 { 1330 $timeout = $retrans if $timeout > $retrans; 1331 $retrans*= $factor; # Exponential backoff 1332 } 1333 $nfound = mselect((my $rout=$rbits), undef, undef, $timeout); # Wait for response 1334 my $why = $!; 1335 $timeout = $finish_time - &time(); # Get remaining time 1336 1337 if (!defined($nfound)) # Hmm, a strange error 1338 { 1339 $ret = undef; 1340 $done = 1; 1341 } 1342 elsif ($nfound) # A packet is waiting 1343 { 1344 $from_msg = ""; 1345 $from_saddr = recv($self->{fh}, $from_msg, 1500, UDP_FLAGS); 1346 if (!$from_saddr) { 1347 # For example an unreachable host will make recv() fail. 1348 if (!$self->{econnrefused} && 1349 ($! == ECONNREFUSED || 1350 $! == ECONNRESET)) { 1351 # "Connection refused" means reachable 1352 # Good, continue 1353 $ret = 1; 1354 } 1355 $done = 1; 1356 } else { 1357 ($from_port, $from_ip) = _unpack_sockaddr_in($from_saddr, $ip->{family}); 1358 my $addr_in = ref($ip) eq "HASH" ? $ip->{addr_in} : $ip; 1359 if (!$source_verify || 1360 (($from_ip eq $addr_in) && # Does the packet check out? 1361 ($from_port == $self->{port_num}) && 1362 ($from_msg eq $msg))) 1363 { 1364 $ret = 1; # It's a winner 1365 $done = 1; 1366 } 1367 } 1368 } 1369 elsif ($timeout <= 0) # Oops, timed out 1370 { 1371 $done = 1; 1372 } 1373 else 1374 { 1375 # Send another in case the last one dropped 1376 if (send($self->{fh}, $msg, UDP_FLAGS)) { 1377 # Another send worked? The previous udp packet 1378 # must have gotten lost or is still in transit. 1379 # Hopefully this new packet will arrive safely. 1380 } else { 1381 if (!$self->{econnrefused} && 1382 $! == ECONNREFUSED) { 1383 # "Connection refused" means reachable 1384 # Good, continue 1385 $ret = 1; 1386 } 1387 $done = 1; 1388 } 1389 } 1390 } 1391 return $ret; 1392} 1393 1394# Description: Send a TCP SYN packet to host specified. 1395sub ping_syn 1396{ 1397 my $self = shift; 1398 my $host = shift; 1399 my $ip = shift; 1400 my $start_time = shift; 1401 my $stop_time = shift; 1402 1403 if ($syn_forking) { 1404 return $self->ping_syn_fork($host, $ip, $start_time, $stop_time); 1405 } 1406 1407 my $fh = FileHandle->new(); 1408 my $saddr = _pack_sockaddr_in($self->{port_num}, $ip); 1409 1410 # Create TCP socket 1411 if (!socket ($fh, $ip->{family}, SOCK_STREAM, $self->{proto_num})) { 1412 croak("tcp socket error - $!"); 1413 } 1414 1415 if (defined $self->{local_addr} && 1416 !CORE::bind($fh, _pack_sockaddr_in(0, $self->{local_addr}))) { 1417 croak("tcp bind error - $!"); 1418 } 1419 1420 $self->_setopts(); 1421 # Set O_NONBLOCK property on filehandle 1422 $self->socket_blocking_mode($fh, 0); 1423 1424 # Attempt the non-blocking connect 1425 # by just sending the TCP SYN packet 1426 if (connect($fh, $saddr)) { 1427 # Non-blocking, yet still connected? 1428 # Must have connected very quickly, 1429 # or else it wasn't very non-blocking. 1430 #warn "WARNING: Nonblocking connect connected anyway? ($^O)"; 1431 } else { 1432 # Error occurred connecting. 1433 if ($! == EINPROGRESS || ($^O eq 'MSWin32' && $! == EWOULDBLOCK)) { 1434 # The connection is just still in progress. 1435 # This is the expected condition. 1436 } else { 1437 # Just save the error and continue on. 1438 # The ack() can check the status later. 1439 $self->{bad}->{$host} = $!; 1440 } 1441 } 1442 1443 my $entry = [ $host, $ip, $fh, $start_time, $stop_time, $self->{port_num} ]; 1444 $self->{syn}->{$fh->fileno} = $entry; 1445 if ($self->{stop_time} < $stop_time) { 1446 $self->{stop_time} = $stop_time; 1447 } 1448 vec($self->{wbits}, $fh->fileno, 1) = 1; 1449 1450 return 1; 1451} 1452 1453sub ping_syn_fork { 1454 my ($self, $host, $ip, $start_time, $stop_time) = @_; 1455 1456 # Buggy Winsock API doesn't allow nonblocking connect. 1457 # Hence, if our OS is Windows, we need to create a separate 1458 # process to do the blocking connect attempt. 1459 my $pid = fork(); 1460 if (defined $pid) { 1461 if ($pid) { 1462 # Parent process 1463 my $entry = [ $host, $ip, $pid, $start_time, $stop_time ]; 1464 $self->{syn}->{$pid} = $entry; 1465 if ($self->{stop_time} < $stop_time) { 1466 $self->{stop_time} = $stop_time; 1467 } 1468 } else { 1469 # Child process 1470 my $saddr = _pack_sockaddr_in($self->{port_num}, $ip); 1471 1472 # Create TCP socket 1473 if (!socket ($self->{fh}, $ip->{family}, SOCK_STREAM, $self->{proto_num})) { 1474 croak("tcp socket error - $!"); 1475 } 1476 1477 if (defined $self->{local_addr} && 1478 !CORE::bind($self->{fh}, _pack_sockaddr_in(0, $self->{local_addr}))) { 1479 croak("tcp bind error - $!"); 1480 } 1481 1482 $self->_setopts(); 1483 1484 $!=0; 1485 # Try to connect (could take a long time) 1486 connect($self->{fh}, $saddr); 1487 # Notify parent of connect error status 1488 my $err = $!+0; 1489 my $wrstr = "$$ $err"; 1490 # Force to 16 chars including \n 1491 $wrstr .= " "x(15 - length $wrstr). "\n"; 1492 syswrite($self->{fork_wr}, $wrstr, length $wrstr); 1493 exit; 1494 } 1495 } else { 1496 # fork() failed? 1497 die "fork: $!"; 1498 } 1499 return 1; 1500} 1501 1502# Description: Wait for TCP ACK from host specified 1503# from ping_syn above. If no host is specified, wait 1504# for TCP ACK from any of the hosts in the SYN queue. 1505sub ack 1506{ 1507 my $self = shift; 1508 1509 if ($self->{proto} eq "syn") { 1510 if ($syn_forking) { 1511 my @answer = $self->ack_unfork(shift); 1512 return wantarray ? @answer : $answer[0]; 1513 } 1514 my $wbits = ""; 1515 my $stop_time = 0; 1516 if (my $host = shift or $self->{host}) { 1517 # Host passed as arg or as option to new 1518 $host = $self->{host} unless defined $host; 1519 if (exists $self->{bad}->{$host}) { 1520 if (!$self->{econnrefused} && 1521 $self->{bad}->{ $host } && 1522 (($! = ECONNREFUSED)>0) && 1523 $self->{bad}->{ $host } eq "$!") { 1524 # "Connection refused" means reachable 1525 # Good, continue 1526 } else { 1527 # ECONNREFUSED means no good 1528 return (); 1529 } 1530 } 1531 my $host_fd = undef; 1532 foreach my $fd (keys %{ $self->{syn} }) { 1533 my $entry = $self->{syn}->{$fd}; 1534 if ($entry->[0] eq $host) { 1535 $host_fd = $fd; 1536 $stop_time = $entry->[4] 1537 || croak("Corrupted SYN entry for [$host]"); 1538 last; 1539 } 1540 } 1541 croak("ack called on [$host] without calling ping first!") 1542 unless defined $host_fd; 1543 vec($wbits, $host_fd, 1) = 1; 1544 } else { 1545 # No $host passed so scan all hosts 1546 # Use the latest stop_time 1547 $stop_time = $self->{stop_time}; 1548 # Use all the bits 1549 $wbits = $self->{wbits}; 1550 } 1551 1552 while ($wbits !~ /^\0*\z/) { 1553 my $timeout = $stop_time - &time(); 1554 # Force a minimum of 10 ms timeout. 1555 $timeout = 0.01 if $timeout <= 0.01; 1556 1557 my $winner_fd = undef; 1558 my $wout = $wbits; 1559 my $fd = 0; 1560 # Do "bad" fds from $wbits first 1561 while ($wout !~ /^\0*\z/) { 1562 if (vec($wout, $fd, 1)) { 1563 # Wipe it from future scanning. 1564 vec($wout, $fd, 1) = 0; 1565 if (my $entry = $self->{syn}->{$fd}) { 1566 if ($self->{bad}->{ $entry->[0] }) { 1567 $winner_fd = $fd; 1568 last; 1569 } 1570 } 1571 } 1572 $fd++; 1573 } 1574 1575 if (defined($winner_fd) or my $nfound = mselect(undef, ($wout=$wbits), undef, $timeout)) { 1576 if (defined $winner_fd) { 1577 $fd = $winner_fd; 1578 } else { 1579 # Done waiting for one of the ACKs 1580 $fd = 0; 1581 # Determine which one 1582 while ($wout !~ /^\0*\z/ && 1583 !vec($wout, $fd, 1)) { 1584 $fd++; 1585 } 1586 } 1587 if (my $entry = $self->{syn}->{$fd}) { 1588 # Wipe it from future scanning. 1589 delete $self->{syn}->{$fd}; 1590 vec($self->{wbits}, $fd, 1) = 0; 1591 vec($wbits, $fd, 1) = 0; 1592 if (!$self->{econnrefused} && 1593 $self->{bad}->{ $entry->[0] } && 1594 (($! = ECONNREFUSED)>0) && 1595 $self->{bad}->{ $entry->[0] } eq "$!") { 1596 # "Connection refused" means reachable 1597 # Good, continue 1598 } elsif (getpeername($entry->[2])) { 1599 # Connection established to remote host 1600 # Good, continue 1601 } else { 1602 # TCP ACK will never come from this host 1603 # because there was an error connecting. 1604 1605 # This should set $! to the correct error. 1606 my $char; 1607 sysread($entry->[2],$char,1); 1608 # Store the excuse why the connection failed. 1609 $self->{bad}->{$entry->[0]} = $!; 1610 if (!$self->{econnrefused} && 1611 (($! == ECONNREFUSED) || 1612 ($! == EAGAIN && $^O =~ /cygwin/i))) { 1613 # "Connection refused" means reachable 1614 # Good, continue 1615 } else { 1616 # No good, try the next socket... 1617 next; 1618 } 1619 } 1620 # Everything passed okay, return the answer 1621 return wantarray ? 1622 ($entry->[0], &time() - $entry->[3], $self->ntop($entry->[1]), $entry->[5]) 1623 : $entry->[0]; 1624 } else { 1625 warn "Corrupted SYN entry: unknown fd [$fd] ready!"; 1626 vec($wbits, $fd, 1) = 0; 1627 vec($self->{wbits}, $fd, 1) = 0; 1628 } 1629 } elsif (defined $nfound) { 1630 # Timed out waiting for ACK 1631 foreach my $fd (keys %{ $self->{syn} }) { 1632 if (vec($wbits, $fd, 1)) { 1633 my $entry = $self->{syn}->{$fd}; 1634 $self->{bad}->{$entry->[0]} = "Timed out"; 1635 vec($wbits, $fd, 1) = 0; 1636 vec($self->{wbits}, $fd, 1) = 0; 1637 delete $self->{syn}->{$fd}; 1638 } 1639 } 1640 } else { 1641 # Weird error occurred with select() 1642 warn("select: $!"); 1643 $self->{syn} = {}; 1644 $wbits = ""; 1645 } 1646 } 1647 } 1648 return (); 1649} 1650 1651sub ack_unfork { 1652 my ($self,$host) = @_; 1653 my $stop_time = $self->{stop_time}; 1654 if ($host) { 1655 # Host passed as arg 1656 if (my $entry = $self->{good}->{$host}) { 1657 delete $self->{good}->{$host}; 1658 return ($entry->[0], &time() - $entry->[3], $self->ntop($entry->[1])); 1659 } 1660 } 1661 1662 my $rbits = ""; 1663 my $timeout; 1664 1665 if (keys %{ $self->{syn} }) { 1666 # Scan all hosts that are left 1667 vec($rbits, fileno($self->{fork_rd}), 1) = 1; 1668 $timeout = $stop_time - &time(); 1669 # Force a minimum of 10 ms timeout. 1670 $timeout = 0.01 if $timeout < 0.01; 1671 } else { 1672 # No hosts left to wait for 1673 $timeout = 0; 1674 } 1675 1676 if ($timeout > 0) { 1677 my $nfound; 1678 while ( keys %{ $self->{syn} } and 1679 $nfound = mselect((my $rout=$rbits), undef, undef, $timeout)) { 1680 # Done waiting for one of the ACKs 1681 if (!sysread($self->{fork_rd}, $_, 16)) { 1682 # Socket closed, which means all children are done. 1683 return (); 1684 } 1685 my ($pid, $how) = split; 1686 if ($pid) { 1687 # Flush the zombie 1688 waitpid($pid, 0); 1689 if (my $entry = $self->{syn}->{$pid}) { 1690 # Connection attempt to remote host is done 1691 delete $self->{syn}->{$pid}; 1692 if (!$how || # If there was no error connecting 1693 (!$self->{econnrefused} && 1694 $how == ECONNREFUSED)) { # "Connection refused" means reachable 1695 if ($host && $entry->[0] ne $host) { 1696 # A good connection, but not the host we need. 1697 # Move it from the "syn" hash to the "good" hash. 1698 $self->{good}->{$entry->[0]} = $entry; 1699 # And wait for the next winner 1700 next; 1701 } 1702 return ($entry->[0], &time() - $entry->[3], $self->ntop($entry->[1])); 1703 } 1704 } else { 1705 # Should never happen 1706 die "Unknown ping from pid [$pid]"; 1707 } 1708 } else { 1709 die "Empty response from status socket?"; 1710 } 1711 } 1712 if (defined $nfound) { 1713 # Timed out waiting for ACK status 1714 } else { 1715 # Weird error occurred with select() 1716 warn("select: $!"); 1717 } 1718 } 1719 if (my @synners = keys %{ $self->{syn} }) { 1720 # Kill all the synners 1721 kill 9, @synners; 1722 foreach my $pid (@synners) { 1723 # Wait for the deaths to finish 1724 # Then flush off the zombie 1725 waitpid($pid, 0); 1726 } 1727 } 1728 $self->{syn} = {}; 1729 return (); 1730} 1731 1732# Description: Tell why the ack() failed 1733sub nack { 1734 my $self = shift; 1735 my $host = shift || croak('Usage> nack($failed_ack_host)'); 1736 return $self->{bad}->{$host} || undef; 1737} 1738 1739# Description: Close the connection. 1740 1741sub close 1742{ 1743 my ($self) = @_; 1744 1745 if ($self->{proto} eq "syn") { 1746 delete $self->{syn}; 1747 } elsif ($self->{proto} eq "tcp") { 1748 # The connection will already be closed 1749 } elsif ($self->{proto} eq "external") { 1750 # Nothing to close 1751 } else { 1752 $self->{fh}->close(); 1753 } 1754} 1755 1756sub port_number { 1757 my $self = shift; 1758 if(@_) { 1759 $self->{port_num} = shift @_; 1760 $self->service_check(1); 1761 } 1762 return $self->{port_num}; 1763} 1764 1765sub ntop { 1766 my($self, $ip) = @_; 1767 1768 # Vista doesn't define a inet_ntop. It has InetNtop instead. 1769 # Not following ANSI... priceless. getnameinfo() is defined 1770 # for Windows 2000 and later, so that may be the choice. 1771 1772 # Any port will work, even undef, but this will work for now. 1773 # Socket warns when undef is passed in, but it still works. 1774 my $port = getservbyname('echo', 'udp'); 1775 my $sockaddr = _pack_sockaddr_in($port, $ip); 1776 my ($error, $address) = getnameinfo($sockaddr, $NI_NUMERICHOST); 1777 croak $error if $error; 1778 return $address; 1779} 1780 1781sub wakeonlan { 1782 my ($mac_addr, $host, $port) = @_; 1783 1784 # use the discard service if $port not passed in 1785 if (! defined $host) { $host = '255.255.255.255' } 1786 if (! defined $port || $port !~ /^\d+$/ ) { $port = 9 } 1787 1788 require IO::Socket::INET; 1789 my $sock = IO::Socket::INET->new(Proto=>'udp') || return undef; 1790 1791 my $ip_addr = inet_aton($host); 1792 my $sock_addr = sockaddr_in($port, $ip_addr); 1793 $mac_addr =~ s/://g; 1794 my $packet = pack('C6H*', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, $mac_addr x 16); 1795 1796 setsockopt($sock, SOL_SOCKET, SO_BROADCAST, 1); 1797 send($sock, $packet, 0, $sock_addr); 1798 $sock->close; 1799 1800 return 1; 1801} 1802 1803######################################################## 1804# DNS hostname resolution 1805# return: 1806# $h->{name} = host - as passed in 1807# $h->{host} = host - as passed in without :port 1808# $h->{port} = OPTIONAL - if :port, then value of port 1809# $h->{addr} = resolved numeric address 1810# $h->{addr_in} = aton/pton result 1811# $h->{family} = AF_INET/6 1812############################ 1813sub _resolv { 1814 my ($self, 1815 $name, 1816 ) = @_; 1817 1818 my %h; 1819 $h{name} = $name; 1820 my $family = $self->{family}; 1821 1822 if (defined($self->{family_local})) { 1823 $family = $self->{family_local} 1824 } 1825 1826# START - host:port 1827 my $cnt = 0; 1828 1829 # Count ":" 1830 $cnt++ while ($name =~ m/:/g); 1831 1832 # 0 = hostname or IPv4 address 1833 if ($cnt == 0) { 1834 $h{host} = $name 1835 # 1 = IPv4 address with port 1836 } elsif ($cnt == 1) { 1837 ($h{host}, $h{port}) = split /:/, $name 1838 # >=2 = IPv6 address 1839 } elsif ($cnt >= 2) { 1840 #IPv6 with port - [2001::1]:port 1841 if ($name =~ /^\[.*\]:\d{1,5}$/) { 1842 ($h{host}, $h{port}) = split /:([^:]+)$/, $name # split after last : 1843 # IPv6 without port 1844 } else { 1845 $h{host} = $name 1846 } 1847 } 1848 1849 # Clean up host 1850 $h{host} =~ s/\[//g; 1851 $h{host} =~ s/\]//g; 1852 # Clean up port 1853 if (defined($h{port}) && (($h{port} !~ /^\d{1,5}$/) || ($h{port} < 1) || ($h{port} > 65535))) { 1854 croak("Invalid port `$h{port}' in `$name'"); 1855 return undef; 1856 } 1857# END - host:port 1858 1859 # address check 1860 # new way 1861 if ($Socket_VERSION > 1.94) { 1862 my %hints = ( 1863 family => $AF_UNSPEC, 1864 protocol => IPPROTO_TCP, 1865 flags => $AI_NUMERICHOST 1866 ); 1867 1868 # numeric address, return 1869 my ($err, @getaddr) = Socket::getaddrinfo($h{host}, undef, \%hints); 1870 if (defined($getaddr[0])) { 1871 $h{addr} = $h{host}; 1872 $h{family} = $getaddr[0]->{family}; 1873 if ($h{family} == AF_INET) { 1874 (undef, $h{addr_in}, undef, undef) = Socket::unpack_sockaddr_in $getaddr[0]->{addr}; 1875 } else { 1876 (undef, $h{addr_in}, undef, undef) = Socket::unpack_sockaddr_in6 $getaddr[0]->{addr}; 1877 } 1878 return \%h 1879 } 1880 # old way 1881 } else { 1882 # numeric address, return 1883 my $ret = gethostbyname($h{host}); 1884 if (defined($ret) && (_inet_ntoa($ret) eq $h{host})) { 1885 $h{addr} = $h{host}; 1886 $h{addr_in} = $ret; 1887 $h{family} = AF_INET; 1888 return \%h 1889 } 1890 } 1891 1892 # resolve 1893 # new way 1894 if ($Socket_VERSION >= 1.94) { 1895 my %hints = ( 1896 family => $family, 1897 protocol => IPPROTO_TCP 1898 ); 1899 1900 my ($err, @getaddr) = Socket::getaddrinfo($h{host}, undef, \%hints); 1901 if (defined($getaddr[0])) { 1902 my ($err, $address) = Socket::getnameinfo($getaddr[0]->{addr}, $NI_NUMERICHOST, $NIx_NOSERV); 1903 if (defined($address)) { 1904 $h{addr} = $address; 1905 $h{addr} =~ s/\%(.)*$//; # remove %ifID if IPv6 1906 $h{family} = $getaddr[0]->{family}; 1907 if ($h{family} == AF_INET) { 1908 (undef, $h{addr_in}, undef, undef) = Socket::unpack_sockaddr_in $getaddr[0]->{addr}; 1909 } else { 1910 (undef, $h{addr_in}, undef, undef) = Socket::unpack_sockaddr_in6 $getaddr[0]->{addr}; 1911 } 1912 return \%h; 1913 } else { 1914 carp("getnameinfo($getaddr[0]->{addr}) failed - $err"); 1915 return undef; 1916 } 1917 } else { 1918 warn(sprintf("getaddrinfo($h{host},,%s) failed - $err", 1919 $family == AF_INET ? "AF_INET" : "AF_INET6")); 1920 return undef; 1921 } 1922 # old way 1923 } else { 1924 if ($family == $AF_INET6) { 1925 croak("Socket >= 1.94 required for IPv6 - found Socket $Socket::VERSION"); 1926 return undef; 1927 } 1928 1929 my @gethost = gethostbyname($h{host}); 1930 if (defined($gethost[4])) { 1931 $h{addr} = inet_ntoa($gethost[4]); 1932 $h{addr_in} = $gethost[4]; 1933 $h{family} = AF_INET; 1934 return \%h 1935 } else { 1936 carp("gethostbyname($h{host}) failed - $^E"); 1937 return undef; 1938 } 1939 } 1940 return undef; 1941} 1942 1943sub _pack_sockaddr_in($$) { 1944 my ($port, 1945 $ip, 1946 ) = @_; 1947 1948 my $addr = ref($ip) eq "HASH" ? $ip->{addr_in} : $ip; 1949 if (length($addr) <= 4 ) { 1950 return Socket::pack_sockaddr_in($port, $addr); 1951 } else { 1952 return Socket::pack_sockaddr_in6($port, $addr); 1953 } 1954} 1955 1956sub _unpack_sockaddr_in($;$) { 1957 my ($addr, 1958 $family, 1959 ) = @_; 1960 1961 my ($port, $host); 1962 if ($family == AF_INET || (!defined($family) and length($addr) <= 16 )) { 1963 ($port, $host) = Socket::unpack_sockaddr_in($addr); 1964 } else { 1965 ($port, $host) = Socket::unpack_sockaddr_in6($addr); 1966 } 1967 return $port, $host 1968} 1969 1970sub _inet_ntoa { 1971 my ($addr 1972 ) = @_; 1973 1974 my $ret; 1975 if ($Socket_VERSION >= 1.94) { 1976 my ($err, $address) = Socket::getnameinfo($addr, $NI_NUMERICHOST); 1977 if (defined($address)) { 1978 $ret = $address; 1979 } else { 1980 carp("getnameinfo($addr) failed - $err"); 1981 } 1982 } else { 1983 $ret = inet_ntoa($addr) 1984 } 1985 1986 return $ret 1987} 1988 19891; 1990__END__ 1991 1992=head1 NAME 1993 1994Net::Ping - check a remote host for reachability 1995 1996=head1 SYNOPSIS 1997 1998 use Net::Ping; 1999 2000 $p = Net::Ping->new(); 2001 print "$host is alive.\n" if $p->ping($host); 2002 $p->close(); 2003 2004 $p = Net::Ping->new("icmp"); 2005 $p->bind($my_addr); # Specify source interface of pings 2006 foreach $host (@host_array) 2007 { 2008 print "$host is "; 2009 print "NOT " unless $p->ping($host, 2); 2010 print "reachable.\n"; 2011 sleep(1); 2012 } 2013 $p->close(); 2014 2015 $p = Net::Ping->new("tcp", 2); 2016 # Try connecting to the www port instead of the echo port 2017 $p->port_number(scalar(getservbyname("http", "tcp"))); 2018 while ($stop_time > time()) 2019 { 2020 print "$host not reachable ", scalar(localtime()), "\n" 2021 unless $p->ping($host); 2022 sleep(300); 2023 } 2024 undef($p); 2025 2026 # Like tcp protocol, but with many hosts 2027 $p = Net::Ping->new("syn"); 2028 $p->port_number(getservbyname("http", "tcp")); 2029 foreach $host (@host_array) { 2030 $p->ping($host); 2031 } 2032 while (($host,$rtt,$ip) = $p->ack) { 2033 print "HOST: $host [$ip] ACKed in $rtt seconds.\n"; 2034 } 2035 2036 # High precision syntax (requires Time::HiRes) 2037 $p = Net::Ping->new(); 2038 $p->hires(); 2039 ($ret, $duration, $ip) = $p->ping($host, 5.5); 2040 printf("$host [ip: $ip] is alive (packet return time: %.2f ms)\n", 2041 1000 * $duration) 2042 if $ret; 2043 $p->close(); 2044 2045 # For backward compatibility 2046 print "$host is alive.\n" if pingecho($host); 2047 2048=head1 DESCRIPTION 2049 2050This module contains methods to test the reachability of remote 2051hosts on a network. A ping object is first created with optional 2052parameters, a variable number of hosts may be pinged multiple 2053times and then the connection is closed. 2054 2055You may choose one of six different protocols to use for the 2056ping. The "tcp" protocol is the default. Note that a live remote host 2057may still fail to be pingable by one or more of these protocols. For 2058example, www.microsoft.com is generally alive but not "icmp" pingable. 2059 2060With the "tcp" protocol the ping() method attempts to establish a 2061connection to the remote host's echo port. If the connection is 2062successfully established, the remote host is considered reachable. No 2063data is actually echoed. This protocol does not require any special 2064privileges but has higher overhead than the "udp" and "icmp" protocols. 2065 2066Specifying the "udp" protocol causes the ping() method to send a udp 2067packet to the remote host's echo port. If the echoed packet is 2068received from the remote host and the received packet contains the 2069same data as the packet that was sent, the remote host is considered 2070reachable. This protocol does not require any special privileges. 2071It should be borne in mind that, for a udp ping, a host 2072will be reported as unreachable if it is not running the 2073appropriate echo service. For Unix-like systems see L<inetd(8)> 2074for more information. 2075 2076If the "icmp" protocol is specified, the ping() method sends an icmp 2077echo message to the remote host, which is what the UNIX ping program 2078does. If the echoed message is received from the remote host and 2079the echoed information is correct, the remote host is considered 2080reachable. Specifying the "icmp" protocol requires that the program 2081be run as root or that the program be setuid to root. 2082 2083If the "external" protocol is specified, the ping() method attempts to 2084use the C<Net::Ping::External> module to ping the remote host. 2085C<Net::Ping::External> interfaces with your system's default C<ping> 2086utility to perform the ping, and generally produces relatively 2087accurate results. If C<Net::Ping::External> if not installed on your 2088system, specifying the "external" protocol will result in an error. 2089 2090If the "syn" protocol is specified, the L</ping> method will only 2091send a TCP SYN packet to the remote host then immediately return. 2092If the syn packet was sent successfully, it will return a true value, 2093otherwise it will return false. NOTE: Unlike the other protocols, 2094the return value does NOT determine if the remote host is alive or 2095not since the full TCP three-way handshake may not have completed 2096yet. The remote host is only considered reachable if it receives 2097a TCP ACK within the timeout specified. To begin waiting for the 2098ACK packets, use the L</ack> method as explained below. Use the 2099"syn" protocol instead the "tcp" protocol to determine reachability 2100of multiple destinations simultaneously by sending parallel TCP 2101SYN packets. It will not block while testing each remote host. 2102This protocol does not require any special privileges. 2103 2104=head2 Functions 2105 2106=over 4 2107 2108=item Net::Ping->new([proto, timeout, bytes, device, tos, ttl, family, 2109 host, port, bind, gateway, retrans, pingstring, 2110 source_verify econnrefused dontfrag 2111 IPV6_USE_MIN_MTU IPV6_RECVPATHMTU]) 2112X<new> 2113 2114Create a new ping object. All of the parameters are optional and can 2115be passed as hash ref. All options besides the first 7 must be passed 2116as hash ref. 2117 2118C<proto> specifies the protocol to use when doing a ping. The current 2119choices are "tcp", "udp", "icmp", "icmpv6", "stream", "syn", or 2120"external". The default is "tcp". 2121 2122If a C<timeout> in seconds is provided, it is used 2123when a timeout is not given to the ping() method (below). The timeout 2124must be greater than 0 and the default, if not specified, is 5 seconds. 2125 2126If the number of data bytes (C<bytes>) is given, that many data bytes 2127are included in the ping packet sent to the remote host. The number of 2128data bytes is ignored if the protocol is "tcp". The minimum (and 2129default) number of data bytes is 1 if the protocol is "udp" and 0 2130otherwise. The maximum number of data bytes that can be specified is 213165535, but staying below the MTU (1472 bytes for ICMP) is recommended. 2132Many small devices cannot deal with fragmented ICMP packets. 2133 2134If C<device> is given, this device is used to bind the source endpoint 2135before sending the ping packet. I believe this only works with 2136superuser privileges and with udp and icmp protocols at this time. 2137 2138If <tos> is given, this ToS is configured into the socket. 2139 2140For icmp, C<ttl> can be specified to set the TTL of the outgoing packet. 2141 2142Valid C<family> values for IPv4: 2143 2144 4, v4, ip4, ipv4, AF_INET (constant) 2145 2146Valid C<family> values for IPv6: 2147 2148 6, v6, ip6, ipv6, AF_INET6 (constant) 2149 2150The C<host> argument implicitly specifies the family if the family 2151argument is not given. 2152 2153The C<port> argument is only valid for a udp, tcp or stream ping, and will not 2154do what you think it does. ping returns true when we get a "Connection refused"! 2155The default is the echo port. 2156 2157The C<bind> argument specifies the local_addr to bind to. 2158By specifying a bind argument you don't need the bind method. 2159 2160The C<gateway> argument is only valid for IPv6, and requires a IPv6 2161address. 2162 2163The C<retrans> argument the exponential backoff rate, default 1.2. 2164It matches the $def_factor global. 2165 2166The C<dontfrag> argument sets the IP_DONTFRAG bit, but note that 2167IP_DONTFRAG is not yet defined by Socket, and not available on many 2168systems. Then it is ignored. On linux it also sets IP_MTU_DISCOVER to 2169IP_PMTUDISC_DO but need we don't chunk oversized packets. You need to 2170set $data_size manually. 2171 2172=item $p->ping($host [, $timeout [, $family]]); 2173X<ping> 2174 2175Ping the remote host and wait for a response. $host can be either the 2176hostname or the IP number of the remote host. The optional timeout 2177must be greater than 0 seconds and defaults to whatever was specified 2178when the ping object was created. Returns a success flag. If the 2179hostname cannot be found or there is a problem with the IP number, the 2180success flag returned will be undef. Otherwise, the success flag will 2181be 1 if the host is reachable and 0 if it is not. For most practical 2182purposes, undef and 0 and can be treated as the same case. In array 2183context, the elapsed time as well as the string form of the ip the 2184host resolved to are also returned. The elapsed time value will 2185be a float, as returned by the Time::HiRes::time() function, if hires() 2186has been previously called, otherwise it is returned as an integer. 2187 2188=item $p->source_verify( { 0 | 1 } ); 2189X<source_verify> 2190 2191Allows source endpoint verification to be enabled or disabled. 2192This is useful for those remote destinations with multiples 2193interfaces where the response may not originate from the same 2194endpoint that the original destination endpoint was sent to. 2195This only affects udp and icmp protocol pings. 2196 2197This is enabled by default. 2198 2199=item $p->service_check( { 0 | 1 } ); 2200X<service_check> 2201 2202Set whether or not the connect behavior should enforce 2203remote service availability as well as reachability. Normally, 2204if the remote server reported ECONNREFUSED, it must have been 2205reachable because of the status packet that it reported. 2206With this option enabled, the full three-way tcp handshake 2207must have been established successfully before it will 2208claim it is reachable. NOTE: It still does nothing more 2209than connect and disconnect. It does not speak any protocol 2210(i.e., HTTP or FTP) to ensure the remote server is sane in 2211any way. The remote server CPU could be grinding to a halt 2212and unresponsive to any clients connecting, but if the kernel 2213throws the ACK packet, it is considered alive anyway. To 2214really determine if the server is responding well would be 2215application specific and is beyond the scope of Net::Ping. 2216For udp protocol, enabling this option demands that the 2217remote server replies with the same udp data that it was sent 2218as defined by the udp echo service. 2219 2220This affects the "udp", "tcp", and "syn" protocols. 2221 2222This is disabled by default. 2223 2224=item $p->tcp_service_check( { 0 | 1 } ); 2225X<tcp_service_check> 2226 2227Deprecated method, but does the same as service_check() method. 2228 2229=item $p->hires( { 0 | 1 } ); 2230X<hires> 2231 2232With 1 causes this module to use Time::HiRes module, allowing milliseconds 2233to be returned by subsequent calls to ping(). 2234 2235=item $p->time 2236X<time> 2237 2238The current time, hires or not. 2239 2240=item $p->socket_blocking_mode( $fh, $mode ); 2241X<socket_blocking_mode> 2242 2243Sets or clears the O_NONBLOCK flag on a file handle. 2244 2245=item $p->IPV6_USE_MIN_MTU 2246X<IPV6_USE_MIN_MTU> 2247 2248With argument sets the option. 2249Without returns the option value. 2250 2251=item $p->IPV6_RECVPATHMTU 2252X<IPV6_RECVPATHMTU> 2253 2254Notify an according IPv6 MTU. 2255 2256With argument sets the option. 2257Without returns the option value. 2258 2259=item $p->IPV6_HOPLIMIT 2260X<IPV6_HOPLIMIT> 2261 2262With argument sets the option. 2263Without returns the option value. 2264 2265=item $p->IPV6_REACHCONF I<NYI> 2266X<IPV6_REACHCONF> 2267 2268Sets ipv6 reachability 2269IPV6_REACHCONF was removed in RFC3542. ping6 -R supports it. 2270IPV6_REACHCONF requires root/admin permissions. 2271 2272With argument sets the option. 2273Without returns the option value. 2274 2275Not yet implemented. 2276 2277=item $p->bind($local_addr); 2278X<bind> 2279 2280Sets the source address from which pings will be sent. This must be 2281the address of one of the interfaces on the local host. $local_addr 2282may be specified as a hostname or as a text IP address such as 2283"192.168.1.1". 2284 2285If the protocol is set to "tcp", this method may be called any 2286number of times, and each call to the ping() method (below) will use 2287the most recent $local_addr. If the protocol is "icmp" or "udp", 2288then bind() must be called at most once per object, and (if it is 2289called at all) must be called before the first call to ping() for that 2290object. 2291 2292The bind() call can be omitted when specifying the C<bind> option to 2293new(). 2294 2295=item $p->message_type([$ping_type]); 2296X<message_type> 2297 2298When you are using the "icmp" protocol, this call permit to change the 2299message type to 'echo' or 'timestamp' (only for IPv4, see RFC 792). 2300 2301Without argument, it returns the currently used icmp protocol message type. 2302By default, it returns 'echo'. 2303 2304=item $p->open($host); 2305X<open> 2306 2307When you are using the "stream" protocol, this call pre-opens the 2308tcp socket. It's only necessary to do this if you want to 2309provide a different timeout when creating the connection, or 2310remove the overhead of establishing the connection from the 2311first ping. If you don't call C<open()>, the connection is 2312automatically opened the first time C<ping()> is called. 2313This call simply does nothing if you are using any protocol other 2314than stream. 2315 2316The $host argument can be omitted when specifying the C<host> option to 2317new(). 2318 2319=item $p->ack( [ $host ] ); 2320X<ack> 2321 2322When using the "syn" protocol, use this method to determine 2323the reachability of the remote host. This method is meant 2324to be called up to as many times as ping() was called. Each 2325call returns the host (as passed to ping()) that came back 2326with the TCP ACK. The order in which the hosts are returned 2327may not necessarily be the same order in which they were 2328SYN queued using the ping() method. If the timeout is 2329reached before the TCP ACK is received, or if the remote 2330host is not listening on the port attempted, then the TCP 2331connection will not be established and ack() will return 2332undef. In list context, the host, the ack time, the dotted ip 2333string, and the port number will be returned instead of just the host. 2334If the optional C<$host> argument is specified, the return 2335value will be pertaining to that host only. 2336This call simply does nothing if you are using any protocol 2337other than "syn". 2338 2339When L</new> had a host option, this host will be used. 2340Without C<$host> argument, all hosts are scanned. 2341 2342=item $p->nack( $failed_ack_host ); 2343X<nack> 2344 2345The reason that C<host $failed_ack_host> did not receive a 2346valid ACK. Useful to find out why when C<ack($fail_ack_host)> 2347returns a false value. 2348 2349=item $p->ack_unfork($host) 2350X<ack_unfork> 2351 2352The variant called by L</ack> with the "syn" protocol and C<$syn_forking> 2353enabled. 2354 2355=item $p->ping_icmp([$host, $timeout, $family]) 2356X<ping_icmp> 2357 2358The L</ping> method used with the icmp protocol. 2359 2360=item $p->ping_icmpv6([$host, $timeout, $family]) I<NYI> 2361X<ping_icmpv6> 2362 2363The L</ping> method used with the icmpv6 protocol. 2364 2365=item $p->ping_stream([$host, $timeout, $family]) 2366X<ping_stream> 2367 2368The L</ping> method used with the stream protocol. 2369 2370Perform a stream ping. If the tcp connection isn't 2371already open, it opens it. It then sends some data and waits for 2372a reply. It leaves the stream open on exit. 2373 2374=item $p->ping_syn([$host, $ip, $start_time, $stop_time]) 2375X<ping_syn> 2376 2377The L</ping> method used with the syn protocol. 2378Sends a TCP SYN packet to host specified. 2379 2380=item $p->ping_syn_fork([$host, $timeout, $family]) 2381X<ping_syn_fork> 2382 2383The L</ping> method used with the forking syn protocol. 2384 2385=item $p->ping_tcp([$host, $timeout, $family]) 2386X<ping_tcp> 2387 2388The L</ping> method used with the tcp protocol. 2389 2390=item $p->ping_udp([$host, $timeout, $family]) 2391X<ping_udp> 2392 2393The L</ping> method used with the udp protocol. 2394 2395Perform a udp echo ping. Construct a message of 2396at least the one-byte sequence number and any additional data bytes. 2397Send the message out and wait for a message to come back. If we 2398get a message, make sure all of its parts match. If they do, we are 2399done. Otherwise go back and wait for the message until we run out 2400of time. Return the result of our efforts. 2401 2402=item $p->ping_external([$host, $timeout, $family]) 2403X<ping_external> 2404 2405The L</ping> method used with the external protocol. 2406Uses L<Net::Ping::External> to do an external ping. 2407 2408=item $p->tcp_connect([$ip, $timeout]) 2409X<tcp_connect> 2410 2411Initiates a TCP connection, for a tcp ping. 2412 2413=item $p->tcp_echo([$ip, $timeout, $pingstring]) 2414X<tcp_echo> 2415 2416Performs a TCP echo. 2417It writes the given string to the socket and then reads it 2418back. It returns 1 on success, 0 on failure. 2419 2420=item $p->close(); 2421X<close> 2422 2423Close the network connection for this ping object. The network 2424connection is also closed by "undef $p". The network connection is 2425automatically closed if the ping object goes out of scope (e.g. $p is 2426local to a subroutine and you leave the subroutine). 2427 2428=item $p->port_number([$port_number]) 2429X<port_number> 2430 2431When called with a port number, the port number used to ping is set to 2432C<$port_number> rather than using the echo port. It also has the effect 2433of calling C<$p-E<gt>service_check(1)> causing a ping to return a successful 2434response only if that specific port is accessible. This function returns 2435the value of the port that L</ping> will connect to. 2436 2437=item $p->mselect 2438X<mselect> 2439 2440A C<select()> wrapper that compensates for platform 2441peculiarities. 2442 2443=item $p->ntop 2444X<ntop> 2445 2446Platform abstraction over C<inet_ntop()> 2447 2448=item $p->checksum($msg) 2449X<checksum> 2450 2451Do a checksum on the message. Basically sum all of 2452the short words and fold the high order bits into the low order bits. 2453 2454=item $p->icmp_result 2455X<icmp_result> 2456 2457Returns a list of addr, type, subcode. 2458 2459=item pingecho($host [, $timeout]); 2460X<pingecho> 2461 2462To provide backward compatibility with the previous version of 2463L<Net::Ping>, a C<pingecho()> subroutine is available with the same 2464functionality as before. C<pingecho()> uses the tcp protocol. The 2465return values and parameters are the same as described for the L</ping> 2466method. This subroutine is obsolete and may be removed in a future 2467version of L<Net::Ping>. 2468 2469=item wakeonlan($mac, [$host, [$port]]) 2470X<wakeonlan> 2471 2472Emit the popular wake-on-lan magic udp packet to wake up a local 2473device. See also L<Net::Wake>, but this has the mac address as 1st arg. 2474C<$host> should be the local gateway. Without it will broadcast. 2475 2476Default host: '255.255.255.255' 2477Default port: 9 2478 2479 perl -MNet::Ping=wakeonlan -e'wakeonlan "e0:69:95:35:68:d2"' 2480 2481=back 2482 2483=head1 NOTES 2484 2485There will be less network overhead (and some efficiency in your 2486program) if you specify either the udp or the icmp protocol. The tcp 2487protocol will generate 2.5 times or more traffic for each ping than 2488either udp or icmp. If many hosts are pinged frequently, you may wish 2489to implement a small wait (e.g. 25ms or more) between each ping to 2490avoid flooding your network with packets. 2491 2492The icmp and icmpv6 protocols requires that the program be run as root 2493or that it be setuid to root. The other protocols do not require 2494special privileges, but not all network devices implement tcp or udp 2495echo. 2496 2497Local hosts should normally respond to pings within milliseconds. 2498However, on a very congested network it may take up to 3 seconds or 2499longer to receive an echo packet from the remote host. If the timeout 2500is set too low under these conditions, it will appear that the remote 2501host is not reachable (which is almost the truth). 2502 2503Reachability doesn't necessarily mean that the remote host is actually 2504functioning beyond its ability to echo packets. tcp is slightly better 2505at indicating the health of a system than icmp because it uses more 2506of the networking stack to respond. 2507 2508Because of a lack of anything better, this module uses its own 2509routines to pack and unpack ICMP packets. It would be better for a 2510separate module to be written which understands all of the different 2511kinds of ICMP packets. 2512 2513=head1 INSTALL 2514 2515The latest source tree is available via git: 2516 2517 git clone https://github.com/rurban/Net-Ping.git 2518 cd Net-Ping 2519 2520The tarball can be created as follows: 2521 2522 perl Makefile.PL ; make ; make dist 2523 2524The latest Net::Ping releases are included in cperl and perl5. 2525 2526=head1 BUGS 2527 2528For a list of known issues, visit: 2529 2530L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-Ping> 2531and 2532L<https://github.com/rurban/Net-Ping/issues> 2533 2534To report a new bug, visit: 2535 2536L<https://github.com/rurban/Net-Ping/issues> 2537 2538=head1 AUTHORS 2539 2540 Current maintainers: 2541 perl11 (for cperl, with IPv6 support and more) 2542 p5p (for perl5) 2543 2544 Previous maintainers: 2545 bbb@cpan.org (Rob Brown) 2546 Steve Peters 2547 2548 External protocol: 2549 colinm@cpan.org (Colin McMillen) 2550 2551 Stream protocol: 2552 bronson@trestle.com (Scott Bronson) 2553 2554 Wake-on-lan: 2555 1999-2003 Clinton Wong 2556 2557 Original pingecho(): 2558 karrer@bernina.ethz.ch (Andreas Karrer) 2559 pmarquess@bfsec.bt.co.uk (Paul Marquess) 2560 2561 Original Net::Ping author: 2562 mose@ns.ccsn.edu (Russell Mosemann) 2563 2564=head1 COPYRIGHT 2565 2566Copyright (c) 2017-2018, Reini Urban. All rights reserved. 2567 2568Copyright (c) 2016, cPanel Inc. All rights reserved. 2569 2570Copyright (c) 2012, Steve Peters. All rights reserved. 2571 2572Copyright (c) 2002-2003, Rob Brown. All rights reserved. 2573 2574Copyright (c) 2001, Colin McMillen. All rights reserved. 2575 2576This program is free software; you may redistribute it and/or 2577modify it under the same terms as Perl itself. 2578 2579=cut 2580