Exemple #1
0
/**
 * Trim string and remove paired and/or escaped quotes from string
 *
 * @param string $string Input string
 * @return string Cleaned string
 */
function trim_quotes($string, $flags = OBS_QUOTES_TRIM)
{
    $string = trim($string);
    // basic trim of string
    if (strpos($string, '"') !== FALSE && is_flag_set(OBS_QUOTES_TRIM, $flags)) {
        if (strpos($string, '\\"') !== FALSE) {
            $string = str_replace('\\"', '"', $string);
            // replace escaped quotes
        }
        $quotes = array('["\']');
        foreach ($quotes as $quote) {
            $pattern = '/^(' . $quote . ')(?<value>.*?)(\\1)$/s';
            while (preg_match($pattern, $string, $matches)) {
                $string = $matches['value'];
            }
        }
    }
    return $string;
}
function discover_new_device($hostname, $source = 'xdp', $protocol = NULL, $device = NULL, $snmp_port = 161)
{
    global $config;
    $source = strtolower($source);
    // Check if source is enabled for autodiscovery
    if ($config['autodiscovery'][$source]) {
        $flags = OBS_DNS_ALL;
        if (!$protocol) {
            $protocol = strtoupper($source);
        }
        print_cli_data("Try discovering host", "{$hostname} through {$protocol}", 3);
        // By first detect hostname is IP or domain name (IPv4/6 == 4/6, hostname == FALSE)
        $ip_version = get_ip_version($hostname);
        if ($ip_version) {
            // Hostname is IPv4/IPv6
            $use_ip = TRUE;
            $ip = $hostname;
        } else {
            $use_ip = FALSE;
            // Add "mydomain" configuration if this resolves, converts switch1 -> switch1.mydomain.com
            if (!empty($config['mydomain']) && isDomainResolves($hostname . '.' . $config['mydomain'], $flags)) {
                $hostname .= '.' . $config['mydomain'];
            }
            // Determine v4 vs v6
            $ip = gethostbyname6($hostname, $flags);
            if ($ip) {
                $ip_version = get_ip_version($ip);
                print_debug("Host {$hostname} resolved as {$ip}");
            } else {
                // No DNS records
                print_debug("Host {$hostname} not resolved, autodiscovery fails.");
                return FALSE;
            }
        }
        if ($ip_version == 6) {
            $flags = $flags ^ OBS_DNS_A;
            // Exclude IPv4
        }
        if (isset($config['autodiscovery']['ping_skip']) && $config['autodiscovery']['ping_skip']) {
            $flags = $flags | OBS_PING_SKIP;
            // Add skip pings flag
        }
        if (match_network($ip, $config['autodiscovery']['ip_nets'])) {
            print_debug("Host {$hostname} ({$ip}) founded inside configured nets, trying to add:");
            // By first check if pingable
            $pingable = isPingable($ip, $flags);
            if (!$pingable && (isset($config['autodiscovery']['ping_skip']) && $config['autodiscovery']['ping_skip'])) {
                $flags = $flags | OBS_PING_SKIP;
                // Add skip pings flag if allowed in config
                $pingable = TRUE;
            }
            if ($pingable) {
                // Check if device duplicated by IP
                $ip = $ip_version == 4 ? $ip : Net_IPv6::uncompress($ip, TRUE);
                $db = dbFetchRow('SELECT D.`hostname` FROM ipv' . $ip_version . '_addresses AS A
                         LEFT JOIN `ports`   AS P ON A.`port_id`   = P.`port_id`
                         LEFT JOIN `devices` AS D ON D.`device_id` = P.`device_id`
                         WHERE D.`disabled` = 0 AND A.`ipv' . $ip_version . '_address` = ?', array($ip));
                if ($db) {
                    print_debug('Already have device ' . $db['hostname'] . " with IP {$ip}");
                    return FALSE;
                }
                // Detect snmp transport, net-snmp needs udp6 for ipv6
                $snmp_transport = $ip_version == 4 ? 'udp' : 'udp6';
                $new_device = detect_device_snmpauth($ip, $snmp_port, $snmp_transport);
                if ($new_device) {
                    if ($use_ip) {
                        // Detect FQDN hostname
                        // by sysName
                        $snmphost = snmp_get($new_device, 'sysName.0', '-Oqv', 'SNMPv2-MIB');
                        if ($snmphost) {
                            $snmp_ip = gethostbyname6($snmphost, $flags);
                        }
                        if ($snmp_ip == $ip) {
                            $hostname = $snmphost;
                        } else {
                            // by PTR
                            $ptr = gethostbyaddr6($ip);
                            if ($ptr) {
                                $ptr_ip = gethostbyname6($ptr, $flags);
                            }
                            if ($ptr && $ptr_ip == $ip) {
                                $hostname = $ptr;
                            } else {
                                if ($config['autodiscovery']['require_hostname']) {
                                    print_debug("Device IP {$ip} does not seem to have FQDN.");
                                    return FALSE;
                                } else {
                                    $hostname = $ip_version == 4 ? $ip : Net_IPv6::compress($hostname, TRUE);
                                    // Always use compressed IPv6 name
                                }
                            }
                        }
                        print_debug("Device IP {$ip} linked to FQDN name: {$hostname}");
                    }
                    $new_device['hostname'] = $hostname;
                    if (!check_device_duplicated($new_device)) {
                        $snmp_v3 = array();
                        if ($new_device['snmp_version'] === 'v3') {
                            $snmp_v3['snmp_authlevel'] = $new_device['snmp_authlevel'];
                            $snmp_v3['snmp_authname'] = $new_device['snmp_authname'];
                            $snmp_v3['snmp_authpass'] = $new_device['snmp_authpass'];
                            $snmp_v3['snmp_authalgo'] = $new_device['snmp_authalgo'];
                            $snmp_v3['snmp_cryptopass'] = $new_device['snmp_cryptopass'];
                            $snmp_v3['snmp_cryptoalgo'] = $new_device['snmp_cryptoalgo'];
                        }
                        $remote_device_id = createHost($new_device['hostname'], $new_device['snmp_community'], $new_device['snmp_version'], $new_device['snmp_port'], $new_device['snmp_transport'], $snmp_v3);
                        if ($remote_device_id) {
                            if (is_flag_set(OBS_PING_SKIP, $flags)) {
                                set_entity_attrib('device', $remote_device_id, 'ping_skip', 1);
                            }
                            $remote_device = device_by_id_cache($remote_device_id, 1);
                            if ($port) {
                                humanize_port($port);
                                log_event("Device autodiscovered through {$protocol} on " . $device['hostname'] . " (port " . $port['port_label'] . ")", $remote_device_id, 'port', $port['port_id']);
                            } else {
                                log_event("Device autodiscovered through {$protocol} on " . $device['hostname'], $remote_device_id, $protocol);
                            }
                            //array_push($GLOBALS['devices'], $remote_device); // createHost() already puth this
                            return $remote_device_id;
                        }
                    }
                }
            }
        } else {
            print_debug("IP {$ip} ({$hostname}) not permitted inside \$config['autodiscovery']['ip_nets'] in config.php");
        }
        print_debug('Autodiscovery for host ' . $hostname . ' failed.');
    } else {
        print_debug('Autodiscovery for protocol ' . $protocol . ' disabled.');
    }
    return FALSE;
}
Exemple #3
0
 //    lowerWarning(1),
 //    upperWarning(2),
 //    upperCritical(3),
 // }
 $options = array();
 $limits_flags = base_convert($entry['externalSensorEnabledThresholds'], 16, 10);
 if (is_flag_set(bindec(10000000), $limits_flags)) {
     $options['limit_low'] = $entry['externalSensorLowerCriticalThreshold'] * $scale;
 }
 if (is_flag_set(bindec(1000000), $limits_flags)) {
     $options['limit_low_warn'] = $entry['externalSensorLowerWarningThreshold'] * $scale;
 }
 if (is_flag_set(bindec(100000), $limits_flags)) {
     $options['limit_high_warn'] = $entry['externalSensorUpperWarningThreshold'] * $scale;
 }
 if (is_flag_set(bindec(10000), $limits_flags)) {
     $options['limit_high'] = $entry['externalSensorUpperCriticalThreshold'] * $scale;
 }
 // Detect type & unit
 $unit = array();
 if (isset($oid_units[$entry['externalSensorUnits']])) {
     $unit = $oid_units[$entry['externalSensorUnits']];
 } else {
     // Other sensors based on SensorTypeEnumeration
     switch ($entry['externalSensorType']) {
         case 'powerFactor':
             $unit = array('type' => 'powerfactor');
             break;
             // Status sensors
         // Status sensors
         case 'onOff':
function auth_user_level_permissions($user_level)
{
    $user = array('level' => -1, 'permission' => 0);
    // level -1 equals "not exist" user
    if (is_numeric($user_level)) {
        krsort($GLOBALS['config']['user_level']);
        // Order levels from max to low
        foreach ($GLOBALS['config']['user_level'] as $level => $entry) {
            if ($user_level >= $level) {
                $user['level'] = $level;
                // Real (normalized) user level
                $user['permission'] = $entry['permission'];
                break;
            }
        }
    }
    // Convert permission flags to Boolean permissions
    $user['permission_admin'] = is_flag_set(OBS_PERMIT_ALL, $user['permission'], TRUE);
    // Administrator
    $user['permission_edit'] = is_flag_set(OBS_PERMIT_EDIT, $user['permission']);
    // Limited Edit
    $user['permission_secure'] = is_flag_set(OBS_PERMIT_SECURE, $user['permission']);
    // Secure Read
    $user['permission_read'] = is_flag_set(OBS_PERMIT_READ, $user['permission']);
    // Global Read
    $user['permission_access'] = is_flag_set(OBS_PERMIT_ACCESS, $user['permission']);
    // Access (logon) allowed
    // Set quick boolen flag that user limited
    $user['limited'] = !$user['permission_read'] && !$user['permission_secure'] && !$user['permission_edit'] && !$user['permission_admin'];
    return $user;
}
/**
 * Checks device availability by icmp echo response
 * If flag OBS_PING_SKIP passed, pings skipped and returns 0.001 (1ms)
 *
 * @param string $hostname Device hostname or IP address
 * @param int Flags. Supported OBS_DNS_A, OBS_DNS_AAAA and OBS_PING_SKIP
 * @return float Average response time for used retries count (default retries is 3)
 */
function isPingable($hostname, $flags = OBS_DNS_ALL)
{
    global $config;
    $ping_debug = isset($config['ping']['debug']) && $config['ping']['debug'];
    $try_a = is_flag_set(OBS_DNS_A, $flags);
    if (is_flag_set(OBS_PING_SKIP, $flags)) {
        return 0.001;
        // Ping is skipped, just return 1ms
    }
    $timeout = isset($config['ping']['timeout']) ? (int) $config['ping']['timeout'] : 500;
    if ($timeout < 50) {
        $timeout = 50;
    } else {
        if ($timeout > 2000) {
            $timeout = 2000;
        }
    }
    $retries = isset($config['ping']['retries']) ? (int) $config['ping']['retries'] : 3;
    if ($retries < 1) {
        $retries = 3;
    } else {
        if ($retries > 10) {
            $retries = 10;
        }
    }
    $sleep = floor(1000000 / $retries);
    // interval between retries, max 1 sec
    if ($ip_version = get_ip_version($hostname)) {
        // Ping by IP
        if ($ip_version === 6) {
            $cmd = $config['fping6'] . " -t {$timeout} -c 1 -q {$hostname} 2>&1";
        } else {
            if (!$try_a) {
                if ($ping_debug) {
                    logfile('debug.log', __FUNCTION__ . "() | DEVICE: {$hostname} | Passed IPv4 address but device use IPv6 transport");
                }
                print_debug('Into function ' . __FUNCTION__ . '() passed IPv4 address (' . $hostname . 'but device use IPv6 transport');
                return 0;
            }
            // Forced check for actual IPv4 address
            $cmd = $config['fping'] . " -t {$timeout} -c 1 -q {$hostname} 2>&1";
        }
    } else {
        // First try IPv4
        $ip = $try_a ? gethostbyname($hostname) : FALSE;
        // Do not check IPv4 if transport IPv6
        if ($ip && $ip != $hostname) {
            $cmd = $config['fping'] . " -t {$timeout} -c 1 -q {$ip} 2>&1";
        } else {
            $ip = gethostbyname6($hostname, OBS_DNS_AAAA);
            // Second try IPv6
            if ($ip) {
                $cmd = $config['fping6'] . " -t {$timeout} -c 1 -q {$ip} 2>&1";
            } else {
                // No DNS records
                if ($ping_debug) {
                    logfile('debug.log', __FUNCTION__ . "() | DEVICE: {$hostname} | NO DNS record found");
                }
                return 0;
            }
        }
    }
    for ($i = 1; $i <= $retries; $i++) {
        $output = external_exec($cmd);
        if ($GLOBALS['exec_status']['exitcode'] === 0) {
            // normal $output = '8.8.8.8 : xmt/rcv/%loss = 1/1/0%, min/avg/max = 1.21/1.21/1.21'
            $tmp = explode('/', $output);
            $ping = $tmp[7];
            if (!$ping) {
                $ping = 0.001;
            }
            // Protection from zero (exclude false status)
        } else {
            $ping = 0;
        }
        if ($ping) {
            break;
        }
        if ($ping_debug) {
            logfile('debug.log', __FUNCTION__ . "() | DEVICE: {$hostname} | FPING OUT ({$i}): " . $output[0]);
            if ($i == $retries) {
                $mtr = $config['mtr'] . " -r -n -c 5 {$ip}";
                logfile('debug.log', __FUNCTION__ . "() | DEVICE: {$hostname} | MTR OUT:\n" . external_exec($mtr));
            }
        }
        if ($i < $retries) {
            usleep($sleep);
        }
    }
    return $ping;
}
Exemple #6
0
function snmpwalk_cache_threepart_oid($device, $oid, $array, $mib = NULL, $mibdir = NULL, $flags = OBS_SNMP_ALL)
{
    $output = 'QUs';
    if (is_flag_set(OBS_SNMP_NUMERIC_INDEX, $flags)) {
        $output .= 'b';
    }
    if (is_flag_set(OBS_SNMP_NUMERIC, $flags)) {
        $output .= 'n';
    }
    if (is_flag_set(OBS_SNMP_ENUM, $flags)) {
        $output .= 'e';
    }
    if (is_flag_set(OBS_SNMP_HEX, $flags)) {
        $output .= 'x';
    }
    $data = snmp_walk($device, $oid, "-O{$output}", $mib, $mibdir, $flags);
    foreach (explode("\n", $data) as $entry) {
        list($oid, $value) = explode('=', $entry, 2);
        $oid = trim($oid);
        $value = trim_quotes($value, $flags);
        if (strpos($oid, '"') !== FALSE) {
            // Example: jnxVpnPwLocalSiteId.l2Circuit."ge-0/1/1.0".621
            $oid_part = $oid;
            $oid_parts = array();
            do {
                if (preg_match('/^"([^"]*)"(?:\\.(.+))?/', $oid_part, $matches)) {
                    // Part with stripes
                    $oid_parts[] = $matches[1];
                    $oid_part = $matches[2];
                    // Next part
                } else {
                    $matches = explode('.', $oid_part, 2);
                    $oid_parts[] = $matches[0];
                    $oid_part = $matches[1];
                    // Next part
                }
                // print_vars($matches);
            } while (strlen($oid_part) > 0);
            // print_vars($oid_parts);
            $oid = $oid_parts[0];
            $first = $oid_parts[1];
            $second = $oid_parts[2];
            $third = $oid_parts[3];
        } else {
            // Simple, not always correct
            $oid_parts = explode('.', $oid);
            $oid = array_shift($oid_parts);
            $first = array_shift($oid_parts);
            $second = array_shift($oid_parts);
            $third = implode('.', $oid_parts);
            //list($oid, $first, $second, $third) = explode('.', $oid);
        }
        print_debug("{$entry} || {$oid} || {$first} || {$second} || {$third}");
        if (isset($oid) && isset($first) && isset($second) && isset($third) && is_valid_snmp_value($value)) {
            $array[$first][$second][$third][$oid] = $value;
        }
    }
    return $array;
}
Exemple #7
0
function gethostbynamel6($host, $flags = OBS_DNS_ALL)
{
    // get AAAA records for $host,
    // if $try_a is true, if AAAA fails, it tries for A
    // results are returned in an array of ips found matching type
    // otherwise returns FALSE
    $ip6 = array();
    $ip4 = array();
    // First try /etc/hosts
    $etc = ipFromEtcHosts($host);
    $try_a = is_flag_set(OBS_DNS_A, $flags);
    if ($try_a === TRUE) {
        if ($etc && strstr($etc, '.')) {
            $ip4[] = $etc;
        }
        // Separate A and AAAA queries, see: https://www.mail-archive.com/observium@observium.org/msg09239.html
        $dns = dns_get_record($host, DNS_A);
        if (!is_array($dns)) {
            $dns = array();
        }
        $dns6 = dns_get_record($host, DNS_AAAA);
        if (is_array($dns6)) {
            $dns = array_merge($dns, $dns6);
        }
    } else {
        if ($etc && strstr($etc, ':')) {
            $ip6[] = $etc;
        }
        $dns = dns_get_record($host, DNS_AAAA);
    }
    foreach ($dns as $record) {
        switch ($record['type']) {
            case 'A':
                $ip4[] = $record['ip'];
                break;
            case 'AAAA':
                $ip6[] = $record['ipv6'];
                break;
        }
    }
    if ($try_a && count($ip4)) {
        // Merge ipv4 & ipv6
        $ip6 = array_merge($ip4, $ip6);
    }
    if (count($ip6)) {
        return $ip6;
    }
    return FALSE;
}