222 lines
7.8 KiB
PHP
222 lines
7.8 KiB
PHP
<?php
|
|
use App\Database;
|
|
use App\Repository\KeaHostMetadataRepository;
|
|
use App\Repository\KeaHostRepository;
|
|
|
|
$module = modules()->get('kea');
|
|
$settings = modules()->settings('kea');
|
|
$metadataFallback = is_array($module['metadata_db_defaults'] ?? null) ? $module['metadata_db_defaults'] : [];
|
|
$metadataConfig = is_array($settings['metadata_db'] ?? null)
|
|
? array_replace($metadataFallback, $settings['metadata_db'])
|
|
: $metadataFallback;
|
|
$fallback = $module['db_defaults'] ?? [];
|
|
$error = null;
|
|
$notice = null;
|
|
$groups = [];
|
|
$availableIpsByGroup = [];
|
|
$usedIps = [];
|
|
|
|
try {
|
|
if (empty($metadataConfig['driver']) || empty($metadataConfig['dbname'])) {
|
|
throw new RuntimeException('Nexus DHCP Zusatzdatenbank ist nicht konfiguriert.');
|
|
}
|
|
|
|
$metadataRepo = new KeaHostMetadataRepository(Database::createFromArray($metadataConfig));
|
|
$metadataRepo->ensureSchema();
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$action = (string)($_POST['action'] ?? '');
|
|
if ($action === 'save_group') {
|
|
$metadataRepo->saveGroup(
|
|
(string)($_POST['name'] ?? ''),
|
|
(string)($_POST['description'] ?? ''),
|
|
(string)($_POST['parent_name'] ?? '')
|
|
);
|
|
$notice = 'Gruppe gespeichert.';
|
|
} elseif ($action === 'add_range') {
|
|
$metadataRepo->addRange(
|
|
(string)($_POST['group_name'] ?? ''),
|
|
(string)($_POST['start_ip'] ?? ''),
|
|
(string)($_POST['end_ip'] ?? '')
|
|
);
|
|
$notice = 'IP-Bereich gespeichert.';
|
|
}
|
|
}
|
|
|
|
$groups = $metadataRepo->listGroupsWithRanges();
|
|
$keaRepo = new KeaHostRepository(modules()->modulePdo('kea', $fallback), $metadataRepo);
|
|
$usedIps = array_merge($keaRepo->usedIpAddresses(), $metadataRepo->desiredIps());
|
|
$availableIpsByGroup = $metadataRepo->availableIpsByGroup($usedIps, 4096);
|
|
} catch (Throwable $e) {
|
|
$error = $e->getMessage();
|
|
}
|
|
|
|
$usedIpLookup = array_flip(array_filter(array_map('strval', $usedIps)));
|
|
$matrixForGroup = static function (array $group) use ($usedIpLookup): array {
|
|
$dots = [];
|
|
foreach (($group['ranges'] ?? []) as $range) {
|
|
$start = ip2long((string)($range['start_ip'] ?? ''));
|
|
$end = ip2long((string)($range['end_ip'] ?? ''));
|
|
if ($start === false || $end === false) {
|
|
continue;
|
|
}
|
|
for ($ip = $start; $ip <= $end && count($dots) < 512; $ip++) {
|
|
$address = long2ip($ip);
|
|
if ($address === false) {
|
|
continue;
|
|
}
|
|
$dots[] = [
|
|
'ip' => $address,
|
|
'used' => isset($usedIpLookup[$address]),
|
|
];
|
|
}
|
|
}
|
|
|
|
return $dots;
|
|
};
|
|
?>
|
|
<section class="kea-page">
|
|
<div class="section-head">
|
|
<div>
|
|
<h2 class="section-title">KEA Gruppen</h2>
|
|
<p>Gruppen und IP-Bereiche fuer DHCP-Reservierungen.</p>
|
|
</div>
|
|
<a class="nav-link" href="/module/kea">Zurueck</a>
|
|
</div>
|
|
|
|
<?php if ($error): ?>
|
|
<div class="kea-message kea-message--error" role="alert">
|
|
<strong>Fehler</strong>
|
|
<p><?= e($error) ?></p>
|
|
</div>
|
|
<?php elseif ($notice): ?>
|
|
<div class="kea-message kea-message--success"><?= e($notice) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<div class="kea-panel">
|
|
<div class="kea-panel__head">
|
|
<div>
|
|
<span class="pill">Gruppe</span>
|
|
<h3>Gruppe anlegen</h3>
|
|
</div>
|
|
</div>
|
|
<form method="post" class="kea-edit-form">
|
|
<input type="hidden" name="action" value="save_group">
|
|
<label class="setup-field">
|
|
<span>Name</span>
|
|
<input type="text" name="name" required>
|
|
</label>
|
|
<label class="setup-field">
|
|
<span>Beschreibung</span>
|
|
<input type="text" name="description">
|
|
</label>
|
|
<label class="setup-field">
|
|
<span>Uebergeordnete Gruppe</span>
|
|
<select name="parent_name">
|
|
<option value="">Keine</option>
|
|
<?php foreach ($groups as $group): ?>
|
|
<option value="<?= e((string)$group['name']) ?>"><?= e((string)$group['name']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
<div class="setup-actions kea-edit-form__wide">
|
|
<button class="cta-button" type="submit">Gruppe speichern</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="kea-panel">
|
|
<div class="kea-panel__head">
|
|
<div>
|
|
<span class="pill">IP-Bereich</span>
|
|
<h3>Bereich zuweisen</h3>
|
|
</div>
|
|
</div>
|
|
<form method="post" class="kea-edit-form">
|
|
<input type="hidden" name="action" value="add_range">
|
|
<label class="setup-field">
|
|
<span>Gruppe</span>
|
|
<select name="group_name" required>
|
|
<option value="">Bitte waehlen</option>
|
|
<?php foreach ($groups as $group): ?>
|
|
<option value="<?= e((string)$group['name']) ?>"><?= e((string)$group['name']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
<label class="setup-field">
|
|
<span>Start-IP</span>
|
|
<input type="text" name="start_ip" placeholder="192.168.178.50" required>
|
|
</label>
|
|
<label class="setup-field">
|
|
<span>End-IP</span>
|
|
<input type="text" name="end_ip" placeholder="192.168.178.99" required>
|
|
</label>
|
|
<div class="setup-actions kea-edit-form__wide">
|
|
<button class="cta-button" type="submit">Bereich speichern</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="kea-panel">
|
|
<div class="kea-panel__head">
|
|
<div>
|
|
<span class="pill">Uebersicht</span>
|
|
<h3>Gruppen und freie IPs</h3>
|
|
</div>
|
|
</div>
|
|
<div class="kea-table-wrap">
|
|
<table class="kea-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Gruppe</th>
|
|
<th>Untergruppe von</th>
|
|
<th>Beschreibung</th>
|
|
<th>Bereiche</th>
|
|
<th>Freie IPs</th>
|
|
<th>Matrix</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if ($groups === []): ?>
|
|
<tr><td colspan="6" class="kea-empty">Noch keine Gruppen definiert.</td></tr>
|
|
<?php else: ?>
|
|
<?php foreach ($groups as $group): ?>
|
|
<?php $available = $availableIpsByGroup[(string)$group['name']] ?? []; ?>
|
|
<tr>
|
|
<td><?= e((string)$group['name']) ?></td>
|
|
<td><?= e((string)($group['parent_name'] ?: '-')) ?></td>
|
|
<td><?= e((string)($group['description'] ?? '-')) ?></td>
|
|
<td>
|
|
<?php if (($group['ranges'] ?? []) === []): ?>
|
|
<span class="muted">Kein Bereich</span>
|
|
<?php else: ?>
|
|
<?php foreach ($group['ranges'] as $range): ?>
|
|
<div class="mono"><?= e((string)$range['start_ip']) ?> - <?= e((string)$range['end_ip']) ?></div>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= e((string)count($available)) ?></td>
|
|
<td>
|
|
<?php $matrix = $matrixForGroup($group); ?>
|
|
<?php if ($matrix === []): ?>
|
|
<span class="muted">Kein Bereich</span>
|
|
<?php else: ?>
|
|
<div class="ip-matrix" aria-label="IP Matrix fuer <?= e((string)$group['name']) ?>">
|
|
<?php foreach ($matrix as $dot): ?>
|
|
<span
|
|
class="ip-dot <?= $dot['used'] ? 'is-used' : 'is-free' ?>"
|
|
title="<?= e((string)$dot['ip']) ?> · <?= $dot['used'] ? 'belegt' : 'frei' ?>"
|
|
></span>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|