FIN_WAIT_2 hung tcp connections - how to kill

Directory Manager <quipu@aun.uninett.no> Mon, 03 February 1992 12:31 UTC

Received: from nri.reston.va.us by NRI.NRI.Reston.VA.US id aa23313; 3 Feb 92 7:31 EST
Received: from bells.cs.ucl.ac.uk by NRI.NRI.Reston.VA.US id aa23309; 3 Feb 92 7:31 EST
Received: from aun.uninett.no by bells.cs.ucl.ac.uk with Internet SMTP id <g.10492-0@bells.cs.ucl.ac.uk>; Mon, 3 Feb 1992 10:44:56 +0000
Received: by aun.uninett.no (5.65b) id <AA18615>; Mon, 3 Feb 92 11:45:40 +0100
Date: Mon, 03 Feb 1992 11:45:40 +0100
From: Directory Manager <quipu@aun.uninett.no>
Message-Id: <9202031045.AA18615@aun.uninett.no>
To: osi-ds@cs.ucl.ac.uk
Subject: FIN_WAIT_2 hung tcp connections - how to kill

 
Below is a shell script we use to get rid of tcp connections stuck in
FIN_WAIT_2 state. This seems to happen from time to time for quipu,
and can be quite annoying. We use it on a SUN4 with SunOS 4.1.1.

Geir.

===========================

#! /bin/sh

# original from cdjohns@NSWC-G.ARPA
#
# TIMETODEATH expressed in decimal instead of hex
#	-- mkhaw@teknowledge-vaxc.arpa

# Use this script to force sockets in FIN_WAIT_2 state to close.
# It works by setting the 2MSL timer in the TCP Protocol Control Block (PCB)
# to a non-zero value.  The kernel then begins to decrement this value until
# it reaches zero, at which point the kernel forces a close on the socket and
# deletes the TCP PCB.  If both sides of the connection are hung, clearing one
# side will possibly clear the other.

# MSLOFFSET is the offset in the tcpcb record for the 2MSL timer.
# <netinet/tcp_var.h> describes the tcpcb record.
# This value is the number of bytes offset, expressed in hexadecimal.

MSLOFFSET=10
STATEOFFSET=8

# TIMETODEATH is the number of half seconds until the connection is 
# closed.  This value is expressed in decimal and must be greater
# than zero.

TIMETODEATH=06

# Display netstat to get PCB addresses (first column).
echo 'Active connections
PCB      Proto Recv-Q Send-Q  Local Address      Foreign Address    (state)'
netstat -A | egrep 'FIN_WAIT_[12]'

echo
echo -n 'PCB address to terminate? '
read addr
echo

# Use adb on kernel to display the PCB of the specified address
adb -k /vmunix /dev/mem << SHAR_EOF
$addr\$<tcpcb
\$q
SHAR_EOF

# Check to see if this was the correct address and PCB. state should be
# 8 for LAST_ACK, 9 for FIN_WAIT_2
echo
echo 'state = 9 = FIN_WAIT_2, state = 8 = LAST_ACK'
echo -n 'Is this the correct PCB (y/n)? '
read ans
echo
case $ans in
  [Yy]*)
	;;
  *)
	echo 'No Changes.'
	exit
	;;
esac

# Use adb on kernel to set the 2MSL timer for the PCB
# and state=CLOSED (0)
adb -k -w /vmunix /dev/mem << SHAR_EOF
$addr+$MSLOFFSET/w 0t$TIMETODEATH
$addr+$STATEOFFSET/w 0
\$q
SHAR_EOF

# Use these lines in place of the above for testing the script.
#adb -k  /vmunix /dev/mem << SHAR_EOF
#$addr+$MSLOFFSET/x 
#\$q
#SHAR_EOF

echo
echo "Connection will be terminated in `expr $TIMETODEATH / 2` seconds."
echo