#!/bin/bash # # Copyright (C) 2026 Nikos Mavrogiannopoulos # # This file is part of ocserv. # # ocserv is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at # your option) any later version. # # ocserv is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GnuTLS; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Regression test for is_data() IPv6 offset bug: ICMPv6 Next Header is at # byte offset 6 of the IPv6 fixed header, not offset 9 (which is the correct # offset only for the IPv4 Protocol field). With the bug present, ICMPv6 # traffic is misclassified as data traffic and resets the idle timer, so the # server never disconnects a client that sends only ICMPv6 packets. This test # expects the server to enforce idle-timeout even when ICMPv6 (ping6) traffic # is flowing continuously. OCCTL="${OCCTL:-../src/occtl/occtl}" SERV="${SERV:-../src/ocserv}" srcdir=${srcdir:-.} OCCTL_SOCKET=./occtl-idle6-$$.socket PIDFILE=ocserv-pid.$$.tmp CPIDFILE=openpid.$$.tmp function finish { echo " * Cleaning up..." test -n "${PING6PID}" && kill "${PING6PID}" >/dev/null 2>&1 || true CLIPID=${CPIDFILE} cleanup_client_server } trap finish EXIT . `dirname $0`/random-net.sh . `dirname $0`/common.sh . `dirname $0`/ns.sh eval "${GETPORT}" echo "Testing that idle timeout fires despite continuous ICMPv6 traffic..." update_config idle-timeout-icmpv6.config ${CMDNS2} ${SERV} -p ${PIDFILE} -f -c ${CONFIG} -d 3 & PID=$! sleep 5 echo "Connecting to obtain cookie..." eval `echo "test" | ${CMDNS1} ${OPENCONNECT} --passwd-on-stdin -q ${ADDRESS}:${PORT} \ -u test --authenticate \ --servercert=pin-sha256:xp3scfzy3rOQsv9NcOve/8YVVv+pHr4qNCXEXrNl5s8=` if [ -z "$COOKIE" ]; then fail $PID "Could not obtain cookie" fi sleep 1 echo "Connecting with cookie..." ${CMDNS1} ${OPENCONNECT} ${ADDRESS}:${PORT} -u test -C "$COOKIE" \ --servercert=pin-sha256:xp3scfzy3rOQsv9NcOve/8YVVv+pHr4qNCXEXrNl5s8= \ -s "${srcdir}/scripts/vpnc-script" \ --background --pid-file "${CPIDFILE}" sleep 4 if [ ! -f "${CPIDFILE}" ]; then fail $PID "It was not possible to establish session!" fi echo "Verifying initial IPv6 connectivity..." set -e ${CMDNS1} ping -6 -c 3 ${VPNADDR6} ${CMDNS2} ${OCCTL} -s ${OCCTL_SOCKET} show user test set +e # Keep sending ICMPv6 Echo Requests through the tunnel for the duration of the # wait. ICMPv6 (Next Header = 0x3A at offset 6) must not be counted as data # traffic by is_data(), so the idle timer must not be reset and the server # must disconnect the client after idle-timeout = 25 s. # # With the bug (data[9] instead of data[6] for IPv6): is_data() never matches # 0x3A at the wrong offset, treats ICMPv6 as data, keeps resetting the timer, # and the client is never disconnected → this test fails. echo "Sending ICMPv6 traffic during idle window (idle-timeout = 25 s)..." ${CMDNS1} ping -6 -i 2 -c 30 ${VPNADDR6} >/dev/null 2>&1 & PING6PID=$! # Wait well past idle-timeout (25 s) plus the server's enforcement period. sleep 60 wait "${PING6PID}" 2>/dev/null || true PING6PID= ${CMDNS2} ${OCCTL} -s ${OCCTL_SOCKET} show user test if test $? = 0; then fail $PID "Client still listed in occtl after idle-timeout despite only ICMPv6 traffic!" fi ${CMDNS1} ping -6 -c 3 ${VPNADDR6} if test $? = 0; then fail $PID "Client remains reachable via IPv6 after idle-timeout!" fi exit 0