3 # Contains code ripped from Net::Ping by Russell Mosemann
9 local $wait = defined($_[0]->{'wait'}) ? $_[0]->{'wait'} : 5;
10 local $ip = &to_ipaddress($_[0]->{'host'}) ||
11 &to_ip6address($_[0]->{'host'});
12 return { 'up' => 0 } if (!$ip);
13 local $ipv6 = &to_ip6address($_[0]->{'host'}) &&
14 !&to_ipaddress($_[0]->{'host'});
15 if ($config{'pinger'} || $ipv6) {
16 # Call a ping command if configured, or if using IPv6 since the built-
17 # in code doesn't support it yet
19 local $auto_pinger = $config{'pinger'} eq "linux" || !$config{'pinger'};
20 if ($auto_pinger && $gconfig{'os_type'} =~ /-linux$/) {
22 $cmd = ($ipv6 ? "ping6" : "ping")." -c 1 -w $wait";
24 elsif ($auto_pinger && $gconfig{'os_type'} eq 'freebsd') {
26 $cmd = ($ipv6 ? "ping6" : "ping")." -c 1 -W ".($wait * 1000);
28 elsif ($auto_pinger) {
29 # Don't know command for this OS
30 return { 'up' => - 1 };
33 $cmd = $config{'pinger'};
35 local $rv = system("$cmd ".quotemeta($_[0]->{'host'}).
36 " >/dev/null 2>&1 </dev/null");
37 return { 'up' => $rv ? 0 : 1 };
41 local $rv = &ping_icmp(inet_aton($ip), $wait);
42 return { 'up' => $rv ? 1 : 0 };
48 print &ui_table_row($text{'ping_host'},
49 &ui_textbox("host", $_[0]->{'host'}, 50), 3);
51 print &ui_table_row($text{'ping_wait'},
52 &ui_textbox("wait", defined($_[0]->{'wait'}) ? $_[0]->{'wait'} : 5, 6).
53 " ".$text{'oldfile_secs'});
58 #$config{'ping_cmd'} || &error($text{'ping_econfig'});
59 &to_ipaddress($in{'host'}) || &to_ip6address($in{'host'}) ||
60 &error($text{'ping_ehost'});
61 $in{'wait'} =~ /^(\d*\.)?\d+$/ || &error($text{'ping_ewait'});
62 $_[0]->{'host'} = $in{'host'};
63 $_[0]->{'wait'} = $in{'wait'};
68 my ($ip, # Packed IP number of the host
69 $timeout # Seconds after which ping times out
72 my $ICMP_ECHOREPLY = 0; # ICMP packet types
74 my $icmp_struct = "C2 S3 A"; # Structure of a minimal ICMP packet
75 my $subcode = 0; # No ICMP subcode for ECHO and ECHOREPLY
76 my $flags = 0; # No special flags when opening a socket
77 my $port = 0; # No port with ICMP
79 my ($saddr, # sockaddr_in with port and ip
80 $checksum, # Checksum of ICMP packet
81 $msg, # ICMP packet to send
82 $len_msg, # Length of $msg
83 $rbits, # Read bits, filehandles for reading
84 $nfound, # Number of ready filehandles found
85 $finish_time, # Time ping should be finished
86 $done, # set to 1 when we are done
88 $recv_msg, # Received message including IP header
89 $from_saddr, # sockaddr_in of sender
90 $from_port, # Port packet was sent from
91 $from_ip, # Packed IP of sender
92 $from_type, # ICMP type
93 $from_subcode, # ICMP subcode
94 $from_chk, # ICMP packet checksum
95 $from_pid, # ICMP packet id
96 $from_seq, # ICMP packet sequence
97 $from_msg, # ICMP message
103 # Construct packet data string
105 for ($cnt = 0; $cnt < $data_size; $cnt++)
107 $data .= chr($cnt % 256);
110 my $proto_num = (getprotobyname('icmp'))[2];
111 socket(PSOCK, PF_INET, SOCK_RAW, $proto_num);
113 $ping_seq = ($ping_seq + 1) % 65536; # Increment sequence
114 $checksum = 0; # No checksum for starters
115 $msg = pack($icmp_struct . $data_size, $ICMP_ECHO, $subcode,
116 $checksum, $$, $ping_seq, $data);
117 $checksum = checksum($msg);
118 $msg = pack($icmp_struct . $data_size, $ICMP_ECHO, $subcode,
119 $checksum, $$, $ping_seq, $data);
120 $len_msg = length($msg);
121 $saddr = pack_sockaddr_in($port, $ip);
122 send(PSOCK, $msg, $flags, $saddr); # Send the message
125 vec($rbits, fileno(PSOCK), 1) = 1;
128 $finish_time = time() + $timeout; # Must be done by this time
129 while (!$done && $timeout > 0) # Keep trying if we have time
131 $nfound = select($rbits, undef, undef, $timeout); # Wait for packet
132 $timeout = $finish_time - time(); # Get remaining time
133 if (!defined($nfound)) # Hmm, a strange error
135 # Probably an interrupted system call, so try again
139 elsif ($nfound) # Got a packet from somewhere
142 $from_saddr = recv(PSOCK, $recv_msg, 1500, $flags);
144 ($from_port, $from_ip) = unpack_sockaddr_in($from_saddr);
145 ($from_type, $from_subcode, $from_chk,
146 $from_pid, $from_seq, $from_msg) =
147 unpack($icmp_struct . $data_size,
148 substr($recv_msg, length($recv_msg) - $len_msg,
150 if (($from_type == $ICMP_ECHOREPLY) &&
152 ($from_pid == $$) && # Does the packet check out?
153 ($from_seq == $ping_seq))
155 $ret = 1; # It's a winner
159 # Packet not actually received
163 else # Oops, timed out
172 # Description: Do a checksum on the message. Basically sum all of
173 # the short words and fold the high order bits into the low order bits.
177 my ($msg # The message to checksum
179 my ($len_msg, # Length of the message
180 $num_short, # The number of short words in the message
181 $short, # One short word
185 $len_msg = length($msg);
186 $num_short = $len_msg / 2;
188 foreach $short (unpack("S$num_short", $msg))
191 } # Add the odd byte in
192 $chk += unpack("C", substr($msg, $len_msg - 1, 1)) if $len_msg % 2;
193 $chk = ($chk >> 16) + ($chk & 0xffff); # Fold high into low
194 return(~(($chk >> 16) + $chk) & 0xffff); # Again and complement