'unauthorized']); exit; } header('Content-Type: application/json; charset=utf-8'); // === Logging-Setup === $logDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'logs'; if (!is_dir($logDir)) { @mkdir($logDir, 0755, true); } $logFile = $logDir . DIRECTORY_SEPARATOR . 'snmp_api.log'; function log_msg(string $msg): void { global $logFile; $timestamp = date('Y-m-d H:i:s'); @file_put_contents($logFile, "[$timestamp] $msg\n", FILE_APPEND); } function rotate_log_if_needed(): void { global $logFile; $maxSize = 500 * 1024; // 500 KB if (file_exists($logFile) && filesize($logFile) > $maxSize) { @rename($logFile, $logFile . '.old'); log_msg('=== Log rotiert ==='); } } $configPath = __DIR__ . '/../../config/config.php'; if (!is_readable($configPath)) { echo json_encode(['error' => 'config_not_found']); exit; } $config = require $configPath; $snmp = $config['snmp'] ?? []; rotate_log_if_needed(); // === Cache-Logik (Datei) === $cacheDir = sys_get_temp_dir(); $cacheFile = $cacheDir . DIRECTORY_SEPARATOR . 'snmp_status_cache.json'; $cacheTTL = 10; // Sekunden if (file_exists($cacheFile)) { $cacheAge = time() - filemtime($cacheFile); if ($cacheAge < $cacheTTL) { $cached = file_get_contents($cacheFile); if ($cached !== false) { echo $cached; exit; } } } // === SNMP Setup === $host = $snmp['host'] ?? '127.0.0.1'; $community = $snmp['community'] ?? 'public'; // Timeout von Sekunden in Mikrosekunden umrechnen (wichtig für PHP snmp Funktionen) $timeoutSec = (int)($snmp['timeout'] ?? 2); $timeoutMicro = $timeoutSec * 1_000_000; $retries = (int)($snmp['retries'] ?? 1); if (!function_exists('snmpget')) { echo json_encode(['error' => 'snmp_extension_missing']); exit; } // Grundeinstellungen snmp_set_oid_output_format(SNMP_OID_OUTPUT_NUMERIC); // Hilfsfunktion: sichere snmpget-Rückgabe function sget(string $host, string $community, string $oid, int $timeout, int $retries) { $v = @snmpget($host, $community, $oid, $timeout, $retries); if ($v === false || $v === null) return null; return is_string($v) ? trim($v) : $v; } // --- 1. Uptime --- // Wir deaktivieren quick_print, damit wir das Format "Timeticks: (12345) 1 day..." erhalten. // Nur so können wir die echten Ticks in der Klammer zuverlässig parsen. snmp_set_quick_print(false); $uptimeOid = $snmp['oids']['uptime'] ?? '1.3.6.1.2.1.1.3.0'; $uptimeRaw = @sget($host, $community, $uptimeOid, $timeoutMicro, $retries); $upticks = null; // Regex sucht nach Zahl in Klammern: (12345678) if ($uptimeRaw && preg_match('/\((.*?)\)/', (string)$uptimeRaw, $matches)) { $upticks = (int)$matches[1]; } function format_uptime(?int $ticks): ?string { if ($ticks === null) return null; $seconds = (int)floor($ticks / 100); $days = intdiv($seconds, 86400); $seconds -= $days * 86400; $hours = intdiv($seconds, 3600); $seconds -= $hours * 3600; $minutes = intdiv($seconds, 60); $seconds -= $minutes * 60; $parts = []; if ($days) $parts[] = $days . ' Tage'; $parts[] = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); return implode(', ', $parts); } $uptimeStr = format_uptime($upticks); // Für den Rest aktivieren wir quick_print wieder, um "saubere" Werte zu bekommen snmp_set_quick_print(true); // --- 2. CPU (Walk über alle Kerne) --- $cpuTable = $snmp['oids']['cpu_table'] ?? '1.3.6.1.2.1.25.3.3.1.2'; $cpuValues = @snmpwalk($host, $community, $cpuTable, $timeoutMicro, $retries); $cpuUsage = 0; if (is_array($cpuValues) && count($cpuValues) > 0) { $totalLoad = 0; $coreCount = 0; foreach ($cpuValues as $val) { $v = (int)filter_var($val, FILTER_SANITIZE_NUMBER_INT); $totalLoad += $v; $coreCount++; } if ($coreCount > 0) { $cpuUsage = round($totalLoad / $coreCount, 2); } } // --- 3. Storage (Disk & RAM) --- $descrOid = $snmp['oids']['storage_descr'] ?? '1.3.6.1.2.1.25.2.3.1.3'; $unitsOid = $snmp['oids']['storage_units'] ?? '1.3.6.1.2.1.25.2.3.1.4'; $sizeOid = $snmp['oids']['storage_size'] ?? '1.3.6.1.2.1.25.2.3.1.5'; $usedOid = $snmp['oids']['storage_used'] ?? '1.3.6.1.2.1.25.2.3.1.6'; $descrWalk = @snmprealwalk($host, $community, $descrOid, $timeoutMicro, $retries); $unitsWalk = @snmprealwalk($host, $community, $unitsOid, $timeoutMicro, $retries); $sizeWalk = @snmprealwalk($host, $community, $sizeOid, $timeoutMicro, $retries); $usedWalk = @snmprealwalk($host, $community, $usedOid, $timeoutMicro, $retries); $diskPercent = null; $memPercent = null; $storageEntries = []; // Fallback-Liste if (is_array($descrWalk)) { foreach ($descrWalk as $descrOidFull => $descrRaw) { if (!preg_match('/\.(\d+)$/', $descrOidFull, $m)) continue; $idx = $m[1]; // Bereinigen $descr = trim(str_ireplace('STRING:', '', (string)$descrRaw), ' "'); // Helper zum Finden der Werte $findVal = function($walkArr, $idx) { if(!is_array($walkArr)) return null; foreach ($walkArr as $oid => $val) { if (preg_match('/\.(\d+)$/', $oid, $m2) && $m2[1] === $idx) { return (int)filter_var($val, FILTER_SANITIZE_NUMBER_INT); } } return null; }; $units = $findVal($unitsWalk, $idx); $size = $findVal($sizeWalk, $idx); $used = $findVal($usedWalk, $idx); if ($size === null || $units === null || $used === null || $size === 0) continue; $totalBytes = $size * $units; $usedBytes = $used * $units; $percent = ($totalBytes > 0) ? ($usedBytes / $totalBytes) * 100 : 0; $storageEntries[] = ['idx' => $idx, 'descr' => $descr, 'percent' => $percent, 'totalGB' => $totalBytes / (1024**3)]; $lower = strtolower($descr); // DISK C: oder Root if ($diskPercent === null) { if (str_starts_with($lower, 'c:') || str_starts_with($lower, 'c:\\') || $lower === '/' || str_contains($lower, 'root')) { $diskPercent = $percent; } } // RAM if ($memPercent === null) { if (str_contains($lower, 'physical memory') || str_contains($lower, 'ram')) { $memPercent = $percent; } } } } // Fallback Disk: Größter Speicher > 5GB if ($diskPercent === null && count($storageEntries) > 0) { usort($storageEntries, fn($a, $b) => $b['totalGB'] <=> $a['totalGB']); foreach($storageEntries as $entry) { if ($entry['totalGB'] > 5) { $diskPercent = $entry['percent']; break; } } } // --- 4. Hostname --- $hostnameOid = '1.3.6.1.2.1.1.5.0'; $hostname = @sget($host, $community, $hostnameOid, $timeoutMicro, $retries); if($hostname) $hostname = trim(str_ireplace('STRING:', '', $hostname), ' "'); // --- Ergebnis --- $result = [ 'hostname' => $hostname ?? 'n/a', 'uptime' => $uptimeStr, 'upticks' => $upticks, 'cpu_usage' => $cpuUsage, 'memory_usage' => $memPercent !== null ? round($memPercent, 2) : 0, 'disk_usage_c' => $diskPercent !== null ? round($diskPercent, 2) : 0, 'last_update' => time(), ]; log_msg('RESULT: UptimeRaw='.($uptimeRaw??'null').' CPU=' . $result['cpu_usage'] . ' Mem=' . $result['memory_usage']); $resultJson = json_encode($result); @file_put_contents($cacheFile, $resultJson); echo $resultJson;