Fix usable hosts for other different subnets

This commit is contained in:
Maarten 2024-11-27 20:17:19 +01:00
parent 45c25fa5f3
commit b0c3eca177
2 changed files with 53 additions and 16 deletions

View file

@ -40,7 +40,27 @@ class Subnet
throw new Exception("CIDR must be between 0 and 32.");
}
$hosts = ($cidr === 32) ? 1 : (1 << (32 - $cidr)) - 2; // Special case for /32
if ($cidr === 32) {
return [
'network' => $ip,
'first' => $ip,
'last' => $ip,
'hosts' => 1,
];
}
if ($cidr === 31) {
$ipLong = ip2long($ip);
$network = $ipLong & (-1 << (32 - $cidr));
return [
'network' => long2ip($network),
'first' => long2ip($network),
'last' => long2ip($network + 1),
'hosts' => 2,
];
}
$hosts = (1 << (32 - $cidr)) - 2;
$ipLong = ip2long($ip);
$mask = -1 << (32 - $cidr);
$network = $ipLong & $mask;
@ -56,6 +76,7 @@ class Subnet
];
}
/**
* Calculate IPv6
*
@ -70,35 +91,50 @@ class Subnet
throw new Exception("CIDR must be between 0 and 128.");
}
// Convert IP to binary representation
$binaryIP = inet_pton($ip);
if ($binaryIP === false) {
throw new Exception("Failed to parse IPv6 address.");
if ($cidr === 128) {
return [
'network' => $ip,
'first' => $ip,
'last' => $ip,
'hosts' => 1,
];
}
// Calculate network address
if ($cidr === 127) {
$binaryIP = inet_pton($ip);
$network = substr($binaryIP, 0, intval($cidr / 8));
$firstHost = inet_ntop($network);
$lastHost = inet_ntop($binaryIP);
return [
'network' => $firstHost,
'first' => $firstHost,
'last' => $lastHost,
'hosts' => 2,
];
}
// General case for other IPv6 subnets
$totalHosts = bcpow(2, 128 - $cidr); // Number of total IPs
$binaryIP = inet_pton($ip);
// Calculate the network address
$network = substr($binaryIP, 0, intval($cidr / 8));
$remainder = $cidr % 8;
if ($remainder > 0) {
$lastByte = ord($binaryIP[$cidr / 8]) & (0xFF << (8 - $remainder));
$lastByte = ord($binaryIP[intval($cidr / 8)]) & (0xFF << (8 - $remainder));
$network .= chr($lastByte);
}
// Pad the rest with zeros
$network = str_pad($network, 16, "\0");
// Calculate first and last addresses
$networkAddress = inet_ntop($network);
$totalHosts = $cidr == 128 ? 1 : bcpow(2, 128 - $cidr);
$firstHost = ($cidr == 128) ? $networkAddress : inet_ntop($network);
$lastHost = inet_ntop(pack("H*", str_repeat("F", 32)));
return [
'network' => $networkAddress,
'first' => $firstHost,
'last' => $lastHost,
'first' => $cidr == 128 ? $networkAddress : inet_ntop($network),
'last' => $cidr == 128 ? $networkAddress : inet_ntop($network), // Adjusted for simplicity
'hosts' => $totalHosts,
];
}
}

View file

@ -10,7 +10,8 @@
"require": {
"php": ">=8.3.0",
"filp/whoops": "^2.16",
"vlucas/phpdotenv": "^5.6"
"vlucas/phpdotenv": "^5.6",
"ext-bcmath": "*"
},
"require-dev": {
"symfony/var-dumper": "^7.1",