Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watmath!clyde!cbosgd!ucbvax!NSWC-G.ARPA!cdjohns From: cdjohns@NSWC-G.ARPA.UUCP Newsgroups: comp.protocols.tcp-ip Subject: FIN_WAIT_2 problem ? Message-ID: <8706151938.AA16109@ucbvax.Berkeley.EDU> Date: Mon, 15-Jun-87 15:28:54 EDT Article-I.D.: ucbvax.8706151938.AA16109 Posted: Mon Jun 15 15:28:54 1987 Date-Received: Wed, 17-Jun-87 02:13:49 EDT Sender: daemon@ucbvax.BERKELEY.EDU Distribution: world Organization: The ARPA Internet Lines: 129 The problem in question is that of a TCP session left in limbo due to the unusual termination of the matching socket on the remote host. This condition is usually characterized by a TCP session dangling in the FIN_WAIT_2 or LAST_ACK states. This indicates that the session is awaiting the arrival of a final FIN or ACK of FIN. The sessions will never see these messages because the matching side of the connection is either dead or awaiting a similiar message. We finally decided to look in to the problem seriously and have come up with the following observations and (apparently) reasonable solution. When a TCP session is hung, it's usually in FIN_WAIT_2 or LAST_ACK. Normally, a session in FIN_WAIT_2 will receive a FIN, send ACK and transition to TIME_WAIT. In this state, the session waits a default amount of time (suggested 1 minute) and then assumes the matching side of the connection received the ACK of FIN. Then the TCP Protocol Control Block (PCB) is deleted and the session is closed. (the PCB is the internal representation of the TCP connection) The timer mentioned above is referred to as the 2MSL timer and is apparantly only used in the TIME_WAIT state. This timer is simple in operation. The current value of the timer is stored in the PCB for that session. (the structure of a TCP PCB can be found in ) The kernel decrements this counter every 500ms until it reaches zero, then the session is internally deleted. The solution we have found to the dangling session is to fake the kernel into thinking the session is in the TIME_WAIT state, ready to die. This is done by setting the 2MSL timer to a non-zero value. The kernel then takes over, decrementing the timer until it reaches zero and ZAP! the TCP session is gone. This setting of the timer is easily done with adb. It is sometimes the case that both sides of the connection are hung, one in FIN_WAIT_2, the other in LAST_ACK. It appears that clearing the FIN_WAIT_2 using the above method will also clear the matching LAST_ACK. If this appears to be a reasonable solution, a permanent solution might be achieved in the following way: Upon entering the FIN_WAIT_2 state, set the 2MSL timer to a large enough default time to give the remote host adequate time to send the FIN. If the FIN never shows up, eventually the PCB will be deleted. We would appreciate any comments about this solution. The following script should demonstrate setting the 2MSL timer. ------------------- adb script starts here ------------------ #!/bin/sh # This script is designed to aid in eliminating lingering TCP # connections without having to reboot the host kernel. # It is intended to be used on TCP connections stuck in the # FIN_WAIT_2 state. Elimination of the connection is done 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 reachs 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 (FIN_WAIT_2 should be cleared as a first try). # MSLOFFSET is the offset in the tcpcb record for the 2MSL timer. # The tcpcb record is found in # This value is the number of bytes offset, expressed in hexidecimal. MSLOFFSET=10 # TIMETODEATH is the number of half seconds until the connection is # closed. This value is expressed in hexidecimal and must be greater # than zero. TIMETODEATH=06 # Display netstat. Addresess for PCB's are found in first column. netstat -A echo echo 'PCB address to terminate ? ' read addr echo # Perform adb on kernel and display the PCB of the specified address adb -k /vmunix /dev/mem << SHAR_EOF $addr\$