From 6e9af3bb2973cf34e6d5fa2fb86420e2a9ce95af Mon Sep 17 00:00:00 2001 From: Tyler Cosgrove Date: Sat, 20 Apr 2019 04:29:19 +1200 Subject: [PATCH] Add getSubnet util to Grav\Common\Utils (#2465) --- system/src/Grav/Common/Utils.php | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index 42f1fbe69..c254009e5 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -1469,4 +1469,44 @@ abstract class Utils return $string; } + + /** + * Find the subnet of an ip with CIDR prefix size + * + * @param string $ip + * @param int $prefix + * + * @return string + * @throws \InvalidArgumentException if provided an invalid IP + */ + public static function getSubnet($ip, $prefix = 64) + { + if (!filter_var($ip, FILTER_VALIDATE_IP)) { + throw new \InvalidArgumentException('Invalid IP: ' . $ip); + } + + // Packed representation of IP + $ip = inet_pton($ip); + + // Maximum netmask length = same as packed address + $len = 8*strlen($ip); + if ($prefix > $len) $prefix = $len; + + $mask = str_repeat('f', $prefix>>2); + + switch($prefix & 3) + { + case 3: $mask .= 'e'; break; + case 2: $mask .= 'c'; break; + case 1: $mask .= '8'; break; + } + $mask = str_pad($mask, $len>>2, '0'); + + // Packed representation of netmask + $mask = pack('H*', $mask); + // Bitwise - Take all bits that are both 1 to generate subnet + $subnet = inet_ntop($ip & $mask); + + return $subnet; + } }