public static function cidrMatch($ip, $range)
    {
        if (strpos($range, '/') === false) {
            $bits = null;
            $subnet = $range;
        } else {
            list($subnet, $bits) = explode('/', $range);
        }

        $ip = inet_pton($ip);
        $subnet = inet_pton($subnet);
        if ($ip === false || $subnet === false) {
            return false;
        }

        if (strlen($ip) > strlen($subnet)) {
            $subnet = str_pad($subnet, strlen($ip), chr(0), STR_PAD_LEFT);
        } elseif (strlen($subnet) > strlen($ip)) {
            $ip = str_pad($ip, strlen($subnet), chr(0), STR_PAD_LEFT);
        }

        if ($bits === null) {
            return ($ip === $subnet);
        } else {
            for ($i = 0; $i < strlen($ip); $i++) {
                $mask = 0;
                if ($bits > 0) {
                    $mask = ($bits >= 8) ? 255 : (256 - (1 << (8 - $bits)));
                    $bits -= 8;
                }
                if ((ord($ip[$i]) & $mask) !== (ord($subnet[$i]) & $mask)) {
                    return false;
                }
            }
        }
        return true;
    }