122 lines
3.4 KiB
PHP
122 lines
3.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Domovoy\Controllers;
|
|
|
|
use Psr\Http\Message\ResponseInterface;
|
|
use Psr\Http\Message\ServerRequestInterface;
|
|
|
|
class NetworkRangeController
|
|
{
|
|
private \Domovoy\Repositories\NetworkRangeRepository $repository;
|
|
|
|
public function __construct(\Domovoy\Repositories\NetworkRangeRepository $repository)
|
|
{
|
|
$this->repository = $repository;
|
|
}
|
|
|
|
public function create(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
|
{
|
|
$data = $request->getParsedBody();
|
|
$name = trim($data['name'] ?? '');
|
|
$cidr = trim($data['cidr'] ?? '');
|
|
|
|
if ($name === '' || $cidr === '') {
|
|
$response->getBody()->write('Name and CIDR are required');
|
|
return $response->withStatus(400);
|
|
}
|
|
|
|
// Basic CIDR validation
|
|
if (!$this->isValidCidr($cidr)) {
|
|
$response->getBody()->write('Invalid CIDR format');
|
|
return $response->withStatus(400);
|
|
}
|
|
|
|
$range = new \Domovoy\Models\NetworkRange();
|
|
$range->name = $name;
|
|
$range->cidr = $cidr;
|
|
$range->enabled = true;
|
|
$this->repository->save($range);
|
|
|
|
return $response
|
|
->withHeader('Location', '/discovery')
|
|
->withStatus(302);
|
|
}
|
|
|
|
public function toggle(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
|
{
|
|
$data = $request->getParsedBody();
|
|
$id = $data['id'] ?? null;
|
|
|
|
if ($id !== null) {
|
|
$range = $this->repository->findById((int)$id);
|
|
if ($range !== null) {
|
|
$range->enabled = !$range->enabled;
|
|
$this->repository->save($range);
|
|
}
|
|
}
|
|
|
|
return $response
|
|
->withHeader('Location', '/discovery')
|
|
->withStatus(302);
|
|
}
|
|
|
|
public function delete(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
|
{
|
|
$data = $request->getParsedBody();
|
|
$id = $data['id'] ?? null;
|
|
|
|
if ($id !== null) {
|
|
$this->repository->delete((int)$id);
|
|
}
|
|
|
|
return $response
|
|
->withHeader('Location', '/discovery')
|
|
->withStatus(302);
|
|
}
|
|
|
|
private function isValidCidr(string $cidr): bool
|
|
{
|
|
if (!preg_match('#^(\d+\.\d+\.\d+\.\d+)/(\d{1,2})$#', $cidr, $matches)) {
|
|
return false;
|
|
}
|
|
|
|
$ip = $matches[1];
|
|
$maskInt = (int)$matches[2];
|
|
|
|
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
|
return false;
|
|
}
|
|
|
|
if ($maskInt < 8 || $maskInt > 32) {
|
|
return false;
|
|
}
|
|
|
|
$long = ip2long($ip);
|
|
if ($long === false) {
|
|
return false;
|
|
}
|
|
|
|
$value = (int)sprintf('%u', $long);
|
|
return $this->isInRange($value, '10.0.0.0', 8)
|
|
|| $this->isInRange($value, '172.16.0.0', 12)
|
|
|| $this->isInRange($value, '192.168.0.0', 16)
|
|
|| $this->isInRange($value, '169.254.0.0', 16)
|
|
|| $this->isInRange($value, '127.0.0.0', 8);
|
|
}
|
|
|
|
private function isInRange(int $ip, string $network, int $mask): bool
|
|
{
|
|
$networkLong = ip2long($network);
|
|
if ($networkLong === false) {
|
|
return false;
|
|
}
|
|
|
|
$networkValue = (int)sprintf('%u', $networkLong);
|
|
$maskValue = (0xFFFFFFFF << (32 - $mask)) & 0xFFFFFFFF;
|
|
|
|
return ($ip & $maskValue) === ($networkValue & $maskValue);
|
|
}
|
|
}
|