/** * 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; }
// 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; }
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; }
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; }