[PATCH 1/2] Add test to check that session multiplexing (with, ControlMaster=auto) works fine for concurrent ssh connections
Jens Rosenboom
Jens.Rosenboom at web.de
Tue Sep 15 21:27:04 AEST 2026
This is a new test that checks if ControlMaster=auto works fine for
multiple ssh connections that are started at the same time.
Signed-off-by: Jens Rosenboom <jens.rosenboom at web.de>
---
regress/multiplex.sh | 46 ++++++++++++++++++++++++++++++++++++
regress/reconfigure.sh | 2 ++
regress/test-exec.sh | 53 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+)
diff --git a/regress/multiplex.sh b/regress/multiplex.sh
index 584bbbe22..239346863 100644
--- a/regress/multiplex.sh
+++ b/regress/multiplex.sh
@@ -245,3 +245,49 @@ wait $SSH_PID
kill -0 $SSH_PID >/dev/null 2>&1 && fatal "stop command failed"
SSH_PID="" # Already gone, so don't kill in cleanup
+# test that, when no master is initially available, multiple concurrent
ssh connections actually go over a single mux master socket
+verbose "test $tid: concurrent connections over a single control socket
(with ControlMaster=auto)"
+test ! -e "$CTL" || fail "control socket still exists"
+barrier="${SSH_REGRESS_TMP}/mux-barrier"
+rm -f "$barrier"
+mkfifo "$barrier"
+pids=""
+if [ -n "$SUDO" ]; then
+ TC=$(command -v tc)
+fi
+if [ -n "$TC" ]; then
+ $SUDO $TC qdisc replace dev lo root netem delay 500ms
+else
+ verbose "SUDO or tc(8) not available, running without induced
network delay"
+fi
+
+i=0
+while [ $i -lt 10 ]; do
+ (
+ # opening the fifo for reading waits for a writing end to open
+ exec 3< "$barrier"
+ exec ${SSH} -F$OBJ/ssh_config -o ControlMaster=auto -S$CTL
otherhost "sleep 4" \
+ >>$TEST_REGRESS_LOGFILE 2>&1
+ ) &
+ pids="$pids $!"
+ i=$((i + 1))
+done
+
+# wait a moment for the sub-shells to have started
+sleep 1
+
+# release all 10 clients (by opening the fifo for writing; it is closed
again, immediately)
+: > "$barrier"
+
+sleep 2
+count_connection_sockets
+connections=$?
+if [ -n "$TC" ]; then
+ $SUDO $TC qdisc del dev lo root
+fi
+[ "$connections" -eq 1 ] || fail "concurrent connections over a single
control socket (with ControlMaster=auto) failed, $connections sockets
were used"
+ret=0
+for pid in $pids; do
+ wait "$pid" || ret=1
+done
+[ "$ret" -eq 0 ] || fail "concurrent connections over a single control
socket (with ControlMaster=auto) failed"
diff --git a/regress/reconfigure.sh b/regress/reconfigure.sh
index d5b4e9808..d96ad9405 100644
--- a/regress/reconfigure.sh
+++ b/regress/reconfigure.sh
@@ -45,6 +45,8 @@ fi
trace "reconfigure with active clients"
${SSH} -F $OBJ/ssh_config somehost sleep 10 # authenticated client
${NC} -d 127.0.0.1 $PORT >/dev/null & # unauthenticated client
+NC_PID=$!
+trap 'kill "$NC_PID" 2>/dev/null' EXIT
PID=`$SUDO cat $PIDFILE`
rm -f $PIDFILE
$SUDO kill -HUP $PID
diff --git a/regress/test-exec.sh b/regress/test-exec.sh
index 30a2a28ab..2e56887a4 100644
--- a/regress/test-exec.sh
+++ b/regress/test-exec.sh
@@ -474,6 +474,59 @@ make_tmpdir ()
SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \
fatal "failed to create temporary directory"
}
+
+count_connection_sockets ()
+{
+ [ -z "$PIDFILE" ] && return
+ [ -f "$PIDFILE" ] || return
+ pid=`$SUDO cat $PIDFILE`
+ if [ "X$pid" = "X" ]; then
+ echo "no sshd running" 1>&2
+ return
+ elif [ $pid -lt 2 ]; then
+ echo "bad pid for sshd: $pid" 1>&2
+ return
+ fi
+
+ sockets=""
+ case "$(uname)" in
+ Linux)
+ if have_prog ss; then
+ sockets=$($SUDO ss -Htn state established \
+ "( dport = :$PORT )")
+ elif have_prog netstat; then
+ sockets=$($SUDO netstat -tn 2>/dev/null | \
+ awk -v p=":$PORT" '$4 ~ p"$" && $6=="ESTABLISHED"')
+ else
+ skip "count_connection_sockets: no ss(8) or netstat(8)"
+ fi
+ ;;
+ Darwin|FreeBSD|NetBSD|DragonFly)
+ have_prog netstat || \
+ skip "count_connection_sockets: no netstat(8)"
+ sockets=$($SUDO netstat -an -p tcp 2>/dev/null | \
+ awk -v p=".$PORT" '$4 ~ p"$" && $6=="ESTABLISHED"')
+ ;;
+ OpenBSD)
+ have_prog netstat || \
+ skip "count_connection_sockets: no netstat(8)"
+ sockets=$($SUDO netstat -an -f inet 2>/dev/null | \
+ awk -v p=".$PORT" \
+ '$1=="tcp" && $4 ~ p"$" && $6=="ESTABLISHED"')
+ ;;
+ SunOS)
+ have_prog netstat || \
+ skip "count_connection_sockets: no netstat(8)"
+ sockets=$($SUDO netstat -an -f inet -P tcp 2>/dev/null | \
+ awk -v p="\\.$PORT\$" '$1 ~ p && $6 ~ /ESTABLISHED/')
+ ;;
+ *)
+ skip "count_connection_sockets: unsupported OS $(uname)"
+ ;;
+ esac
+
+ return $(echo "$sockets" | grep -c .)
+}
# End of portable specific functions
stop_sshd ()
--
2.55.0
More information about the openssh-unix-dev
mailing list