Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

559 lines
21 KiB

  1. package Net::Ping;
  2. # Author: [email protected] (Russell Mosemann)
  3. #
  4. # Authors of the original pingecho():
  5. # [email protected] (Andreas Karrer)
  6. # [email protected] (Paul Marquess)
  7. #
  8. # Copyright (c) 1996 Russell Mosemann. All rights reserved. This
  9. # program is free software; you may redistribute it and/or modify it
  10. # under the same terms as Perl itself.
  11. use 5.005_64;
  12. require Exporter;
  13. use strict;
  14. our(@ISA, @EXPORT, $VERSION, $def_timeout, $def_proto, $max_datasize);
  15. use FileHandle;
  16. use Socket qw( SOCK_DGRAM SOCK_STREAM SOCK_RAW PF_INET
  17. inet_aton sockaddr_in );
  18. use Carp;
  19. @ISA = qw(Exporter);
  20. @EXPORT = qw(pingecho);
  21. $VERSION = 2.02;
  22. # Constants
  23. $def_timeout = 5; # Default timeout to wait for a reply
  24. $def_proto = "udp"; # Default protocol to use for pinging
  25. $max_datasize = 1024; # Maximum data bytes in a packet
  26. # Description: The pingecho() subroutine is provided for backward
  27. # compatibility with the original Net::Ping. It accepts a host
  28. # name/IP and an optional timeout in seconds. Create a tcp ping
  29. # object and try pinging the host. The result of the ping is returned.
  30. sub pingecho
  31. {
  32. my ($host, # Name or IP number of host to ping
  33. $timeout # Optional timeout in seconds
  34. ) = @_;
  35. my ($p); # A ping object
  36. $p = Net::Ping->new("tcp", $timeout);
  37. $p->ping($host); # Going out of scope closes the connection
  38. }
  39. # Description: The new() method creates a new ping object. Optional
  40. # parameters may be specified for the protocol to use, the timeout in
  41. # seconds and the size in bytes of additional data which should be
  42. # included in the packet.
  43. # After the optional parameters are checked, the data is constructed
  44. # and a socket is opened if appropriate. The object is returned.
  45. sub new
  46. {
  47. my ($this,
  48. $proto, # Optional protocol to use for pinging
  49. $timeout, # Optional timeout in seconds
  50. $data_size # Optional additional bytes of data
  51. ) = @_;
  52. my $class = ref($this) || $this;
  53. my $self = {};
  54. my ($cnt, # Count through data bytes
  55. $min_datasize # Minimum data bytes required
  56. );
  57. bless($self, $class);
  58. $proto = $def_proto unless $proto; # Determine the protocol
  59. croak("Protocol for ping must be \"tcp\", \"udp\" or \"icmp\"")
  60. unless $proto =~ m/^(tcp|udp|icmp)$/;
  61. $self->{"proto"} = $proto;
  62. $timeout = $def_timeout unless $timeout; # Determine the timeout
  63. croak("Default timeout for ping must be greater than 0 seconds")
  64. if $timeout <= 0;
  65. $self->{"timeout"} = $timeout;
  66. $min_datasize = ($proto eq "udp") ? 1 : 0; # Determine data size
  67. $data_size = $min_datasize unless defined($data_size) && $proto ne "tcp";
  68. croak("Data for ping must be from $min_datasize to $max_datasize bytes")
  69. if ($data_size < $min_datasize) || ($data_size > $max_datasize);
  70. $data_size-- if $self->{"proto"} eq "udp"; # We provide the first byte
  71. $self->{"data_size"} = $data_size;
  72. $self->{"data"} = ""; # Construct data bytes
  73. for ($cnt = 0; $cnt < $self->{"data_size"}; $cnt++)
  74. {
  75. $self->{"data"} .= chr($cnt % 256);
  76. }
  77. $self->{"seq"} = 0; # For counting packets
  78. if ($self->{"proto"} eq "udp") # Open a socket
  79. {
  80. $self->{"proto_num"} = (getprotobyname('udp'))[2] ||
  81. croak("Can't udp protocol by name");
  82. $self->{"port_num"} = (getservbyname('echo', 'udp'))[2] ||
  83. croak("Can't get udp echo port by name");
  84. $self->{"fh"} = FileHandle->new();
  85. socket($self->{"fh"}, &PF_INET(), &SOCK_DGRAM(),
  86. $self->{"proto_num"}) ||
  87. croak("udp socket error - $!");
  88. }
  89. elsif ($self->{"proto"} eq "icmp")
  90. {
  91. croak("icmp ping requires root privilege") if ($> and $^O ne 'VMS');
  92. $self->{"proto_num"} = (getprotobyname('icmp'))[2] ||
  93. croak("Can't get icmp protocol by name");
  94. $self->{"pid"} = $$ & 0xffff; # Save lower 16 bits of pid
  95. $self->{"fh"} = FileHandle->new();
  96. socket($self->{"fh"}, &PF_INET(), &SOCK_RAW(), $self->{"proto_num"}) ||
  97. croak("icmp socket error - $!");
  98. }
  99. elsif ($self->{"proto"} eq "tcp") # Just a file handle for now
  100. {
  101. $self->{"proto_num"} = (getprotobyname('tcp'))[2] ||
  102. croak("Can't get tcp protocol by name");
  103. $self->{"port_num"} = (getservbyname('echo', 'tcp'))[2] ||
  104. croak("Can't get tcp echo port by name");
  105. $self->{"fh"} = FileHandle->new();
  106. }
  107. return($self);
  108. }
  109. # Description: Ping a host name or IP number with an optional timeout.
  110. # First lookup the host, and return undef if it is not found. Otherwise
  111. # perform the specific ping method based on the protocol. Return the
  112. # result of the ping.
  113. sub ping
  114. {
  115. my ($self,
  116. $host, # Name or IP number of host to ping
  117. $timeout # Seconds after which ping times out
  118. ) = @_;
  119. my ($ip, # Packed IP number of $host
  120. $ret # The return value
  121. );
  122. croak("Usage: \$p->ping(\$host [, \$timeout])") unless @_ == 2 || @_ == 3;
  123. $timeout = $self->{"timeout"} unless $timeout;
  124. croak("Timeout must be greater than 0 seconds") if $timeout <= 0;
  125. $ip = inet_aton($host);
  126. return(undef) unless defined($ip); # Does host exist?
  127. if ($self->{"proto"} eq "udp")
  128. {
  129. $ret = $self->ping_udp($ip, $timeout);
  130. }
  131. elsif ($self->{"proto"} eq "icmp")
  132. {
  133. $ret = $self->ping_icmp($ip, $timeout);
  134. }
  135. elsif ($self->{"proto"} eq "tcp")
  136. {
  137. $ret = $self->ping_tcp($ip, $timeout);
  138. }
  139. else
  140. {
  141. croak("Unknown protocol \"$self->{proto}\" in ping()");
  142. }
  143. return($ret);
  144. }
  145. sub ping_icmp
  146. {
  147. my ($self,
  148. $ip, # Packed IP number of the host
  149. $timeout # Seconds after which ping times out
  150. ) = @_;
  151. my $ICMP_ECHOREPLY = 0; # ICMP packet types
  152. my $ICMP_ECHO = 8;
  153. my $icmp_struct = "C2 S3 A"; # Structure of a minimal ICMP packet
  154. my $subcode = 0; # No ICMP subcode for ECHO and ECHOREPLY
  155. my $flags = 0; # No special flags when opening a socket
  156. my $port = 0; # No port with ICMP
  157. my ($saddr, # sockaddr_in with port and ip
  158. $checksum, # Checksum of ICMP packet
  159. $msg, # ICMP packet to send
  160. $len_msg, # Length of $msg
  161. $rbits, # Read bits, filehandles for reading
  162. $nfound, # Number of ready filehandles found
  163. $finish_time, # Time ping should be finished
  164. $done, # set to 1 when we are done
  165. $ret, # Return value
  166. $recv_msg, # Received message including IP header
  167. $from_saddr, # sockaddr_in of sender
  168. $from_port, # Port packet was sent from
  169. $from_ip, # Packed IP of sender
  170. $from_type, # ICMP type
  171. $from_subcode, # ICMP subcode
  172. $from_chk, # ICMP packet checksum
  173. $from_pid, # ICMP packet id
  174. $from_seq, # ICMP packet sequence
  175. $from_msg # ICMP message
  176. );
  177. $self->{"seq"} = ($self->{"seq"} + 1) % 65536; # Increment sequence
  178. $checksum = 0; # No checksum for starters
  179. $msg = pack($icmp_struct . $self->{"data_size"}, $ICMP_ECHO, $subcode,
  180. $checksum, $self->{"pid"}, $self->{"seq"}, $self->{"data"});
  181. $checksum = Net::Ping->checksum($msg);
  182. $msg = pack($icmp_struct . $self->{"data_size"}, $ICMP_ECHO, $subcode,
  183. $checksum, $self->{"pid"}, $self->{"seq"}, $self->{"data"});
  184. $len_msg = length($msg);
  185. $saddr = sockaddr_in($port, $ip);
  186. send($self->{"fh"}, $msg, $flags, $saddr); # Send the message
  187. $rbits = "";
  188. vec($rbits, $self->{"fh"}->fileno(), 1) = 1;
  189. $ret = 0;
  190. $done = 0;
  191. $finish_time = time() + $timeout; # Must be done by this time
  192. while (!$done && $timeout > 0) # Keep trying if we have time
  193. {
  194. $nfound = select($rbits, undef, undef, $timeout); # Wait for packet
  195. $timeout = $finish_time - time(); # Get remaining time
  196. if (!defined($nfound)) # Hmm, a strange error
  197. {
  198. $ret = undef;
  199. $done = 1;
  200. }
  201. elsif ($nfound) # Got a packet from somewhere
  202. {
  203. $recv_msg = "";
  204. $from_saddr = recv($self->{"fh"}, $recv_msg, 1500, $flags);
  205. ($from_port, $from_ip) = sockaddr_in($from_saddr);
  206. ($from_type, $from_subcode, $from_chk,
  207. $from_pid, $from_seq, $from_msg) =
  208. unpack($icmp_struct . $self->{"data_size"},
  209. substr($recv_msg, length($recv_msg) - $len_msg,
  210. $len_msg));
  211. if (($from_type == $ICMP_ECHOREPLY) &&
  212. ($from_ip eq $ip) &&
  213. ($from_pid == $self->{"pid"}) && # Does the packet check out?
  214. ($from_seq == $self->{"seq"}))
  215. {
  216. $ret = 1; # It's a winner
  217. $done = 1;
  218. }
  219. }
  220. else # Oops, timed out
  221. {
  222. $done = 1;
  223. }
  224. }
  225. return($ret)
  226. }
  227. # Description: Do a checksum on the message. Basically sum all of
  228. # the short words and fold the high order bits into the low order bits.
  229. sub checksum
  230. {
  231. my ($class,
  232. $msg # The message to checksum
  233. ) = @_;
  234. my ($len_msg, # Length of the message
  235. $num_short, # The number of short words in the message
  236. $short, # One short word
  237. $chk # The checksum
  238. );
  239. $len_msg = length($msg);
  240. $num_short = int($len_msg / 2);
  241. $chk = 0;
  242. foreach $short (unpack("S$num_short", $msg))
  243. {
  244. $chk += $short;
  245. } # Add the odd byte in
  246. $chk += (unpack("C", substr($msg, $len_msg - 1, 1)) << 8) if $len_msg % 2;
  247. $chk = ($chk >> 16) + ($chk & 0xffff); # Fold high into low
  248. return(~(($chk >> 16) + $chk) & 0xffff); # Again and complement
  249. }
  250. # Description: Perform a tcp echo ping. Since a tcp connection is
  251. # host specific, we have to open and close each connection here. We
  252. # can't just leave a socket open. Because of the robust nature of
  253. # tcp, it will take a while before it gives up trying to establish a
  254. # connection. Therefore, we have to set the alarm to break out of the
  255. # connection sooner if the timeout expires. No data bytes are actually
  256. # sent since the successful establishment of a connection is proof
  257. # enough of the reachability of the remote host. Also, tcp is
  258. # expensive and doesn't need our help to add to the overhead.
  259. sub ping_tcp
  260. {
  261. my ($self,
  262. $ip, # Packed IP number of the host
  263. $timeout # Seconds after which ping times out
  264. ) = @_;
  265. my ($saddr, # sockaddr_in with port and ip
  266. $ret # The return value
  267. );
  268. socket($self->{"fh"}, &PF_INET(), &SOCK_STREAM(), $self->{"proto_num"}) ||
  269. croak("tcp socket error - $!");
  270. $saddr = sockaddr_in($self->{"port_num"}, $ip);
  271. $SIG{'ALRM'} = sub { die };
  272. alarm($timeout); # Interrupt connect() if we have to
  273. $ret = 0; # Default to unreachable
  274. eval <<'EOM' ;
  275. return unless connect($self->{"fh"}, $saddr);
  276. $ret = 1;
  277. EOM
  278. alarm(0);
  279. $self->{"fh"}->close();
  280. return($ret);
  281. }
  282. # Description: Perform a udp echo ping. Construct a message of
  283. # at least the one-byte sequence number and any additional data bytes.
  284. # Send the message out and wait for a message to come back. If we
  285. # get a message, make sure all of its parts match. If they do, we are
  286. # done. Otherwise go back and wait for the message until we run out
  287. # of time. Return the result of our efforts.
  288. sub ping_udp
  289. {
  290. my ($self,
  291. $ip, # Packed IP number of the host
  292. $timeout # Seconds after which ping times out
  293. ) = @_;
  294. my $flags = 0; # Nothing special on open
  295. my ($saddr, # sockaddr_in with port and ip
  296. $ret, # The return value
  297. $msg, # Message to be echoed
  298. $finish_time, # Time ping should be finished
  299. $done, # Set to 1 when we are done pinging
  300. $rbits, # Read bits, filehandles for reading
  301. $nfound, # Number of ready filehandles found
  302. $from_saddr, # sockaddr_in of sender
  303. $from_msg, # Characters echoed by $host
  304. $from_port, # Port message was echoed from
  305. $from_ip # Packed IP number of sender
  306. );
  307. $saddr = sockaddr_in($self->{"port_num"}, $ip);
  308. $self->{"seq"} = ($self->{"seq"} + 1) % 256; # Increment sequence
  309. $msg = chr($self->{"seq"}) . $self->{"data"}; # Add data if any
  310. send($self->{"fh"}, $msg, $flags, $saddr); # Send it
  311. $rbits = "";
  312. vec($rbits, $self->{"fh"}->fileno(), 1) = 1;
  313. $ret = 0; # Default to unreachable
  314. $done = 0;
  315. $finish_time = time() + $timeout; # Ping needs to be done by then
  316. while (!$done && $timeout > 0)
  317. {
  318. $nfound = select($rbits, undef, undef, $timeout); # Wait for response
  319. $timeout = $finish_time - time(); # Get remaining time
  320. if (!defined($nfound)) # Hmm, a strange error
  321. {
  322. $ret = undef;
  323. $done = 1;
  324. }
  325. elsif ($nfound) # A packet is waiting
  326. {
  327. $from_msg = "";
  328. $from_saddr = recv($self->{"fh"}, $from_msg, 1500, $flags)
  329. or last; # For example an unreachable host will make recv() fail.
  330. ($from_port, $from_ip) = sockaddr_in($from_saddr);
  331. if (($from_ip eq $ip) && # Does the packet check out?
  332. ($from_port == $self->{"port_num"}) &&
  333. ($from_msg eq $msg))
  334. {
  335. $ret = 1; # It's a winner
  336. $done = 1;
  337. }
  338. }
  339. else # Oops, timed out
  340. {
  341. $done = 1;
  342. }
  343. }
  344. return($ret);
  345. }
  346. # Description: Close the connection unless we are using the tcp
  347. # protocol, since it will already be closed.
  348. sub close
  349. {
  350. my ($self) = @_;
  351. $self->{"fh"}->close() unless $self->{"proto"} eq "tcp";
  352. }
  353. 1;
  354. __END__
  355. =head1 NAME
  356. Net::Ping - check a remote host for reachability
  357. =head1 SYNOPSIS
  358. use Net::Ping;
  359. $p = Net::Ping->new();
  360. print "$host is alive.\n" if $p->ping($host);
  361. $p->close();
  362. $p = Net::Ping->new("icmp");
  363. foreach $host (@host_array)
  364. {
  365. print "$host is ";
  366. print "NOT " unless $p->ping($host, 2);
  367. print "reachable.\n";
  368. sleep(1);
  369. }
  370. $p->close();
  371. $p = Net::Ping->new("tcp", 2);
  372. while ($stop_time > time())
  373. {
  374. print "$host not reachable ", scalar(localtime()), "\n"
  375. unless $p->ping($host);
  376. sleep(300);
  377. }
  378. undef($p);
  379. # For backward compatibility
  380. print "$host is alive.\n" if pingecho($host);
  381. =head1 DESCRIPTION
  382. This module contains methods to test the reachability of remote
  383. hosts on a network. A ping object is first created with optional
  384. parameters, a variable number of hosts may be pinged multiple
  385. times and then the connection is closed.
  386. You may choose one of three different protocols to use for the
  387. ping. The "udp" protocol is the default. Note that a live remote host
  388. may still fail to be pingable by one or more of these protocols. For
  389. example, www.microsoft.com is generally alive but not pingable.
  390. With the "tcp" protocol the ping() method attempts to establish a
  391. connection to the remote host's echo port. If the connection is
  392. successfully established, the remote host is considered reachable. No
  393. data is actually echoed. This protocol does not require any special
  394. privileges but has higher overhead than the other two protocols.
  395. Specifying the "udp" protocol causes the ping() method to send a udp
  396. packet to the remote host's echo port. If the echoed packet is
  397. received from the remote host and the received packet contains the
  398. same data as the packet that was sent, the remote host is considered
  399. reachable. This protocol does not require any special privileges.
  400. It should be borne in mind that, for both tcp and udp ping, a host
  401. will be reported as unreachable if it is not running the
  402. appropriate echo service. For Unix-like systems see L<inetd(8)> for
  403. more information.
  404. If the "icmp" protocol is specified, the ping() method sends an icmp
  405. echo message to the remote host, which is what the UNIX ping program
  406. does. If the echoed message is received from the remote host and
  407. the echoed information is correct, the remote host is considered
  408. reachable. Specifying the "icmp" protocol requires that the program
  409. be run as root or that the program be setuid to root.
  410. =head2 Functions
  411. =over 4
  412. =item Net::Ping->new([$proto [, $def_timeout [, $bytes]]]);
  413. Create a new ping object. All of the parameters are optional. $proto
  414. specifies the protocol to use when doing a ping. The current choices
  415. are "tcp", "udp" or "icmp". The default is "udp".
  416. If a default timeout ($def_timeout) in seconds is provided, it is used
  417. when a timeout is not given to the ping() method (below). The timeout
  418. must be greater than 0 and the default, if not specified, is 5 seconds.
  419. If the number of data bytes ($bytes) is given, that many data bytes
  420. are included in the ping packet sent to the remote host. The number of
  421. data bytes is ignored if the protocol is "tcp". The minimum (and
  422. default) number of data bytes is 1 if the protocol is "udp" and 0
  423. otherwise. The maximum number of data bytes that can be specified is
  424. 1024.
  425. =item $p->ping($host [, $timeout]);
  426. Ping the remote host and wait for a response. $host can be either the
  427. hostname or the IP number of the remote host. The optional timeout
  428. must be greater than 0 seconds and defaults to whatever was specified
  429. when the ping object was created. If the hostname cannot be found or
  430. there is a problem with the IP number, undef is returned. Otherwise,
  431. 1 is returned if the host is reachable and 0 if it is not. For all
  432. practical purposes, undef and 0 and can be treated as the same case.
  433. =item $p->close();
  434. Close the network connection for this ping object. The network
  435. connection is also closed by "undef $p". The network connection is
  436. automatically closed if the ping object goes out of scope (e.g. $p is
  437. local to a subroutine and you leave the subroutine).
  438. =item pingecho($host [, $timeout]);
  439. To provide backward compatibility with the previous version of
  440. Net::Ping, a pingecho() subroutine is available with the same
  441. functionality as before. pingecho() uses the tcp protocol. The
  442. return values and parameters are the same as described for the ping()
  443. method. This subroutine is obsolete and may be removed in a future
  444. version of Net::Ping.
  445. =back
  446. =head1 WARNING
  447. pingecho() or a ping object with the tcp protocol use alarm() to
  448. implement the timeout. So, don't use alarm() in your program while
  449. you are using pingecho() or a ping object with the tcp protocol. The
  450. udp and icmp protocols do not use alarm() to implement the timeout.
  451. =head1 NOTES
  452. There will be less network overhead (and some efficiency in your
  453. program) if you specify either the udp or the icmp protocol. The tcp
  454. protocol will generate 2.5 times or more traffic for each ping than
  455. either udp or icmp. If many hosts are pinged frequently, you may wish
  456. to implement a small wait (e.g. 25ms or more) between each ping to
  457. avoid flooding your network with packets.
  458. The icmp protocol requires that the program be run as root or that it
  459. be setuid to root. The tcp and udp protocols do not require special
  460. privileges, but not all network devices implement the echo protocol
  461. for tcp or udp.
  462. Local hosts should normally respond to pings within milliseconds.
  463. However, on a very congested network it may take up to 3 seconds or
  464. longer to receive an echo packet from the remote host. If the timeout
  465. is set too low under these conditions, it will appear that the remote
  466. host is not reachable (which is almost the truth).
  467. Reachability doesn't necessarily mean that the remote host is actually
  468. functioning beyond its ability to echo packets.
  469. Because of a lack of anything better, this module uses its own
  470. routines to pack and unpack ICMP packets. It would be better for a
  471. separate module to be written which understands all of the different
  472. kinds of ICMP packets.
  473. =cut