Annotation of /alx-src/tags/alx-web-0_7_0_20170802_2/include/ppping.inc.php
Parent Directory | Revision Log
Revision 7070 -
(hide annotations)
(download)
Mon Sep 7 10:50:48 2015 UTC (9 years ago) by niro
Original Path: alx-src/branches/alx-web-070/include/ppping.inc.php
File size: 9495 byte(s)
Mon Sep 7 10:50:48 2015 UTC (9 years ago) by niro
Original Path: alx-src/branches/alx-web-070/include/ppping.inc.php
File size: 9495 byte(s)
created branch 'alx-web-070'
1 | niro | 2195 | <?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 | * |