File: 1.09.5a/server/bin/discover.php (View as HTML)

  1: <?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: $ranges=array();
 24: $actranges=array();
 25: $rangecount=0;
 26: $recorded=0;
 27: $webprobe=false;
 28: $live=false;
 29: $debug=false;
 30: $outfile="discover.xml";
 31: $output="";
 32: 
 33: 
 34: 
 35: function AddNode($nodeid,$hostname,$description="")
 36: {
 37: global $output;
 38: $output.="<node NODEID=\"".$nodeid."\">\n";
 39: $output.=" <nodeid>".$nodeid."</nodeid>\n";
 40: $output.=" <hostname>".$hostname."</hostname>\n";
 41: $output.=" <nodedesc>".$description."</nodedesc>\n";
 42: $output.="</node>\n\n";
 43: }
 44: 
 45: function AddLocaltest($nodeid,$testtype,$param)
 46: {
 47: global $output,$recorded;
 48: $output.="<localtest>\n";
 49: $output.=" <nodeid>".$nodeid."</nodeid>\n";
 50: $output.=" <testtype>".$testtype."</testtype>\n";
 51: $output.=" <testparam>".$param."</testparam>\n";
 52: $output.="</localtest>\n\n";
 53: }
 54: 
 55:  function DiscovericmpChecksum($data)
 56:     {
 57:     if (strlen($data)%2)
 58:     $data .= "\x00";
 59:     
 60:     $bit = unpack('n*', $data);
 61:     $sum = array_sum($bit);
 62:     
 63:     while ($sum >> 16)
 64:     $sum = ($sum >> 16) + ($sum & 0xffff);
 65:     
 66:     return pack('n*', ~$sum);
 67:     }
 68:    
 69: function DiscoverPing($host)
 70: 	{
 71:     // Make Package
 72:     $type= "\x08";
 73:     $code= "\x00";
 74:     $checksum= "\x00\x00";
 75:     $identifier = "\x00\x00";
 76:     $seqNumber = "\x00\x00";
 77:     $data= "FreeNATS";
 78:     $package = $type.$code.$checksum.$identifier.$seqNumber.$data;
 79:     $checksum = DiscovericmpChecksum($package); // Calculate the checksum
 80:     $package = $type.$code.$checksum.$identifier.$seqNumber.$data;
 81:     
 82:     // Return s or ms(s*1000)
 83:     $returnsecs=true;
 84:     
 85: 
 86: 	// Timeout Values
 87:     $timeout=10;
 88:     
 89:     // Create Socket
 90:     $socket = @socket_create(AF_INET, SOCK_RAW, 1);
 91:     	//or die(socket_strerror(socket_last_error()));
 92:     if (!$socket) return -1;
 93:     
 94:     // Set Non-Blocking
 95:     @socket_set_nonblock($socket);
 96:     	
 97:     // Connect Socket
 98:     $sconn=@socket_connect($socket, $host, null);
 99:     if (!$sconn) return -1;
100:     
101:     // Send Data
102:     @socket_send($socket, $package, strLen($package), 0);
103:         
104:     $startTime=microtime(true);
105:     
106: 
107:     // Read Data
108:     $keepon=true;
109: 
110:     while( (!(@socket_read($socket, 255))) && $keepon)
111:     	{ // basically just kill time
112:     	// consider putting some sort of sleepy thing here to lower load but would f* with figures!
113:     	
114:     	if ( (microtime(true) - $startTime) > $timeout )
115:     		$keepon=false;
116: 		}
117:     	
118: 	if ($keepon) // didn't time out - read data
119:     	{
120: 	 
121: 	    @socket_close($socket);
122:     	
123:     	return 1;
124:     	
125:     	}
126:     	
127:     // Socket timed out
128:     @socket_close($socket);
129:     return 0;
130: 	}
131: 
132: 
133: function ddt($txt) // discovery debug text
134: {
135: global $debug;
136: if ($debug) echo $txt."\n";
137: }
138: 
139: if ($argc<2)
140: 	{
141: 	echo "FreeNATS Discovery Tool\n";
142: 	echo "Usage: php discover.php <IP/RANGE> [<IP/RANGE> ...] [options]\n\n";
143: 	echo "Goes through IPs or ranges and discovers nodes, outputting an XML file for\n";
144: 	echo "import to FreeNATS with the bulk importer.\n\n";
145: 	echo "IPs or Ranges are Specified as:";
146: 	echo " 10.0.10.1 - single IP address\n";
147: 	echo " 10.0.10.1-10.0.10.254 - range of IP addresses\n";
148: 	echo " 10.0.10.0/24 - network with numeric netmask\n";
149: 	echo " 10.0.10.0/255.255.255.0 - network with IPv4 netmask\n\n";
150: 	echo "Options are:";
151: 	echo " --file <filename> - output XML file (defaults to discover.xml)\n";
152: 	echo " --webprobe - do a web probe and add the test if found\n";
153: 	echo " --recorded - set the record data flag for any discovered tests by default\n\n";
154: 	echo "See www.purplepixie.org/freenats for more information.\n\n";
155: 	exit();
156: 	}
157: 
158: for ($ac=1; $ac<$argc; $ac++)
159: 	{
160: 	$arg=$argv[$ac];
161: 	if ($arg=="--live") $live=true;
162: 	else if ($arg=="--debug") $debug=true;
163: 	else if ($arg=="--file") $outfile=$argv[++$ac];
164: 	else if ($arg=="--webprobe") $webprobe=true;
165: 	else if ($arg=="--recorded") $recorded=1;
166: 	else 
167: 		{
168: 		$ranges[$rangecount]=$arg;
169: 		$actranges[$rangecount]['start']=0;
170: 		$actranges[$rangecount]['finish']=0;
171: 		
172: 		if (strpos($arg,"-")!==false) // range
173: 			{
174: 			$pos=strpos($arg,"-");
175: 			$from=substr($arg,0,$pos);
176: 			$to=substr($arg,$pos+1);
177: 			$actranges[$rangecount]['start']=ip2long($from);
178: 			$actranges[$rangecount]['finish']=ip2long($to);
179: 			}
180: 		else if (strpos($arg,"/")!==false) // mask delimited
181: 			{
182: 			$pos=strpos($arg,"/");
183: 			$ip=substr($arg,0,$pos);
184: 			$mask=substr($arg,$pos+1);
185: 			if (is_numeric($mask)) // numeric mask
186: 				{
187: 				ddt("Numeric Netmask ".$mask);
188: 				$netmask=0;
189: 				for ($a=0; $a<$mask; $a++)
190: 					{
191: 					$val=pow(2,(32-$a-1));
192: 					ddt("Numeric Netmask: Pos ".$a." Adding ".$val);
193: 					$netmask+=$val;
194: 					}
195: 				ddt("Numeric Netmask ".long2ip($netmask)." ".$netmask);
196: 				$netmask=ip2long(long2ip($netmask)); // weirdness avoidance!!
197: 				//
198: 				}
199: 			else $netmask=ip2long($mask);
200: 			ddt("Netmask ".$netmask);
201: 			$ipaddr=ip2long($ip);
202: 			ddt("IP ".$ipaddr." (".$ip.")");
203: 			$network=($ipaddr & $netmask);
204: 			$firsthost=$network+1;
205: 			
206: 			$broadcast=($network | (~$netmask));
207: 			$lasthost=$broadcast-1;
208: 			
209: 			$actranges[$rangecount]['start']=$firsthost;
210: 			
211: 			$actranges[$rangecount]['finish']=$lasthost;
212: 			
213: 			}
214: 		else
215: 			{ // single host
216: 			$actranges[$rangecount]['start']=ip2long($arg);
217: 			$actranges[$rangecount]['finish']=ip2long($arg);
218: 			}
219: 		
220: 		$rangecount++;
221: 		}
222: 	}
223: 	
224: 
225: $output.="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
226: $output.="<freenats-data>\n\n";
227: 
228: $output.="<default TYPE=\"node\">\n";
229: $output.=" <nodeenabled>1</nodeenabled>\n";
230: $output.=" <pingtest>0</pingtest>\n";
231: $output.="</default>\n\n";
232: 
233: $output.="<default TYPE=\"localtest\">\n";
234: $output.=" <testenabled>1</testenabled>\n";
235: $output.=" <testrecord>".$recorded."</testrecord>\n";
236: $output.="</default>\n\n";
237: 
238: 	
239: 
240: echo "FreeNATS Discover Started\n";
241: echo " Live: ";
242: if ($live) echo "Yes";
243: else echo "No";
244: echo "    Debug: ";
245: if ($debug) echo "Yes";
246: else echo "No";
247: echo "\n File: ".$outfile;
248: echo "\n\n";
249: echo "Ranges: ".$rangecount."\n";
250: if ($rangecount<=0)
251: 	{
252: 	echo "\nNo ranges or IP addresses specified\n";
253: 	}
254: 	
255: for($a=0; $a<$rangecount; $a++)
256:  {
257:  echo " ".$ranges[$a]." ".$actranges[$a]['start']."-".$actranges[$a]['finish']." ".long2ip($actranges[$a]['start'])."-".long2ip($actranges[$a]['finish'])."\n";
258:  }
259: echo "\n";
260: 
261: for($a=0; $a<$rangecount; $a++)
262: 	{
263: 	$start=$actranges[$a]['start'];
264: 	$finish=$actranges[$a]['finish'];
265: 	echo "+ ".long2ip($start)." - ".long2ip($finish)."\n";
266: 	for ($ip=$start; $ip<=$finish; $ip++)
267: 		{
268: 		ddt("- ".long2ip($ip)." (".$ip.")");
269: 		$res=DiscoverPing(long2ip($ip));
270: 		if ($res<0)
271: 			{
272: 			echo "Fatal Error: Could Not Open ICMP Connection (Ping Send Failed)\n\n";
273: 			exit();
274: 			}
275: 		else if ($res==0)
276: 			{
277: 			ddt("- No Reply for Ping");
278: 			}
279: 		else
280: 			{
281: 			echo "- Ping Returned - Host Active\n";
282: 			$hostname=gethostbyaddr(long2ip($ip));
283: 			echo "- Name: ".$hostname."\n";
284: 			$ipaddr=long2ip($ip);
285: 			if ($hostname==$ipaddr)
286: 				{
287: 				$nodeid=$ipaddr;
288: 				}
289: 			else
290: 				{
291: 				$exp=explode(".",$hostname);
292: 				$nodeid=$exp[0];
293: 				}
294: 			echo "- NodeID: ".$nodeid."\n";
295: 			AddNode($nodeid,$ipaddr,$hostname);
296: 			if ($webprobe)
297: 				{
298: 				$url="http://".$ipaddr."/";
299: 				echo "- Web Probe: ".$url."... ";
300: 				$fp=@fopen($url,"r");
301: 				if ($fp<=0) echo "Failed\n";
302: 				else
303: 					{
304: 					echo "Succeeded\n";
305: 					fclose($fp);
306: 					AddLocaltest($nodeid,"webtime",$url);
307: 					echo "- Adding Web Test ".$url."\n";
308: 					}
309: 				}
310: 			}
311: 		echo "\n";
312: 		}
313: 	echo "\n";
314: 	}
315: 	
316: $output.="\n</freenats-data>";
317: 
318: echo "\nFinish... Writing File... ";
319: $fp=fopen($outfile,"w");
320: fputs($fp,$output,strlen($output));
321: fclose($fp);
322: echo "\n";
323: 
324: ?>