File: 1.08.1a/server/base/tests.inc.php (View as HTML)

  1: <?php // tests.inc.php
  2: /* -------------------------------------------------------------
  3: This file is part of FreeNATS
  4: 
  5: FreeNATS is (C) Copyright 2008 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: if ($count==0) $count=strlen($s);
113: for($a=0; $a<$count; $a++)
114: 	{
115: 	$c=$s[$a];
116: 	printf("%d: 0x%02x %d %c\n",$a,$c,$c,$c);
117: 	}
118: }
119: 
120: 
121: 
122: 
123:  function icmpChecksum($data)
124:     {
125:     if (strlen($data)%2)
126:     $data .= "\x00";
127:     
128:     $bit = unpack('n*', $data);
129:     $sum = array_sum($bit);
130:     
131:     while ($sum >> 16)
132:     $sum = ($sum >> 16) + ($sum & 0xffff);
133:     
134:     return pack('n*', ~$sum);
135:     }
136:    
137: function PingTest($host,$ctimeout=-1)
138: 	{
139: 	global $NATS;
140: 	$FreeNATS_Timer=new TFNTimer();
141:     // Make Package
142:     $type= "\x08";
143:     $code= "\x00";
144:     $checksum= "\x00\x00";
145:     $identifier = "\x00\x00";
146:     $seqNumber = "\x00\x00";
147:     $data= "FreeNATS";
148:     $package = $type.$code.$checksum.$identifier.$seqNumber.$data;
149:     $checksum = icmpChecksum($package); // Calculate the checksum
150:     $package = $type.$code.$checksum.$identifier.$seqNumber.$data;
151:     
152:     // Return s or ms(s*1000)
153:     $returnsecs=true;
154:     if (isset($NATS))
155:     	{
156: 	    if ($NATS->Cfg->Get("test.icmp.returnms",0)==1) $returnsecs=false;
157:     	}
158: 
159: 	// Timeout Values
160:     if (isset($NATS)) $timeout=$NATS->Cfg->Get("test.icmp.timeout",10);
161:     else $timeout=10;
162:     if ($ctimeout>0) $timeout=$ctimeout; // use custom timeout if passed
163:     if ($timeout<=0) $timeout=10; // catch-all for defaults bug
164:     
165:     // Create Socket
166:     $socket = socket_create(AF_INET, SOCK_RAW, 1); // @
167:     	//or die(socket_strerror(socket_last_error()));
168:     if (!$socket) return 0;
169:     
170:     // Set Non-Blocking
171:     socket_set_nonblock($socket); // @
172:     	
173:     // Connect Socket
174:     $sconn=socket_connect($socket, $host, null); // @
175:     if (!$sconn) return 0;
176:     
177: 	// Package Size
178: 	$package_size = 8+strlen($data);
179: 	
180:     // Send Data
181:     socket_send($socket, $package, $package_size, 0); // @
182:         
183:     // Start Timer
184:     $FreeNATS_Timer->Start();
185:     $startTime = microtime(true); // need this for the looping section
186:     
187: 
188:     // Read Data
189:     $keepon=true;
190: 
191:     while( (!($echo_reply=socket_read($socket, 2))) && $keepon) // @socket_read
192:     	{ // basically just kill time
193:     	// consider putting some sort of sleepy thing here to lower load but would f* with figures!
194:     	
195:     	if ( (microtime(true) - $startTime) > $timeout )
196:     		$keepon=false;
197: 		}
198:     	
199: 	if ($keepon) // didn't time out - read data
200:     	{
201: 	    $elapsed=$FreeNATS_Timer->Stop();
202: 		
203: 		// Examing Received Data
204: 		// Type, Code, Checksum 2, id 2, seq 2, data X
205: 		$ret_type=$echo_reply[0];
206: 		$ret_code=$echo_reply[1];
207: 		//printf("%02x %02x ",$ret_type,$ret_code);
208: 		/*
209: 		$ret_checksum=substr($echo_reply,2,2);
210: 		$ret_id=substr($echo_reply,4,2);
211: 		$ret_seq=substr($echo_reply,6,2);
212: 		$ret_data=substr($echo_reply,8,strlen($echo_reply)-7);
213: 		*/
214: 		/*
215: 		printf("\n%02x %02x %04x %x %04x %s ",$ret_type,$ret_code,$ret_checksum,$ret_id,$ret_seq,$ret_data);
216: 		printf("\n%02x %02x %04x %x %04x %s ",$type,$code,$checksum,$identifier,$seqNumber,$data);
217: 		echo "\n";
218: 		bin_str_dump($package,$package_size);
219: 		bin_str_dump($echo_reply);
220: 		*/
221: 	    if ($returnsecs) $elapsed=round($elapsed,4);
222: 	    else $elapsed=round( ($elapsed*1000),4 );
223: 	    socket_close($socket); // @
224:     	// $ret=round(microtime(true) - $startTime, 4); -- old method
225:     	if ($elapsed<=0) $elapsed="0.0001"; // safety catch-all
226: 		
227: 		if ($ret_type==0) // valid icmp echo_reply message
228: 			return $elapsed;
229: 		else // icmp error message
230: 			return -1;
231:     	/*
232:     	if ($ret==0) return "0.0001";
233:     	else 
234:     		{
235: 	    	if ($ret<=0) return "0.0001";
236: 	    	else return $ret;
237:     		}
238:     	*/
239:     	}
240:     	
241:     // Socket timed out
242:     socket_close($socket); // @
243:     return 0;
244: 	}
245: 
246: function WebTest($url,$timeout=-1)
247: 	{
248: 	global $NATS;
249: 	if ($timeout<=0) // use NATS or env
250: 		{
251: 		if (isset($NATS))
252: 			{
253: 			$nto=$NATS->Cfg->Get("test.http.timeout",-1);
254: 			if ($nto>0) $timeout=$nto; // use NATS timeout
255: 			}
256: 		}
257: 	if ($timeout>0) // use the set timeout
258: 		$oldtimeout=ini_set("default_socket_timeout",$timeout);
259: 		
260: 	if (function_exists("curl_getinfo")) // use CURL if present
261: 		{
262: 		$ch=curl_init();
263: 		curl_setopt($ch,CURLOPT_URL,$url);
264: 		curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
265: 		curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
266: 		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
267: 		curl_setopt($ch,CURLOPT_HEADER,1);
268: 		if ($timeout>0) curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
269: 		if ($timeout>0) curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
270: 		if (!$output=curl_exec($ch))
271: 			{
272: 			$ctr=-1; // failed
273: 			}
274: 		else $ctr=round(curl_getinfo($ch,CURLINFO_SIZE_DOWNLOAD)/1024,2);
275: 		curl_close($ch);
276: 		
277: 		if ($ctr==0) $ctr="0.0001";
278: 		
279: 		}
280: 	else
281: 		{	// no CURL - use fopen()	
282: 		$oldagent=ini_set("user_agent","MSIE 4\.0b2;"); // MSIE 4.0b2 is HTTP/1.0 only just like fopen http wrapper
283: 		$fp=@fopen($url,"r");
284: 		if ($fp<=0)
285: 			{
286: 			if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
287: 			ini_set("user_agent",$oldagent);
288: 			return -1;
289: 			}
290: 		$ctr=0;
291: 		while ($body=@fgets($fp,1024)) $ctr+=sizeof($body);
292: 		@fclose($fp);
293: 		ini_set("user_agent",$oldagent);
294: 		}
295: 	
296: 	
297: 	
298: 	if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
299: 	return $ctr;
300: 	}
301: 	
302: function DoTest($test,$param,$hostname="",$timeout=-1,$params=0,$nodeid="")
303: {
304: global $NATS;
305: if (!is_array($params))
306: 	{
307: 	$params=array();
308: 	for ($a=0; $a<10; $a++) $params[$a]="";
309: 	}
310: 	
311: switch ($test)
312: 	{
313: 	case "web": case "wsize":
314: 		// Don't bother with pre-resolution as size only
315: 		return WebTest($param,$timeout);
316: 		break;
317: 	/* -- modularised
318: 	case "tcp": // nb TCP does not support timeouts currently
319: 		$ip=ip_lookup($hostname);
320: 		if ($ip=="0") return 0;
321: 		$fp=@fsockopen($ip,$param);
322: 		if ($fp<=0) return 0;
323: 		@fclose($fp);
324: 		return 1;
325: 		break;
326: 	*/
327: 	case "wtime":
328: 		$timer=new TFNTimer();
329: 		// Do a pre-lookup
330: 		$ip=url_lookup($param);
331: 		if ($ip=="0") return -1; // dns lookup failed
332: 		$timer->Start();
333: 		$r=WebTest($param,$timeout);
334: 		$elapsedTime=$timer->Stop();
335: 		$elapsedTime=round($elapsedTime,4);
336: 		if ($r<0) return -1; // open failed
337: 		if ($r==0) return -2; // no chars shown as returned
338: 		if ($elapsedTime<=0) return 0.0001;
339: 		return $elapsedTime;
340: 		break;
341: 		
342: 	case "host":
343: 		$timer=new TFNTimer();
344: 		if (preg_match("/[a-zA-Z]/",$param)>0) $is_ip=false;
345: 		else $is_ip=true;
346: 		
347: 		$timer->Start();
348: 		if ($is_ip) $result=gethostbyaddr($param);
349: 		else $result=gethostbyname($param);
350: 		$elapsedTime=$timer->Stop();
351: 		
352: 		if ($result==$param) // lookup failed
353: 			return -1;
354: 			
355: 		if ($result=="")	// lookup failed
356: 			return -1;
357: 			
358: 		$elapsedTime=round($elapsedTime,4);
359: 		if ($elapsedTime<=0) return 0.0001;
360: 		return $elapsedTime;
361: 		break;
362: 
363: 	case "testloop":
364: 		return $param;
365: 		break;
366: 		
367: 	case "testrand":
368: 		mt_srand(microtime()*1000000);
369: 		if ( ($param=="") || ($param==0) ) $param=100;
370: 		return mt_rand(0,$param);
371: 		break;
372: 		
373: 	case "ping":
374: 		return PingTest($param,$timeout);
375: 		break;
376: 
377: 	default:
378: 		if (isset($NATS)) // try and see if a test is registered
379: 			{
380: 			if (isset($NATS->Tests->QuickList[$test])) // exists
381: 				{
382: 				$NATS->Tests->Tests[$test]->Create();
383: 				return $NATS->Tests->Tests[$test]->instance->DoTest($test,$param,$hostname,$timeout,$params);
384: 				}
385: 			}
386: 		
387: 	}
388: return -1; // did not run any test so untested
389: }
390: 
391: function SimpleEval($test,$result)
392: {
393: global $NATS;
394: switch($test)
395: 	{
396: 	case "ping": // handles both types of simple evaluation (inbuilt ICMP and remote ping)
397: 		if ($result<=0) return 2;
398: 		return 0;
399: 	case "web": case "wsize":
400: 		if ($result<=0) return 2;
401: 		return 0;
402: 	/*
403: 	case "tcp":
404: 		if ($result==1) return 0;
405: 		return 2;
406: 	*/
407: 	case "wtime":
408: 		if ($result<0) return 2;
409: 		return 0;
410: 	/*
411: 	case "mysql":
412: 		if ($result<=0) return 2;
413: 		return 0;
414: 		
415: 	case "mysqlrows":
416: 		if ($result<=0) return 2; // no rows returned or error
417: 		return 0;
418: 	*/	
419: 	case "host": case "dns":
420: 		if ($result<=0) return 2; // no records returned or error
421: 		
422: 	case "testloop":
423: 		return 0;
424: 	case "testrand":
425: 		return 0;
426: 		
427: 	default:
428: 	if (isset($NATS))
429: 		{
430: 		if (isset($NATS->Tests->QuickList[$test]))
431: 			{
432: 			$NATS->Tests->Tests[$test]->Create();
433: 			return $NATS->Tests->Tests[$test]->instance->Evaluate($result);
434: 			}
435: 		}
436: 	}
437: return -1; // untested if we don't know WTF the result was
438: }
439: 
440: function aText($al)
441: {
442: return oText($al); // uses function in tests.inc.php with site config support	
443: /* -- depreciated
444: switch($al)
445: 	{
446: 	case -1: return "Untested";
447: 	case 0: return "Passed";
448: 	case 1: return "Warning";
449: 	case 2: return "Failed";
450: 	default: return "Unknown";
451: 	}
452: */
453: }
454: ?>