Subject: TCP end-to-end Semantics

From: [email-masked]
Date: Mon, 8 Jan 2001 16:04:29 +0100

Can somebody shed some light on a few things pleas please?

1.
People claim that TCP semantics is not violated if TCP acks are "spoofed", as long as the initial 3-way handshake and the FIN are respected.
Seems strange to me. Namely, the sending TCP will have lost the data because of spoofing and falsely assumes it has arrived if the link breaks down, i.e. there is a "false positive". Who says the sender wants to do a FIN, it could just stop and will 
notice nothing about the break down.

2.
What if I used large windows, but spoofed the initial SYN/ACK, i.e. the opposite. This will speed up small transfers, because there is no wait for the handshake to complete. The other side can not open the socket, the first data transfer will simply 
fail, so no false positives here? Good idea or not?

3.
What guarantee does an application have anyway. If I do a send in TCP, the data goes into TCP's buffer without error and is handled asynchronously, which could fail. How rock-solid is end-to-end reliability?

Thank you,

Eric Verlind
SW Architect

---

From: Craig Partridge <[email-masked]>
Date: Mon, 08 Jan 2001 10:27:58 -0500

In message <0056900014977107000002L072*@MHS>, [email-masked] writes:

>1.
>People claim that TCP semantics is not violated if TCP acks are "spoofed", as 
 >long as the initial 3-way handshake and the FIN are respected.
>Seems strange to me. Namely, the sending TCP will have lost the data because o
 >f spoofing and falsely assumes it has arrived if the link breaks down, i.e. t
 >here is a "false positive". Who says the sender wants to do a FIN, it could j
 >ust stop and will 

You're right, spoofing ACKs does violate TCP semantics.  Some folks argue
that if their intermediate node, that spoofs ACKs, also buffers data then
you're safe, but they're wrong -- as the intermediate could fail.

>2.
>What if I used large windows, but spoofed the initial SYN/ACK, i.e. the opposi
 >te. This will speed up small transfers, because there is no wait for the hand
 >shake to complete. The other side can not open the socket, the first data tra
 >nsfer will simply 

Well it doesn't violate semantics in the same way -- if the other end does
not open the connection then either (a) you'll get a RST and the connection
will fail or (b) you'll retransmit several times and the connection will
fail.  It will never claim that data is delivered that was not.

>3.
>What guarantee does an application have anyway. If I do a send in TCP, the dat
 >a goes into TCP's buffer without error and is handled asynchronously, which c
 >ould fail. How rock-solid is end-to-end reliability?

If you linger on the close (such that all data is acknowledged before your
socket closes -- and assuming no ack spoofing) then you'll have a firm
guarantee that your data reached the remote system.  This guarantee, however,
is only for the end system -- it does not say the end application received
the data (it may never read it).

Craig

---

From: Luigi Rizzo <[email-masked]>
Date: Mon, 8 Jan 2001 23:07:32 +0100 (CET)

>>People claim that TCP semantics is not violated if TCP acks are "spoofed", as 
...
> you're safe, but they're wrong -- as the intermediate could fail.
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

how is this different from what you say next

> the data (it may never read it).

i.e. how is your "remote system" different from any intermediate in the
way -- you may have a better chance of detecting its failure, but no
guarantees, anyways. The receiving end could well be an on-board CPU+memory
on the network card (for however a bad idea this can be) and go
equally unnoticed.

Maybe we could say some intermediate device violates semantics iff
there is a procedure that deterministically (or with very high
probability) makes it behave differently from an implementation on
the end-system ?

	cheers
	luigi
----------------------------------+-----------------------------------------
 Luigi RIZZO, [email-masked]  . ACIRI/ICSI (on leave from Univ. di Pisa)
 http://www.iet.unipi.it/~luigi/  . 1947 Center St, Berkeley CA 94704
 Phone (510) 666 2927             .
----------------------------------+-----------------------------------------

---

From: Craig Partridge <[email-masked]>
Date: Mon, 08 Jan 2001 18:31:51 -0500

>> you're safe, but they're wrong -- as the intermediate could fail.

Hi Luigi:

That's an astute point, thanks!

The answer is that I view the probability of failure as part of the TCP
semantics.  That is, TCP says it provides connectivity between two end
points ("reliable inter-process communications between pairs of
processes in host computers...").

My view is that means that TCP's host-to-host behavior is a function solely
of the two end points.  (One could also say this view is a logical consequence
of the simple dumb network approach, of which IP is an example).

So my second example, where the receiver could fail to deliver the data after
ACKing it, in a normal TCP is solely a function of the receiver suffering
one of a (fairly short) list of errors.  Adding an intermediary doesn't
change the receiver probability, but adds the probability of the failure
of the intermediary.  So the probability of failure is now different from
what it was if just the two hosts were involved.

Thanks for an insightful question and I'll be interested to know what
you think of my reply :-)

Craig

---

From: Alhussein Abouzeid <[email-masked]>
Date: Mon, 8 Jan 2001 20:14:28 -0800 (PST)

What is a system? and what are "TCP end-to-end semantics"? Where are they
defined? 

I think saying remote and intermediate "system" does more harm
than good in clarifying the issue.

I do not think that the failure of the receiver to deliver data
to the application after ACKing it is a problem of the transport layer
anyway. If we accept layering, and we accept the end-to-end philosophy,
then the guarantee that a transport protocol provides is between the two
_transport_ end points not the two _application_ end points. Right?

Now, there can be two ways to treat the end-to-end argument. If you (or 
your application) are a hardliner and require that the transport
protocol ACK packets only if they are received at the destination, then
spoofing is a violation. If, on the other hand, you apply the end-to-end
on a "session" basis, i.e. a transport protocol will only terminate the
session when all packets of the session are received, then, in principle,
one can argue that there exists  an intermediary spoofer (e.g. that
doesn't complete the handshake except after the reception of all packets
at the receiver) that will not be violating the semantics, even if it
plays with the data packets/ACKs to its convenience during the course of
the session.

In other words, it depends on whether you define a "per packet" or a "per
session" semantics. I've looked, and I failed to find any substantial 
study on how this affects the application layer. I think that it will generally
depend on the application.

My 6 piastres (= 2 cents)

-Hussein.

---

From: Morten Schlaeger <[email-masked]>
Date: Tue, 09 Jan 2001 10:53:39 +0100

Some quotation from RFC793: 

[page 2]
"Some computer systems will be connected to networks via
  front-end computers which house the TCP and internet protocol layers,
  as well as network specific software.  The TCP specification describes
  an interface to the higher level protocols which appears to be
  implementable even for the front-end case, as long as a suitable
  host-to-front end protocol is implemented."

[page 8]
"The mechanisms of TCP do not preclude implementation of the TCP in a
  front-end processor.  However, in such an implementation, a
  host-to-front-end protocol must provide the functionality to support
  the type of TCP-user interface described in this document."

I think, we should differentiate between protocol semantic and interface
semantic.
From an application point of view not the TCP semantic
alone is important but also the semantic of the interface the
application uses to
communicate with the protocol stack.

Of course, when the acknowledgments are sent by some intermediate host
the meaning of
the acknowledgment has changed to some extent. If we would use an
application-network interface in which a "write-call" would return only
when the data are acknowledged by the peer TCP, then this semantic might
have some impact on the application design (although this gives
the sender no guarantee that the data was consumed by the destination
application).

Using the Berkeley socket interface the socket calls to send data return
when TCP has accepted the data for delivery (fits into the send-buffer,
assuming blocking mode). The
application is not informed about the success or failure of delivery. It
is even allowed to 
close the socket after passing some data to the socket. 
Although I agree, that the crash probability is increased when an
intermediate host is used,  there is no difference for the application
whether the acknowledgments are sent by the destination host or an
intermediate host. If it wants to implement a reliable data transfer it
must implement its own mechanisms.

The only possibility for the application to know about the status of the
data delivery
is to use the linger option. This option moves the important role to the
fin packet, which should not be acknowledged by the intermediate host
until all data are received by the final destination host (which still
is no guarantee that the data was consumed by the application).

I think, Hussein, this goes somehow in the same direction as your per
packet and per session semantic definition?

Best regards,

Morten

-- 
------------------------------------------------------------------------
Morten Schläger                              Tel.: ++49 (030) 314-23834
Technical University Berlin                   Fax.: ++49 (030) 314-23818
Telecommunication Networks Group (TKN)            [email-masked]
Sekr. FT 5-2/Einsteinufer 25    
10587 Berlin, Germany

---

From: Jacob Heitz <[email-masked]>
Date: Tue, 09 Jan 2001 07:45:36 -0800

I, the application, expect from you, TCP, the following:

When my peer application has received all the data I sent
in order and uncorrupted AND I have received all the data
the peer application has sent to me in order and uncorrupted, 
I expect a successful Close-Indication from you. If an 
unrecoverable error occurs, I expect an Error-Indication.

It's that simple.

The application indicates to TCP that it has no more data
to send with a Close-Request.

If you, TCP, cannot make that promise, then your usefulness
to me is greatly diminished and I need to do my own error
detection and correction and may as well use UDP.

---

From: Joe Touch <[email-masked]>
Date: Tue, 09 Jan 2001 09:50:46 -0800

> _transport_ end points not the two _application_ end points. Right?

The E2E argument makes assertions about the differences
between composing services (e.g., ACKs here) or not.
The ultimate effect of that would be applications that
write IP packets.

We tend to accept some slack inside the endhost as a tradeoff.

> plays with the data packets/ACKs to its convenience during the course of

The problem is that the end system can THINK all the packets have been
received, and have a different set of packets than were sent.

(see the earlier example I posted - where the spoofer ACKs,
the source window rolls-around, and then the path changes).

Joe

---

From: Fred Baker <[email-masked]>
Date: Tue, 09 Jan 2001 21:28:42 +0800

>What is a system? and what are "TCP end-to-end semantics"? Where are they

TCP's e2e semantics are described in RFC 793. With respect to the 
relationship to applications above TCP, it says:

   Much of this document is written in the context of TCP implementations
   which are co-resident with higher level protocols in the host
   computer.  Some computer systems will be connected to networks via
   front-end computers which house the TCP and internet protocol layers,
   as well as network specific software.  The TCP specification describes
   an interface to the higher level protocols which appears to be
   implementable even for the front-end case, as long as a suitable
   host-to-front end protocol is implemented.

Translation: the communication between TCP and its client applications is 
"reliable" in the same sense that communication between TCPs is "reliable". 
Between TCPs, "reliable" means that either the packets will be delivered 
and acknowledged, or after some number of retransmission attempts TCP will 
take the connection down and advise its client application of the failure. 
Between TCP and its client, that communication is provided by the operating 
system, and will either deliver the data or will inform both TCP and the 
application that the OS link has failed. It is technically possible that 
TCP could acknowledge the delivery of the data to a hung application and 
exchange FIN/FIN-ACK, and then have the application die an untimely death 
without fully processing the data, but the presumption is that OS failure 
or application failure at that specific point is so unlikely that it is 
acceptable to leave that to the application or the user to detect and correct.

If TCP is terminated somewhere else - the above text mentions front-end 
processors - the clear expectation is that the communication link between 
the TCP and the client remains "reliable". I think the problem that Craig 
is mentioning is that when TCP Acks are spoofed, the probability of that 
end case is greater - the link between the guy spoofing the Ack and the 
ultimate destination is not necessarily as well guaranteed. It seems to me 
that this concern can be obviated only by having the spoofer cache the data 
exchanged on the connection and itself assure the delivery of the data - 
retransmit.

>_transport_ end points not the two _application_ end points. Right?

Of course, the ultimate judge of whether the right thing happened has to be 
the user of the application. But using that argument to justify failing to 
deliver the data to the application does indeed significantly weaken the 
legitimate expectations of the user. Per the text I quoted above, the user 
can legitimately expect that if TCP says the data was delivered, the data 
was indeed delivered to the application - only an OS failure or an 
application failure will cause the application to not receive and consume 
it. If you go on to argue that this is not a legitimate expectation, then 
all applications have to have some form of reliability guarantee in them as 
well.

---

From: Fred Baker <[email-masked]>
Date: Wed, 10 Jan 2001 05:53:19 +0800

By the way, I missed the initial message in this thread. What is proposed? 
Is it suggested that we move the acknowledge pointer (the sequence number 
of the next octet that the receiver expects to receive), or increase the 
window amount?