protected function getSubnet($ip, $netmask)
    {
        $binString = @inet_pton($ip);
        if ($binString === false) {
            throw new \InvalidArgumentException("Not a valid IP address.");
        }

        // Length of the IP in bytes (4 or 16)
        $byteLen = mb_strlen($binString, "8bit");
        if (!is_int($netmask) || $netmask < 0 || $netmask > $byteLen * 8) {
            throw new \InvalidArgumentException("Not a valid netmask.");
        }

        for ($byte = $byteLen - 1; ($byte + 1) * 8 > $netmask; --$byte) {
            // Bitlength of a mask for the current byte
            $maskLen = min(8, ($byte + 1) * 8 - $netmask);

            // Create the byte mask of maskLen bits
            $mask = (~((1 << $maskLen) - 1)) & 0xff;

            // Export byte as 'unsigned char' and apply the mask
            $maskedByte = $mask & unpack('C', $binString[$byte])[1];
            $binString[$byte] = pack('C', $maskedByte);
        }

        return inet_ntop($binString) . '/' . $netmask;
    }