TCP packets : end of thre-way handshake and start of data-transmission - how to detect ?

Hello All,

I'm (still) busy trying to write TCP/IP for an rtl8019as NIC connected to an ATMega32 controller, and seem to have hit a snag : I cannot seem to find any information that tells me *with authority* when the three-way handshake ends and the first data-packet starts. Most info that I found describe the handshake, and than follow that up with tearing-down the connection (sending the FIN flag).

And yes, I have seen the I've looked at the RFC 793 for it. It seems to indicate that data-less packets being received by the server after it has send its SYN/ACK should (pretty-much) be ignored, but nothing is actually said about it.

It allso makes me wonder about services that send back data when a connection is made, *without* the client having to do anything else than connect (it does not need to send any data. Like with , for instance, "daytime" at port 15, "quote of the day" at port 19 and "chargen" on port

20).

Allso, I can't seem to find any information/description about when a server is supposed to tell the client that further communication should be directed at another port (what the high-level "accept" function does/seems to handle). When I tried to change the port number in the SYN/ACK packet I get a RST back.

I would be much obliged if someone could tell me where I can find specific information on (some or all of) the above problems.

Regards, Rudy Wieser

Reply to
R.Wieser
Loading thread data ...

RFC 793 Section 3.4 (Establishing a connection) says in part:

" Several examples of connection initiation follow. Although these examples do not show connection synchronization using data-carrying segments, this is perfectly legitimate, so long as the receiving TCP doesn't deliver the data to the user until it is clear the data is valid (i.e., the data must be buffered at the receiver until the connection reaches the ESTABLISHED state)."

This says that it is possible to transport data in the SYN packets, but any such data can't be delivered to higher levels until the three-way handshake is complete.

I'd expect it would be difficult to send any data in the initial SYN packet because it would be necessary to assume a window size. The second packet (SYN/ACK) could include data because the first SYN could report a window size, but the connection initiator might start with an empty window in the initial SYN and then indicate a non-empty window in the subsequent ACK.

If the connection responder indicates an empty window in its SYN, it would need to send another packet after the three-way handshake to report the window size (but that packet could contain data, if the client has already indicated a non-empty window).

Two possibile "minimum" dialogues might be:

Client sends SYN (with window nonempty) Server sends SYN/ACK (with window nonempty if useful) and data Client sends ACK (of SYN and possibly data) Server sends FIN Client sends FIN,ACK (of data and FIN) Server sends ACK (of FIN)

Client sends SYN (with window 0) Server sends SYN/ACK (with window 0) Client sends ACK (with window nonempty) Server sends data (with window nonempty if useful) Client sends FIN,ACK (of data) Server sends FIN,ACK (of FIN) Client sends ACK (of FIN)

Combinations of empty/non-empty windows might also be possible.

That is a feature of the sockets API, and doesn't quite work the way you might think it does. (I was also confused by this when I first started using TCP/IP.)

The server listens on a well-known port, but the listening socket is not used for communication, just to detect incoming connections. accept() returns a newly created socket which deals with one specific connection.

The listening socket and all those returned by accept() have the same port number at the server side, but all the sockets returned by accept() have unique (client_IP, client_port) pairs.

The client has picked its own typically high-numbered port for the outgoing connection, and addresses the server at its well-known port. The resulting connection is identified by the quadruplet:

(client_IP, client_port, server_IP, server_port)

All packets for that connection (from initial SYN to last FIN/ACK and following ACK) have the same values in the source and destination IP and port fields (with the source and destination fields swapped for packets in the opposite direction).

Multiple clients will have different (client_IP, client_port) pairs, so their packets can be distinguished and sent to the appropriate socket at the server, even though the (server_IP, server_port) pairs are the same.

--
David Empson
dempson@actrix.gen.nz
Reply to
David Empson

It helps to have examined a conversation in detail. Ethereal is a free download.

formatting link

Reply to
MikeWhy

Hello David,

Thanks for your reply, but somehow I can't seem to extract from it what I need :

Its not the client actually sending data before it should I'm concerned about (as the controller does not have enough RAM to store the data I will probably just drop the connection), but how figure out which packets to skip before I'm allowed to send some data myself : Currently I receive two different ACK responses to my SYN/ACK (the second packet re-defines the window-size). When I send some data after receiving the first ACK the client behaves as if I did not send that packet at all (mind you, this is on a LAN).

I can ofcourse "fix" this by checking the Acknowledgement-number and as it did not change re-send the data, but a) would like to know why it does not respond to my data b) have not enough resources in the controller to send a packet again anyway. :-\

Thank you for that info, but can you tell me how I should, after the initial contact, re-direct the client to another port ?

Regards, Rudy Wieser

-- Origional message David Empson schreef in berichtnieuws

1iz7rka.1twixqu1seqp20N% snipped-for-privacy@actrix.gen.nz...

to

find

handshake

with

to

has

actually

port

server

directed

I
Reply to
R.Wieser

at I

ial

I think you find that you (server) need to do this in response to the

1st SYN, not after the three-way handshake. It is only necessary if you expect to have multiple incoming connections to a given port.
Reply to
Rocky

Hello Rocky,

:-) That is exactly what I tried and described in my initial message and which fails (gets responded to with a Reset).

As I'm implementing a Server I should consider the possibility of multiple incoming connections, don't you think ? :-) Although its not specified as mandatory, I think it will help to keep mixups between the different requests at a minimum.

Regards, Rudy Wieser

-- Origi> Hello David,

initial

I think you find that you (server) need to do this in response to the

1st SYN, not after the three-way handshake. It is only necessary if you expect to have multiple incoming connections to a given port.
Reply to
R.Wieser

Call it whatever you like internally, but it must never show on the wire. Read a few sniffer traces. Ethereal is a free download.

Reply to
MikeWhy

and

I think that David put it correctly. When you change the socket (not port number) you do not need to change the port number on the server. The server knows the intended socket because the SOURCE_IP:PORT of incoming packets will be unique for a given connection. For example, assume your IP is 192.168.0.1 and you are listening on port 23. When a SYN comes in from 192.168.0.123 it will have a source port of (for example) 12345. The source port on clients is normally chosen sequentially (on windows machines) so it is normally always different on a subsequent or concurrent connection. Obviously it will repeat eventually. Thus your unique socket indentifier on your server is:

192.168.0.1:23 and 192.168.0.123:12345. Your transactions from the first threeway handshake will use these parameters. Your software will transfer these parameters to a 'connection socket' (as opposed to a listening socket). The main difference is that if a packet comes in that DOES NOT match a connected socket, then it is presented to the listening socket.

I hope this gives you some idea... I know what I mean :)

Rocky

Reply to
Rocky

TCP does not allow a port re-direct a la TFTP.

There is no danger of a mix-up: a TCP connection is identified by a set of four numbers: the source IP, destination IP, source port and destination port. For the same client and server, the source ports are different for different connections.

After the three-way handshake is completed, you're not allowed to do any kinds of re-direct: the conversation is on and the four numbers fixed till FIN/ACK's or RST.

--

Tauno Voipio
tauno voipio (at) iki fi
Reply to
Tauno Voipio

e and

ple

cified

-

You are right - it mustn't show on the wire. BTW it is now WIRESHARK.

formatting link

Reply to
Rocky

Hello Mike,

My bad it seems. I allways assumed that the "accept" function moved the connection to a high port, so the "listen" port was kept free to accept whomever tried to connect to it.

And yes, looking at some snifs I made some time ago I see that the port-numbers to not change during, or after the three-way handshake.

Regards, Rudy Wieser

-- Origional message MikeWhy schreef in berichtnieuws nBGLl.29139$ snipped-for-privacy@nlpi066.nbdc.sbc.com...

and

multiple

specified

Reply to
R.Wieser

Hello Rocky,

It looks that an assumption of how things work got the better of me : I allways thought that the "accept" function would take over the connection and move it from the origional port to high-numbered one. Looking at at a few packet-sniff logs (as suggested by "MikeWhy", who allso replied to me) I realized that that assumption was wrong.

Now if I can only get that years-old misconception outof my head and replace it with the correct way-of-working

Regards, Rudy Wieser

-- Origi>

I think that David put it correctly. When you change the socket (not port number) you do not need to change the port number on the server. The server knows the intended socket because the SOURCE_IP:PORT of incoming packets will be unique for a given connection. For example, assume your IP is 192.168.0.1 and you are listening on port 23. When a SYN comes in from 192.168.0.123 it will have a source port of (for example) 12345. The source port on clients is normally chosen sequentially (on windows machines) so it is normally always different on a subsequent or concurrent connection. Obviously it will repeat eventually. Thus your unique socket indentifier on your server is:

192.168.0.1:23 and 192.168.0.123:12345. Your transactions from the first threeway handshake will use these parameters. Your software will transfer these parameters to a 'connection socket' (as opposed to a listening socket). The main difference is that if a packet comes in that DOES NOT match a connected socket, then it is presented to the listening socket.

I hope this gives you some idea... I know what I mean :)

Rocky

Reply to
R.Wieser

Hello Tauno,

Hmmm ... thats 12 (IPv4) or 16 (IPv6) bytes only to define a two-way socket. As I'm working on a controller with very limited memory (just 2048 *Bytes* of RAM, which allso needs to hold the ethernet-packet itself as well as the stack) I hoped I could use another method to uniquely identify a connection : by (ab)using (a few bits of) the new-to-be-assigned portnumber together with the Acknowledge-number. But alas, that idea is now outof the window.

Yep, thats clear to me now. Thanks for explaining.

Regards, Rudy Wieser

-- Origi> > Hello Rocky,

and

multiple

specified as

I
Reply to
R.Wieser

You might be remembering that accept() returns a new socket, bound to the new connection. The original listener socket is still there. Anyway, now that you know, you'll just know.

Reply to
MikeWhy

You're allowed to send data with the SYN/ACK; that doesn't mean that the client will accept it. But ideally, you shouldn't send any data until after the client ACK's your SYN+ACK. This prevents a rogue client from using your server as a DoS "amplifier" (sending a SYN with a spoofed source address).

If you can't re-send, you can't implement TCP. Even on a LAN, packets get dropped; you can't discard data until it has been ACK'd.

You can't redirect the client to another port. If the client connects from port 123 to port 456, all subsequent client->server packets will be from 123 to 456, and all subsequent server->client packets must be from

456->123. If you send anything else, expect a RST.
Reply to
Nobody

You need to store all of that, plus both sequence numbers (another 8 bytes), timers, the client's receive window, the path MTU, the client's MAC address, probably some other stuff. Resist the temptation to try to get away with implementing only what you think you need based upon a handful of test cases. Expect the client and intermediate routers to behave in every way the standards permit them to.

Reply to
Nobody

And a few ways the standards don't permit them to.

--
Grant Edwards                   grante             Yow! He is the MELBA-BEING
                                  at               ... the ANGEL CAKE
                               visi.com            ... XEROX him ... XEROX
                                                   him --
Reply to
Grant Edwards

In that situation you aren't allowed to send data in response to the ACK of your SYN, because that ACK said the window size was zero. The receiver is allowed to throw away data you send which falls outside the receiver's window. You must wait until the second ACK which says the window size is nonzero.

You could only send data with your responding SYN/ACK or in response to the client's subsequent ACK if the client had indicated a nonzero window size in the previous packet, and it seems that most common TCP/IP implementations never do that during the three-way handshake.

It occurs to me that the SYN packets are usually also negotiating MSS, and some TCP implementations may want to wait for MSS to be established in both directions before reporting their window size.

Don't use the arrival of a specific packet directly as a trigger to send: you should be copying the window size out of the received packets (strictly it is the range of bytes starting from the ack sequence number up to the end of the window, and you may need to allow for data you had previously sent but which the receiver hasn't acknowledged yet).

Wait until the window size is nonzero before sending. You should also check that you aren't sending too much data, e.g. the client might open a very small window initially, preventing you from sending all your data. In this situation you might not be able to send at all unless the client opens its window further, unless you send your data in several small pieces.

You might want to look at the open source uIP project to get some implementation ideas. It is designed to be used on very small systems with limited memory.

--
David Empson
dempson@actrix.gen.nz
Reply to
David Empson

Is there a specific reason why you insist on implementing TCP/IP with such small resources ?

UDP would be much more suitable for such small devices.

Paul

Reply to
Paul Keinanen

Hello Nobody,

Thats the problem, I did (only start to send *after* the clients ACK).

Too little RAM in the controller for that I'm afraid. But I may try to figure out a method to work around it *after* I get the connection to work.

Yep, that has been made clear to me now. :-)

Regards, Rudy Wieser

-- Origi>

what I

will

skip

is on

it

not

send a

initial

Reply to
R.Wieser

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.