views:

747

answers:

3

Situation: The server calls listen() (but not accept()!). The client sends a SYN to the server. The server gets the SYN, and then sends a SYN/ACK back to the client. However, the client now hangs up / dies, so it never sends an ACK back to the server. The connection is in the SYN_SENT state.

Now another client sends a SYN, gets a SYN/ACK back from the server, and sends back an ACK. This connection is now in the ESTABLISHED state.

Now the server finally calls accept(). What happens? Does accept() block on the first, faulty connection, until some kind of timeout occurs? Does it check the queue for any ESTABLISHED connections and return those, first?

+2  A: 

Well, what you're describing here is a typical syn-flood attack ( http://en.wikipedia.org/wiki/SYN_flood ) when executed more than once.

When looking for example at: http://lkml.indiana.edu/hypermail/linux/kernel/0307.0/1258.html there are two seperate queues, one syn queue and one established queue. Apparently it the first connection will remain in the syn queue (since it's in the SYN_RCVD state), the second connection will be in the established queue where the accept() will get it from. A netstat should still show the first in the SYN_RCVD state.

(note see also my comment, it is the client who will be in the SYN_SENT state, the server (which we are discussing) wil bein the SYN_RCVD state).

amo-ej1
A: 

You have to remember that listen(), accept(), et al, are not under the hood protocol debugging tools. From the accept man page: "accept - accept a connection on a socket". Incomplete connections aren't reported, nor should they be. The application doesn't need to worry about setup and teardown of sockets, or retransmissions, or fragment reassembly, or ...

If you are writing a network application, covering the things that you should be concerned about is more than enough work. If you have a working application but are trying to figure out problems then use a nice network debugging tool, tools for inspecting the state of your OS, etc. Do NOT try to put this in your applications.

If you're trying to write a debugging tool, then you can't accomplish what you want by using application level TCP/IP calls. You'll need to drop down at least one level.

dwc
I'm implementing listen() and accept() myself for a project, so I have to know how they behave.
Claudiu
+1  A: 

You should note that in some implementations, the half open connection (the one in the SYN_RCVD state), may not even be recorded on the server. Implementations may use SYN cookies, in which they encode all of the information they need to complete establishing the connection into the sequence number of the SYN+ACK packet. When the ACK packet is returned, with the sequence number incremented, they can decrement it and get the information back. This can help protect against SYN floods by not allocating any resources on the server for these half-open connections; thus no matter how many extra SYN packets a client sends, the server will not run out of resources.

Note that SCTP implements a 4-way handshake, with cookies built into the protocol, to protect against SYN floods while allowing more information to be stored in the cookie, and thus not having to limit the protocol features supported because the size of the cookie is too small (in TCP, you only get 32 bits of sequence number to store all of the information).

So to answer your question, the user-space accept() will only ever see fully established connections, and will have no notion of the half-open connections that are purely an implementation detail of the TCP stack.

Brian Campbell