Hi,
I observed a strange behavior with the minisocks in the linux-2.6.16 kernel.
Here is the scenario:
- The server creates a socket, bind, listen and wait indefinitly.
- The client creates a socket, does a bind, connects to the server,
sends data and closes the connection. It waits 61 seconds and does the
same again (with same bind address).
Since this moment, any client trying to connect to the server (eg.
telnet) receives the SYN|ACK from the server but the ACK is lost by the
server and the connection stays in the SYN_RECV state in the server side.
It seems that there are two sockets in the req queue which are
<SS_FREE,TCP_CLOSE_WAIT> and <SS_FREE,TCP_CLOSE> with the same tuple
(src_addr, src_port, dst_addr, dst_port).
This behavior does not occurs, if the client sets the setsockopt reuse
addr option with the second connection.
Joined to this email, client and server written in Python.
--Daniel
#! /usr/bin/env python
import os
import sys
import socket
import time
import getopt
import string
def usage(procname):
print(os.path.basename(procname) + " --local=<ip> --remote=<ip> --port=<port>")
try:
opts, args = getopt.getopt(sys.argv[1:], "", ["local=", "remote=", "port="])
except getopt.GetoptError:
usage(sys.argv[0])
sys.exit(2)
local = ""
remote = ""
port = ""
for o, a in opts:
if o in ("-l", "--local"):
local=a
if o in ("-r", "--remote"):
remote=a
if o in ("-p", "--port"):
port=a
if local == "" or remote == "" or port == "":
usage(sys.argv[0])
sys.exit(2)
# -----------------------------------------------------------------------------
try:
# first connection
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(1,2,1) # REUSE_ADDR
s.bind((local,int(port)))
s.connect((remote,int(port)))
print "Binded to " + local + ":" + port
print "Connected to " + remote + ":" + port
s.send("Hello world ! ")
s.close()
print "Disconnected from " + remote + ":" + port
# Wait some time for FIN_WAIT2
print "Waiting 61 secs..."
time.sleep(61)
# second connection
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((local,int(port)))
s.connect((remote,int(port)))
s.send("Hello world ! ")
s.close()
# server is now in 'strange' state
print "ok, now try with telnet " + remote + " " + port + " and look in server side "
time.sleep(3600)
sys.exit(0)
except socket.error, msg:
print msg
sys.exit(1)
#! /usr/bin/env python
import os
import sys
import socket
import time
import getopt
import string
def usage(procname):
print(os.path.basename(procname) + " --local=ipaddress --port=port")
try:
opts, args = getopt.getopt(sys.argv[1:], "", [ "local=", "port="])
except getopt.GetoptError:
usage(sys.argv[0])
sys.exit(2)
local = ""
port = ""
for o, a in opts:
if o in ("-l", "--local"):
local=a
if o in ("-p", "--port"):
port=a
if local == "" or port == "":
usage(sys.argv[0])
sys.exit(2)
# -----------------------------------------------------------------------------
try:
# Create the listen point
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(1,2,1)
s.bind((local,int(port)))
s.listen(10)
# Does nothing and rely on the TCP stack for incoming connections
print "Ok, ready."
time.sleep(3600)
except socket.error, msg:
print msg