File:
1.08.2a/server/base/tests.inc.php (
View as Code)
1: 2: /* -------------------------------------------------------------
3: This file is part of FreeNATS
4:
5: FreeNATS is (C) Copyright 2008-2010 PurplePixie Systems
6:
7: FreeNATS 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: FreeNATS 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 FreeNATS. If not, see www.gnu.org/licenses
19:
20: For more information see www.purplepixie.org/freenats
21: -------------------------------------------------------------- */
22:
23: if (!isset($BaseDir)) $BaseDir="../base/"; //
24: require_once($BaseDir."timer.inc.php"); // just in case standalone
25:
26: // FreeNATS_Local_Test Base Class - Local Tests (run from FreeNATS server) must extend from this
27:
28: class FreeNATS_Local_Test
29: {
30: function DoTest($testname,$param,$hostname="",$timeout=-1,$params=false)
31: {
32: return 0;
33: }
34:
35: function Evaluate($result)
36: {
37: return -1;
38: }
39:
40: function DisplayForm(&$row)
41: {
42: return false;
43: }
44:
45: function ProtectOutput(&$row)
46: {
47: return false;
48: }
49: }
50:
51: // ------------------------------------------------------------------------------------------------
52: require($BaseDir."tests/tcp.inc.php");
53: require($BaseDir."tests/udp.inc.php");
54: require($BaseDir."tests/mysql.inc.php");
55: require($BaseDir."tests/imap.inc.php");
56: require($BaseDir."tests/smtp.inc.php");
57:
58: require($BaseDir."tests/dns.inc.php");
59: require($BaseDir."tests/nats-dns.inc.php"); // the wrapper module
60:
61: require($BaseDir."tests/smb.inc.php");
62:
63:
64: function ip_lookup($hostname) // "safe" DNS lookup function to call with a hostname, URL or IP - returns 0 if unsuccessful
65: {
66: // Is it already an IP adress?
67: $out=str_replace(".","",$hostname);
68: if (is_numeric($out)) return $hostname; // yes it is
69:
70: // No it is not
71: $ip=@gethostbyname($hostname);
72: if ($ip==$hostname) return 0; // unmodified host - lookup failed
73:
74: return $ip;
75: }
76:
77: function next_run_x($interval)
78: {
79: if ($interval<1) return time();
80: return time()+(($interval)*60)-30;
81: }
82:
83: function test_sleep()
84: {
85: global $NATS;
86: if (!isset($NATS)) return false;
87: $sleep=$NATS->Cfg->Get("test.interval",0);
88: if ($sleep<=0) return false;
89: $sleep=$sleep*1000000; // convert to usec
90: usleep($sleep);
91: return true;
92: }
93:
94: function url_lookup($url)
95: {
96: // Sod regular expressions here as we'd have to do it twice or with cleverness I lack
97: // Is it a URL?
98: $colon=strpos($url,":");
99: if ($colon != 0) // exists so it a URL
100: {
101: $out=preg_match("@^(?:http[s]*://)?([^/|\?|:]+)@i",$url,$matches);
102: $hostname=$matches[1];
103: }
104: else $hostname=$url; // try direct
105:
106: return ip_lookup($hostname);
107: }
108:
109:
110: function bin_str_dump($s,$count=0)
111: {
112: //$s = base_convert($s,10,2);
113: $data = unpack('C*',$s);
114: foreach($data as $item)
115: {
116: echo ord($item)." ";
117: }
118: echo "\n";
119: }
120:
121:
122:
123:
124: function icmpChecksum($data)
125: {
126: if (strlen($data)%2)
127: $data .= "\x00";
128:
129: $bit = unpack('n*', $data);
130: $sum = array_sum($bit);
131:
132: while ($sum >> 16)
133: $sum = ($sum >> 16) + ($sum & 0xffff);
134:
135: return pack('n*', ~$sum);
136: }
137:
138: function PingTest($host,$ctimeout=-1)
139: {
140: global $NATS;
141: $FreeNATS_Timer=new TFNTimer();
142: // Make Package
143: $type= "\x08";
144: $code= "\x00";
145: $checksum= "\x00\x00";
146: $identifier = "\x00\x00";
147: $seqNumber = "\x00\x00";
148: $data= "FreeNATS";
149: $package = $type.$code.$checksum.$identifier.$seqNumber.$data;
150: $checksum = icmpChecksum($package); // Calculate the checksum
151: $package = $type.$code.$checksum.$identifier.$seqNumber.$data;
152:
153: // Return s or ms(s*1000)
154: $returnsecs=true;
155: if (isset($NATS))
156: {
157: if ($NATS->Cfg->Get("test.icmp.returnms",0)==1) $returnsecs=false;
158: }
159:
160: // Timeout Values
161: if (isset($NATS)) $timeout=$NATS->Cfg->Get("test.icmp.timeout",10);
162: else $timeout=10;
163: if ($ctimeout>0) $timeout=$ctimeout; // use custom timeout if passed
164: if ($timeout<=0) $timeout=10; // catch-all for defaults bug
165:
166: // Create Socket
167: $socket = socket_create(AF_INET, SOCK_RAW, 1); // @
168: //or die(socket_strerror(socket_last_error()));
169: if (!$socket) return 0;
170:
171: // Set Non-Blocking
172: socket_set_nonblock($socket); // @
173:
174: // Connect Socket
175: $sconn=socket_connect($socket, $host, null); // @
176: if (!$sconn) return 0;
177:
178: // Package Size
179: //$package_size = 8+strlen($data);
180: $package_size = strlen($package);
181:
182: // Send Data
183: socket_send($socket, $package, $package_size, 0); // @
184:
185: // Start Timer
186: $FreeNATS_Timer->Start();
187: $startTime = microtime(true); // need this for the looping section
188:
189:
190: // Read Data
191: $keepon=true;
192:
193: while( (false===($echo_reply=socket_read($socket, 255))) && $keepon) // @socket_read
194: { // basically just kill time
195: // consider putting some sort of sleepy thing here to lower load but would f* with figures!
196:
197: if ( (microtime(true) - $startTime) > $timeout )
198: $keepon=false;
199: }
200:
201: /* 0 timeout, -1 icmp error (we think), -2 strlen too small on reply, -3 not enough bin parts, -4 echo_reply is false
202: */
203:
204: if ($keepon) // didn't time out - read data
205: {
206: $elapsed=$FreeNATS_Timer->Stop();
207:
208: if ( $echo_reply === false ) return -4;
209: else if (strlen($echo_reply)<2) return -2;
210:
211: //bin_str_dump($package);
212: //bin_str_dump($echo_reply);
213: //echo "Len p: ".strlen($package).", Len r: ".strlen($echo_reply)."\n";
214: $parts = unpack("C*",$echo_reply);
215: if (count($parts)<2) return -3;
216: $ret_type_part = $parts[2]; // ask me not why but this seems to be the type when unpacked as signed char (C)
217: // Examing Received Data
218: // Type, Code, Checksum 2, id 2, seq 2, data X
219: $ret_type=$echo_reply[0];
220: $ret_code=$echo_reply[1];
221: //printf("%02x %02x ",$ret_type,$ret_code);
222: /*
223: $ret_checksum=substr($echo_reply,2,2);
224: $ret_id=substr($echo_reply,4,2);
225: $ret_seq=substr($echo_reply,6,2);
226: $ret_data=substr($echo_reply,8,strlen($echo_reply)-7);
227: */
228: /*
229: printf("\n%02x %02x %04x %x %04x %s ",$ret_type,$ret_code,$ret_checksum,$ret_id,$ret_seq,$ret_data);
230: printf("\n%02x %02x %04x %x %04x %s ",$type,$code,$checksum,$identifier,$seqNumber,$data);
231: echo "\n";
232: bin_str_dump($package,$package_size);
233: bin_str_dump($echo_reply);
234: */
235: if ($returnsecs) $elapsed=round($elapsed,4);
236: else $elapsed=round( ($elapsed*1000),4 );
237: socket_close($socket); // @
238: // $ret=round(microtime(true) - $startTime, 4); -- old method
239: if ($elapsed<=0) $elapsed="0.0001"; // safety catch-all
240:
241:
242: if (($ret_type==0)&&(ord($ret_type_part)==48)) // valid icmp echo_reply message ( ord()==48 is equal to "0" )
243: return $elapsed;
244: else // icmp error message
245: return -1;
246: /*
247: if ($ret==0) return "0.0001";
248: else
249: {
250: if ($ret<=0) return "0.0001";
251: else return $ret;
252: }
253: */
254: }
255:
256: // Socket timed out
257: socket_close($socket); // @
258: return 0;
259: }
260:
261: function WebTest($url,$timeout=-1)
262: {
263: global $NATS;
264: if ($timeout<=0) // use NATS or env
265: {
266: if (isset($NATS))
267: {
268: $nto=$NATS->Cfg->Get("test.http.timeout",-1);
269: if ($nto>0) $timeout=$nto; // use NATS timeout
270: }
271: }
272: if ($timeout>0) // use the set timeout
273: $oldtimeout=ini_set("default_socket_timeout",$timeout);
274:
275: if (function_exists("curl_getinfo")) // use CURL if present
276: {
277: $ch=curl_init();
278: curl_setopt($ch,CURLOPT_URL,$url);
279: curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
280: curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
281: curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
282: curl_setopt($ch,CURLOPT_HEADER,1);
283: if ($timeout>0) curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
284: if ($timeout>0) curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
285: if (!$output=curl_exec($ch))
286: {
287: $ctr=-1; // failed
288: }
289: else $ctr=round(curl_getinfo($ch,CURLINFO_SIZE_DOWNLOAD)/1024,2);
290: curl_close($ch);
291:
292: if ($ctr==0) $ctr="0.0001";
293:
294: }
295: else
296: { // no CURL - use fopen()
297: $oldagent=ini_set("user_agent","MSIE 4\.0b2;"); // MSIE 4.0b2 is HTTP/1.0 only just like fopen http wrapper
298: $fp=@fopen($url,"r");
299: if ($fp<=0)
300: {
301: if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
302: ini_set("user_agent",$oldagent);
303: return -1;
304: }
305: $ctr=0;
306: while ($body=@fgets($fp,1024)) $ctr+=sizeof($body);
307: @fclose($fp);
308: ini_set("user_agent",$oldagent);
309: }
310:
311:
312:
313: if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
314: return $ctr;
315: }
316:
317: function DoTest($test,$param,$hostname="",$timeout=-1,$params=0,$nodeid="")
318: {
319: global $NATS;
320: if (!is_array($params))
321: {
322: $params=array();
323: for ($a=0; $a<10; $a++) $params[$a]="";
324: }
325:
326: switch ($test)
327: {
328: case "web": case "wsize":
329: // Don't bother with pre-resolution as size only
330: return WebTest($param,$timeout);
331: break;
332: /* -- modularised
333: case "tcp": // nb TCP does not support timeouts currently
334: $ip=ip_lookup($hostname);
335: if ($ip=="0") return 0;
336: $fp=@fsockopen($ip,$param);
337: if ($fp<=0) return 0;
338: @fclose($fp);
339: return 1;
340: break;
341: */
342: case "wtime":
343: $timer=new TFNTimer();
344: // Do a pre-lookup
345: $ip=url_lookup($param);
346: if ($ip=="0") return -1; // dns lookup failed
347: $timer->Start();
348: $r=WebTest($param,$timeout);
349: $elapsedTime=$timer->Stop();
350: $elapsedTime=round($elapsedTime,4);
351: if ($r<0) return -1; // open failed
352: if ($r==0) return -2; // no chars shown as returned
353: if ($elapsedTime<=0) return 0.0001;
354: return $elapsedTime;
355: break;
356:
357: case "host":
358: $timer=new TFNTimer();
359: if (preg_match("/[a-zA-Z]/",$param)>0) $is_ip=false;
360: else $is_ip=true;
361:
362: $timer->Start();
363: if ($is_ip) $result=gethostbyaddr($param);
364: else $result=gethostbyname($param);
365: $elapsedTime=$timer->Stop();
366:
367: if ($result==$param) // lookup failed
368: return -1;
369:
370: if ($result=="") // lookup failed
371: return -1;
372:
373: $elapsedTime=round($elapsedTime,4);
374: if ($elapsedTime<=0) return 0.0001;
375: return $elapsedTime;
376: break;
377:
378: case "testloop":
379: return $param;
380: break;
381:
382: case "testrand":
383: mt_srand(microtime()*1000000);
384: if ( ($param=="") || ($param==0) ) $param=100;
385: return mt_rand(0,$param);
386: break;
387:
388: case "ping":
389: return PingTest($param,$timeout);
390: break;
391:
392: default:
393: if (isset($NATS)) // try and see if a test is registered
394: {
395: if (isset($NATS->Tests->QuickList[$test])) // exists
396: {
397: $NATS->Tests->Tests[$test]->Create();
398: return $NATS->Tests->Tests[$test]->instance->DoTest($test,$param,$hostname,$timeout,$params);
399: }
400: }
401:
402: }
403: return -1; // did not run any test so untested
404: }
405:
406: function SimpleEval($test,$result)
407: {
408: global $NATS;
409: switch($test)
410: {
411: case "ping": // handles both types of simple evaluation (inbuilt ICMP and remote ping)
412: if ($result<=0) return 2;
413: return 0;
414: case "web": case "wsize":
415: if ($result<=0) return 2;
416: return 0;
417: /*
418: case "tcp":
419: if ($result==1) return 0;
420: return 2;
421: */
422: case "wtime":
423: if ($result<0) return 2;
424: return 0;
425: /*
426: case "mysql":
427: if ($result<=0) return 2;
428: return 0;
429:
430: case "mysqlrows":
431: if ($result<=0) return 2; // no rows returned or error
432: return 0;
433: */
434: case "host": case "dns":
435: if ($result<=0) return 2; // no records returned or error
436:
437: case "testloop":
438: return 0;
439: case "testrand":
440: return 0;
441:
442: default:
443: if (isset($NATS))
444: {
445: if (isset($NATS->Tests->QuickList[$test]))
446: {
447: $NATS->Tests->Tests[$test]->Create();
448: return $NATS->Tests->Tests[$test]->instance->Evaluate($result);
449: }
450: }
451: }
452: return -1; // untested if we don't know WTF the result was
453: }
454:
455: function aText($al)
456: {
457: return oText($al); // uses function in tests.inc.php with site config support
458: /* -- depreciated
459: switch($al)
460: {
461: case -1: return "Untested";
462: case 0: return "Passed";
463: case 1: return "Warning";
464: case 2: return "Failed";
465: default: return "Unknown";
466: }
467: */
468: }
469: ?>