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: ?>