Contents of /alx-src/trunk/alx-web/include/ppping.inc.php
Parent Directory | Revision Log
Revision 2804 -
(show annotations)
(download)
Mon Aug 29 20:22:21 2011 UTC (13 years, 1 month ago) by niro
File size: 9495 byte(s)
Mon Aug 29 20:22:21 2011 UTC (13 years, 1 month ago) by niro
File size: 9495 byte(s)
-merged branch alx-web-0_6_0 into trunk
1 | <?php |
2 | /* ------------------------------------------------------------- |
3 | This file is part of PurplePixie Ping (PPPing) |
4 | |
5 | PPPing is (C) Copyright 2010 PurplePixie Systems |
6 | |
7 | PPPing is free software: you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation, either version 3 of the License, or |
10 | (at your option) any later version. |
11 | |
12 | PPPing is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with PPPing. If not, see www.gnu.org/licenses |
19 | |
20 | For more information see www.purplepixie.org/phpping |
21 | -------------------------------------------------------------- */ |
22 | |
23 | /** |
24 | * PPPing PHP Ping Utility |
25 | * @package PPPing PHP Ping Utility |
26 | * @author David Cutting |
27 | * @version 0.01 |
28 | **/ |
29 | |
30 | /** |
31 | * Main PPPing Class |
32 | * @package PPPing PHP Ping Utility |
33 | **/ |
34 | class PPPing |
35 | { |
36 | /** |
37 | * Time-to-Live for IP Packet (DO NOT USE) |
38 | * |
39 | * -1 Uses system default (usually 64). Please note that this is currently |
40 | * not functional. |
41 | **/ |
42 | var $ttl=-1; |
43 | |
44 | /** |
45 | * Hostname to ping (resolvable host or IP address) |
46 | **/ |
47 | var $hostname=""; |
48 | |
49 | /** |
50 | * Identifier - will fill with random content (16 bits) |
51 | **/ |
52 | var $identity=0; |
53 | |
54 | /** |
55 | * Sequence number in decimal (16 bits) |
56 | **/ |
57 | var $sequence=0; |
58 | |
59 | /** |
60 | * Timeout in seconds - maximum wait for a response before timeout |
61 | **/ |
62 | var $timeout=10; |
63 | |
64 | /** |
65 | * Timer start seconds |
66 | **/ |
67 | var $timer_start_sec=0; |
68 | |
69 | /** |
70 | * Timer start mseconds |
71 | **/ |
72 | var $timer_start_msec=0; |
73 | |
74 | /** |
75 | * Data package for the ping |
76 | **/ |
77 | var $data_package = "PPPing"; |
78 | |
79 | /** |
80 | * Debug - prints output to the screen |
81 | **/ |
82 | var $debug=false; |
83 | |
84 | /** |
85 | * Holds information on last result |
86 | **/ |
87 | var $Last = array(); |
88 | |
89 | /** |
90 | * Clears last data |
91 | **/ |
92 | function clearLast() |
93 | { |
94 | $this->last = array( |
95 | "set" => false, |
96 | "result" => 0, |
97 | "ttl" => 0, |
98 | "hops" => 0, |
99 | "source" => "", |
100 | "destination" => "" ); |
101 | } |
102 | /** |
103 | * Get a padded hex identifier |
104 | **/ |
105 | function getIdentity() |
106 | { |
107 | if ( (is_numeric($this->identity)) && ($this->identity>=0) && ($this->identity<65535) ) |
108 | $id=$this->identity; |
109 | else $id=0; |
110 | |
111 | $id=dechex($id); |
112 | $id=str_pad($id,4,"0",STR_PAD_LEFT); |
113 | $id=pack("H*",$id); |
114 | |
115 | return $id; |
116 | } |
117 | |
118 | /** |
119 | * Get a padded hex sequence |
120 | **/ |
121 | function getSequence() |
122 | { |
123 | if ( (is_numeric($this->sequence)) && ($this->sequence>=0) && ($this->sequence<65535) ) |
124 | $seq=$this->sequence; |
125 | else $seq=0; |
126 | $seq=dechex($seq); |
127 | $seq=str_pad($seq,4,"0",STR_PAD_LEFT); |
128 | $seq=pack("H*",$seq); |
129 | |
130 | return $seq; |
131 | } |
132 | |
133 | /** |
134 | * Returns a hex string of the binary data for debug purposes |
135 | **/ |
136 | function getHex($data) |
137 | { |
138 | $parts=unpack("H*",$data); |
139 | return $parts[1]; |
140 | } |
141 | |
142 | /** |
143 | * Randomise identity and/or sequence within 16 bit parameters |
144 | **/ |
145 | function Randomise($identity=true,$sequence=false) |
146 | { |
147 | mt_srand(microtime()*1000000); |
148 | if ($identity) $this->identity=mt_rand(0,65534); |
149 | if ($sequence) $this->sequence=mt_rand(0,65534); |
150 | } |
151 | |
152 | /** |
153 | * Start timer (reset values) |
154 | **/ |
155 | function startTimer() |
156 | { |
157 | $now=microtime(); |
158 | $timearray=explode(" ",$now); |
159 | $this->timer_start_sec=$timearray[1]; |
160 | $this->timer_start_msec=$timearray[0]; |
161 | } |
162 | |
163 | /** |
164 | * Stop timer (return result) |
165 | **/ |
166 | function stopTimer() |
167 | { |
168 | $now=microtime(); |
169 | $timearray=explode(" ",$now); |
170 | |
171 | $finish_secs=$timearray[1]; |
172 | $finish_msecs=$timearray[0]; |
173 | |
174 | $elapsed_seconds = $finish_secs - $this->timer_start_sec; |
175 | $elapsed_time = $elapsed_seconds + $finish_msecs - $this->timer_start_msec; |
176 | |
177 | $elapsed_ms = $elapsed_time * 1000; |
178 | |
179 | $elapsed_ms = round($elapsed_ms,3); |
180 | |
181 | return $elapsed_ms; |
182 | } |
183 | |
184 | |
185 | /** |
186 | * Constructor - randomises ID |
187 | **/ |
188 | function PPPing() |
189 | { |
190 | $this->Randomise(); |
191 | } |
192 | |
193 | /** |
194 | * Returns a dotted quad from hex format IPv4 address |
195 | **/ |
196 | function ipAddress($hexip) |
197 | { |
198 | $quad=""; |
199 | for($a=0; $a<=6; $a+=2) |
200 | { |
201 | $portion=substr($hexip,$a,2); |
202 | $decimal=hexdec($portion); |
203 | if ($quad!="") $quad.="."; |
204 | $quad.=$decimal; |
205 | } |
206 | return $quad; |
207 | } |
208 | |
209 | /** |
210 | * Generate an ICMP checksum |
211 | **/ |
212 | function Checksum($data) |
213 | { |
214 | if (strlen($data)%2) |
215 | $data .= "\x00"; |
216 | |
217 | $bit = unpack('n*', $data); |
218 | $sum = array_sum($bit); |
219 | |
220 | while ($sum >> 16) |
221 | $sum = ($sum >> 16) + ($sum & 0xffff); |
222 | |
223 | return pack('n*', ~$sum); |
224 | } |
225 | |
226 | /** |
227 | * Do a ping of the set hostname |
228 | * |
229 | * @return float |
230 | * Returns a negative number of failure which can be turned into text with |
231 | * the strError method. A positive number is a response in milliseconds (ms) |
232 | **/ |
233 | function Ping() |
234 | { |
235 | $this->clearLast(); |
236 | $type = "\x08"; // icmp echo |
237 | $code = "\x00"; |
238 | $checksum = "\x00\x00"; // initial |
239 | $identifier = $this->getIdentity(); |
240 | $dec_identity = $this->identity; |
241 | //$identifier = "\x00\x00"; |
242 | //$seqNumber = "\x00\x00"; |
243 | $seqNumber = $this->getSequence(); |
244 | $dec_sequence = $this->sequence; |
245 | $data = $this->data_package; |
246 | $package = $type.$code.$checksum.$identifier.$seqNumber.$data; |
247 | $checksum = $this->Checksum($package); // proper checksum |
248 | $package = $type.$code.$checksum.$identifier.$seqNumber.$data; |
249 | |
250 | $ip_protocol_code = getprotobyname("ip"); |
251 | $ip_ttl_code = 7; |
252 | |
253 | // Lookup hostname |
254 | $ips=str_replace(".","",$this->hostname); |
255 | if (!is_numeric($ips)) |
256 | { |
257 | $host=gethostbyname($this->hostname); |
258 | if ($host==$this->hostname) return -5; |
259 | } |
260 | else $host=$this->hostname; |
261 | |
262 | // Create Socket |
263 | $socket = socket_create(AF_INET, SOCK_RAW, 1); // @ |
264 | //or die(socket_strerror(socket_last_error())); |
265 | if (!$socket) return -3; |
266 | |
267 | // Set Non-Blocking |
268 | socket_set_nonblock($socket); // @ |
269 | |
270 | $socket_ttl = socket_get_option($socket,$ip_protocol_code,$ip_ttl_code); |
271 | |
272 | //for ($a=0; $a<64; $a++) |
273 | // echo $a." - ".@socket_get_option($socket,$ip_protocol_code,$a)."\n"; |
274 | |
275 | if ($this->ttl>0) |
276 | { |
277 | socket_set_option($socket,$ip_protocol_code,$ip_ttl_code,128); |
278 | $socket_ttl = socket_get_option($socket,$ip_protocol_code,$ip_ttl_code); |
279 | //socket_set_option($socket,Socket::IPPROTO_IP,Socket::IP_TTL,128); |
280 | //$socket_ttl = socket_get_option($socket,Socket::IPPROTO_IP,Socket::IP_TTL); |
281 | |
282 | } |
283 | else $socket_ttl = 64; // standard TTL |
284 | |
285 | |
286 | // Connect Socket |
287 | $sconn=socket_connect($socket, $host, null); // @ |
288 | if (!$sconn) return 0; |
289 | |
290 | // Package Size |
291 | //$package_size = 8+strlen($data); |
292 | $package_size = strlen($package); |
293 | |
294 | // Send Data |
295 | socket_send($socket, $package, $package_size, 0); // @ |
296 | |
297 | // Start Timer |
298 | $this->startTimer(); |
299 | $startTime = microtime(true); // need this for the looping section |
300 | |
301 | |
302 | // Read Data |
303 | $keepon=true; |
304 | |
305 | while( (false===($echo_reply=socket_read($socket, 255))) && $keepon) // @socket_read |
306 | { |
307 | |
308 | if ( (microtime(true) - $startTime) > $this->timeout ) |
309 | $keepon=false; |
310 | |
311 | } |
312 | |
313 | |
314 | if ($keepon) // didn't time out - read data |
315 | { |
316 | $elapsed=$this->stopTimer(); |
317 | |
318 | socket_close($socket); // @ |
319 | |
320 | if ( $echo_reply === false ) return -4; |
321 | else if (strlen($echo_reply)<2) return -2; |
322 | |
323 | $rx_parts = unpack("C*",$echo_reply); |
324 | $tx_parts = unpack("C*",$package); |
325 | $ipheader=""; |
326 | $ipheader_hex=""; |
327 | |
328 | if ($rx_parts[1] == 0x45) // IP Header Information |
329 | { |
330 | $ipheader=substr($echo_reply,0,20); |
331 | $ipheader_hex = $this->getHex($ipheader); |
332 | $echo_reply=substr($echo_reply,20); |
333 | $rx_parts = unpack("C*",$echo_reply); |
334 | } |
335 | |
336 | if ($this->debug) |
337 | { |
338 | echo "\n"; |
339 | echo " TyCoChksIdenSequData\n"; |
340 | echo "TX: ".$this->getHex($package)."\n"; |
341 | echo "RX: ".$this->getHex($echo_reply)."\n"; |
342 | if ($ipheader!="") echo "HR: ".$ipheader_hex."\n"; |
343 | } |
344 | |
345 | $echo_reply_hex = $this->getHex($echo_reply); |
346 | $reply_type = $rx_parts[1]; |
347 | $reply_code = $rx_parts[2]; |
348 | $reply_identity = hexdec(substr($echo_reply_hex,8,4)); |
349 | $reply_sequence = hexdec(substr($echo_reply_hex,12,4)); |
350 | |
351 | $match=true; |
352 | if ($ipheader!="") |
353 | { |
354 | $source=substr($ipheader_hex,24,8); |
355 | $dest=substr($ipheader_hex,32,8); |
356 | $ttl=hexdec(substr($ipheader_hex,16,2)); |
357 | if ($this->debug) echo $this->ipAddress($source)." => ".$this->ipAddress($dest)." | ttl: ".$ttl."\n"; |
358 | if ($source==$dest) $match=true; |
359 | else $match=false; |
360 | |
361 | $this->last["set"]=true; |
362 | $this->last["source"]=$this->ipAddress($source); |
363 | $this->last["destination"]=$this->ipAddress($dest); |
364 | $this->last["ttl"]=$ttl; |
365 | $this->last["hops"]=$socket_ttl - $ttl; |
366 | |
367 | |
368 | } |
369 | |
370 | if ( (($rx_parts[1]==0) || (($rx_parts[1]==8)&&($match))) && ($rx_parts[2]==0) ) |
371 | { // is echo_reply (0) or is echo_request (8) AND match (from same host) |
372 | // and has code of 0 |
373 | // valid response |
374 | if ($reply_identity != $dec_identity) return -8; // ID mismatch |
375 | else if ($reply_sequence != $dec_sequence) return -7; // sequence mismatch |
376 | else |
377 | { |
378 | $this->last["result"]=$elapsed; |
379 | return $elapsed; |
380 | } |
381 | } |
382 | else |
383 | { // ICMP Error |
384 | return -9; |
385 | } |
386 | |
387 | } |
388 | socket_close($socket); // @ |
389 | return -1; // timeout |
390 | } |
391 | |
392 | /** |
393 | * Returns textual error for code |
394 | **/ |
395 | function strError($code) |
396 | { |
397 | switch($code) |
398 | { |
399 | case -1: return "Timed Out"; break; |
400 | case -2: return "Reply Too Short"; break; |
401 | case -3: return "Failed to Open Socket"; break; |
402 | case -4: return "Invalid (false) Response"; break; |
403 | case -5: return "Hostname Lookup Failed"; break; |
404 | case -7: return "Sequence Mismatch"; break; |
405 | case -8: return "Identity Mismatch"; break; |
406 | case -9: return "ICMP Generic Error"; break; |
407 | |
408 | default: return "Unknown Error"; break; |
409 | } |
410 | } |
411 | |
412 | |
413 | } |
414 | |
415 | ?> |
Properties
Name | Value |
---|---|
svn:executable | * |