mirror of
				https://github.com/librenms/librenms.git
				synced 2024-10-07 16:52:45 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			228 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			228 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env php
 | |
| <?php
 | |
| /*
 | |
|  * Copyright (C) 2015 Daniel Preussker <f0o@librenms.org>
 | |
|  * This program is free software: you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License as published by
 | |
|  * the Free Software Foundation, either version 3 of the License, or
 | |
|  * (at your option) any later version.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
 | |
|  * GNU General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * SNMP Scan
 | |
|  * @author f0o <f0o@librenms.org>
 | |
|  * @copyright 2015 f0o, LibreNMS
 | |
|  * @license GPL
 | |
|  * @package LibreNMS
 | |
|  * @subpackage Discovery
 | |
|  */
 | |
| 
 | |
| use LibreNMS\Exceptions\HostExistsException;
 | |
| use LibreNMS\Exceptions\HostUnreachableException;
 | |
| use LibreNMS\Exceptions\HostUnreachablePingException;
 | |
| 
 | |
| chdir(__DIR__); // cwd to the directory containing this script
 | |
| 
 | |
| $ts = microtime(true);
 | |
| 
 | |
| $init_modules = array('discovery');
 | |
| require __DIR__ . '/includes/init.php';
 | |
| 
 | |
| if ($config['autodiscovery']['snmpscan'] === false) {
 | |
|     echo 'SNMP-Scan disabled.'.PHP_EOL;
 | |
|     exit(2);
 | |
| }
 | |
| 
 | |
| function perform_snmp_scan($net, $force_network, $force_broadcast)
 | |
| {
 | |
|     global $stats, $config, $debug, $vdebug, $more_info;
 | |
|     echo 'Range: '.$net->network.'/'.$net->bitmask.PHP_EOL;
 | |
|     $config['snmp']['timeout'] = 1;
 | |
|     $config['snmp']['retries'] = 0;
 | |
|     $config['fping_options']['retries']  = 0;
 | |
|     $start = ip2long($net->network);
 | |
|     $end   = ip2long($net->broadcast)-1;
 | |
| 
 | |
|     if ($force_network === true) { //Force-scan network address
 | |
|         d_echo("Forcing network address scan".PHP_EOL);
 | |
|         $start = $start-1;
 | |
|     }
 | |
| 
 | |
|     if ($force_broadcast === true) { //Force-scan broadcast address
 | |
|         d_echo("Forcing broadcast address scan".PHP_EOL);
 | |
|         $end = $end+1;
 | |
|     }
 | |
| 
 | |
|     if ($net->bitmask === "31") { //Handle RFC3021 /31 prefixes
 | |
|         $start = ip2long($net->network)-1;
 | |
|         $end   = ip2long($net->broadcast);
 | |
|         d_echo("RFC3021 network, hosts ".long2ip($start+1)." and ".long2ip($end).PHP_EOL.PHP_EOL);
 | |
|     } elseif ($net->bitmask === "32") { //Handle single-host /32 prefixes
 | |
|         $start = ip2long($net->network)-1;
 | |
|         $end   = $start+1;
 | |
|         d_echo("RFC3021 network, hosts ".long2ip($start+1)." and ".long2ip($end).PHP_EOL.PHP_EOL);
 | |
|     } else {
 | |
|         d_echo("Network:   ".($net->network).PHP_EOL);
 | |
|         d_echo("Broadcast: ".($net->broadcast).PHP_EOL.PHP_EOL);
 | |
|     }
 | |
| 
 | |
|     while ($start++ < $end) {
 | |
|         $stats['count']++;
 | |
|         $host = long2ip($start);
 | |
| 
 | |
|         if ($vdebug || $more_info === true) {
 | |
|             echo "Scanning: ".$host.PHP_EOL;
 | |
|         }
 | |
| 
 | |
|         if (match_network($config['autodiscovery']['nets-exclude'], $host)) {
 | |
|             if ($vdebug || $more_info === true) {
 | |
|                 echo "Excluded by config.php".PHP_EOL.PHP_EOL;
 | |
|             } else {
 | |
|                 echo '|';
 | |
|             }
 | |
|             continue;
 | |
|         }
 | |
|         $test = isPingable($host);
 | |
|         if ($test['result'] === false) {
 | |
|             if ($vdebug || $more_info === true) {
 | |
|                 echo "Unpingable Device $host".PHP_EOL.PHP_EOL;
 | |
|             } else {
 | |
|                 echo '.';
 | |
|             }
 | |
|             continue;
 | |
|         }
 | |
|         if (ip_exists($host)) {
 | |
|             $stats['known']++;
 | |
|             if ($vdebug || $more_info === true) {
 | |
|                 echo "Known Device $host".PHP_EOL;
 | |
|             } else {
 | |
|                 echo '*';
 | |
|             }
 | |
|             continue;
 | |
|         }
 | |
|         foreach (array('udp','tcp') as $transport) {
 | |
|             try {
 | |
|                 addHost(gethostbyaddr($host), '', $config['snmp']['port'], $transport, $config['distributed_poller_group']);
 | |
|                 $stats['added']++;
 | |
|                 if ($vdebug || $more_info === true) {
 | |
|                     echo "Added Device $host".PHP_EOL.PHP_EOL;
 | |
|                 } else {
 | |
|                     echo '+';
 | |
|                 }
 | |
|                 break;
 | |
|             } catch (HostExistsException $e) {
 | |
|                 $stats['known']++;
 | |
|                 if ($vdebug || $more_info === true) {
 | |
|                     echo "Known Device $host".PHP_EOL.PHP_EOL;
 | |
|                 } else {
 | |
|                     echo '*';
 | |
|                 }
 | |
|                 break;
 | |
|             } catch (HostUnreachablePingException $e) {
 | |
|                 if ($vdebug || $more_info === true) {
 | |
|                     echo "Unpingable Device $host".PHP_EOL.PHP_EOL;
 | |
|                 } else {
 | |
|                     echo '.';
 | |
|                 }
 | |
|                 break;
 | |
|             } catch (HostUnreachableException $e) {
 | |
|                 if ($debug || $more_info === true) {
 | |
|                     print_error($e->getMessage() . " over $transport");
 | |
|                     foreach ($e->getReasons() as $reason) {
 | |
|                         echo "  $reason".PHP_EOL;
 | |
|                     }
 | |
|                 }
 | |
|                 if ($transport === 'tcp') {
 | |
|                     // tried both udp and tcp without success
 | |
|                     $stats['failed']++;
 | |
|                     if ($vdebug || $more_info === true) {
 | |
|                         echo "Failed to Add Device $host".PHP_EOL.PHP_EOL;
 | |
|                     } else {
 | |
|                         echo '-';
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     echo PHP_EOL;
 | |
| }
 | |
| 
 | |
| $opts  = getopt('r:d::v::i::n::b::l::h::');
 | |
| $stats = array('count'=> 0, 'known'=>0, 'added'=>0, 'failed'=>0);
 | |
| $start = false;
 | |
| $debug = false;
 | |
| $quiet = 1;
 | |
| $net   = false;
 | |
| 
 | |
| if (isset($opts['h']) || (empty($opts) && (!isset($config['nets']) || empty($config['nets'])))) {
 | |
|     echo 'Usage: '.$argv[0].' -r <CIDR_Range> [-d] [-l] [-h]'.PHP_EOL;
 | |
|     echo '  -r CIDR_Range     CIDR noted IP-Range to scan'.PHP_EOL;
 | |
|     echo '                    This argument is only required if $config[\'nets\'] is not set'.PHP_EOL;
 | |
|     echo '                    Example: 192.168.0.0/24'.PHP_EOL;
 | |
|     echo '                    Example: 192.168.0.0/31 will be treated as an RFC3021 p-t-p network'.PHP_EOL;
 | |
|     echo '                                            with two addresses, 192.168.0.0 and 192.168.0.1'.PHP_EOL;
 | |
|     echo '                    Example: 192.168.0.1/32 will be treated as a single host address'.PHP_EOL;
 | |
|     echo '  -n                Force scan of network address'.PHP_EOL;
 | |
|     echo '  -b                Force scan of broadcast address'.PHP_EOL;
 | |
|     echo '  -d                Enable Debug'.PHP_EOL;
 | |
|     echo '  -v                Enable verbose Debug'.PHP_EOL;
 | |
|     echo '  -i                Provide more information on actions'.PHP_EOL;
 | |
|     echo '  -l                Show Legend'.PHP_EOL;
 | |
|     echo '  -h                Print this text'.PHP_EOL;
 | |
|     exit(0);
 | |
| }
 | |
| if (isset($opts['d']) || isset($opts['v'])) {
 | |
|     if (isset($opts['v'])) {
 | |
|         $vdebug = true;
 | |
|     }
 | |
|     $debug = true;
 | |
| }
 | |
| if (isset($opts['l'])) {
 | |
|     echo '   * = Known Device;   . = Unpingable Device;   + = Added Device;   - = Failed To Add Device;  | = Excluded by config.php'.PHP_EOL;
 | |
| }
 | |
| 
 | |
| if (isset($opts['n'])) {
 | |
|     $force_network = true;
 | |
| }
 | |
| 
 | |
| if (isset($opts['b'])) {
 | |
|     $force_broadcast = true;
 | |
| }
 | |
| 
 | |
| if (isset($opts['i'])) {
 | |
|     $more_info = true;
 | |
| }
 | |
| 
 | |
| if (isset($opts['r'])) {
 | |
|     $net = Net_IPv4::parseAddress($opts['r']);
 | |
|     if (ip2long($net->network) !== false) {
 | |
|         perform_snmp_scan($net, $force_network, $force_broadcast);
 | |
|         echo 'Scanned '.$stats['count'].' IPs, Already known '.$stats['known'].' Devices, Added '.$stats['added'].' Devices, Failed to add '.$stats['failed'].' Devices.'.PHP_EOL;
 | |
|         echo 'Runtime: '.(microtime(true)-$ts).' secs'.PHP_EOL;
 | |
|     } else {
 | |
|         echo 'Could not interpret supplied CIDR noted IP-Range: '.$opts['r'].PHP_EOL;
 | |
|         exit(2);
 | |
|     }
 | |
| } elseif (isset($config['nets']) && !empty($config['nets'])) {
 | |
|     if (!is_array($config['nets'])) {
 | |
|         $config['nets'] = array( $config['nets'] );
 | |
|     }
 | |
|     foreach ($config['nets'] as $subnet) {
 | |
|         $net = Net_IPv4::parseAddress($subnet);
 | |
|         perform_snmp_scan($net, $force_network, $force_broadcast);
 | |
|     }
 | |
|     echo 'Scanned '.$stats['count'].' IPs, Already know '.$stats['known'].' Devices, Added '.$stats['added'].' Devices, Failed to add '.$stats['failed'].' Devices.'.PHP_EOL;
 | |
|     echo 'Runtime: '.(microtime(true)-$ts).' secs'.PHP_EOL;
 | |
| } else {
 | |
|     echo 'Please either add a range argument with \'-r <CIDR_RANGE>\' or define $config[\'nets\'] in your config.php'.PHP_EOL;
 | |
|     exit(2);
 | |
| }
 |