RFC 983

ISO transport arrives on top of the TCP

πŸ“… published April 1986, from ietf

RFC 983: ISO Transport Services on Top of the TCP πŸŽ€

bestie, this is RFC 983, and the title block is giving "classic networking drama" πŸ’… It was written by D. E. Cass and M. T. Rose, both from NRTC, and it's dated April 1986. Its category is a proposed protocol standard for the ARPA Internet community (you'll see that in the Status section). The header doesn't list anything it obsoletes or updates, so there's no backstory to dig through πŸ™ˆ

Status of This Memo ✨

okay so first, the official vibe check 🧚 This memo is a proposed protocol standard for the ARPA Internet community. Hosts in the ARPA-Internet that choose to implement ISO TSAP services on top of TCP are expected to adopt and implement this standard. Suggestions for improvement are encouraged, and you're free to distribute this memo as much as you want πŸ’–

1. Introduction and Philosophy πŸ¦‹

okay so the ARPA Internet crew already has a super mature set of transport and internetwork protocols (TCP/IP), and they're honestly really successful at giving end-users network and transport services. Meanwhile the CCITT and the ISO have defined a bunch of session, presentation, and application recommendations that the international community and tons of vendors have adopted 🌸 The goal is to offer those higher-level services directly on the ARPA Internet without wrecking the stuff that already works. That way people can build expertise with ISO and CCITT applications that weren't previously available on the ARPA Internet. It also gives us a smoother route from TCP/IP networks to ISO-based networks, in the medium and long term πŸ“

There are two ways to "port" an ISO or CCITT application to a TCP/IP setup. The first is to port each application on its own, building local protocols on top of TCP. This is useful short-term, since you can whip up special-purpose interfaces to TCP quickly, but it lacks generality πŸ™ƒ

The second approach is based on the fact that both the ARPA Internet protocol suite and the ISO protocol suite are layered systems. (The ARPA one is more pragmatic about its layering, though πŸ’€) A key idea behind layering is layer-independence. Most readers already know this, but we need a little background to introduce the concept 🫢

Externally, a layer is defined by two things:

  • a service-offered definition, which describes the services the layer provides and the interfaces it gives you to access them; and,
  • a service-required definition, which describes the services the layer uses and the interfaces it uses to access them.

All the entities in the network that cooperate to provide the service are known as the service-provider. Each individual one is a service-peer πŸ‘‘

Internally, a layer is defined by one thing:

  • a protocol definition, which describes the rules each service-peer follows when it talks to other service-peers.

Putting it all together, the service-provider uses the protocol and services of the layer below to offer its service to the layer above. Protocol verification is basically about proving that this really happens (and it's also a fertile field for loads of computer science PhD dissertations πŸ€“).

The concept of layer-independence is pretty simple:

IF one preserves the services offered by the service-provider THEN the service-user is completely naive with respect to the protocol which the service-peers use

For this memo, we use layer-independence to define a Transport Service Access Point (TSAP). It looks exactly like the services and interfaces offered by the ISO/CCITT TSAP (as defined in [ISO-8072]), but the internals are built on TCP/IP (as defined in [RFC-793,RFC791]) instead of the ISO/CCITT transport and network protocols. So the ISO/CCITT higher-level layers (all session, presentation, and application entities) can run fully without knowing they're on a TCP/IP internetwork. Iconic, right? ✨

The authors hope this paragraph won't shock most readers. But an ALARMING number of people seem to think layering is just a way of chopping a big problem into smaller ones, simply for the sake of chopping it up 😭 Layering does tend to bring modularity into an architecture, and modularity tends to bring sanity into implementations (both conceptual and physical). But modularity, by itself, isn't the end goal. Flexibility IS πŸ’œ

2. Motivation 🌈

When you're migrating from TCP/IP to the ISO protocols, there are several strategies you could try. This memo was written with one particular strategy in mind 🎯

The migration strategy this memo uses is based on gatewaying between the TCP/IP and ISO protocol suites at the transport layer. There are two strong arguments for this approach:

  • a. Experience teaches us that it takes just as long to get good implementations of the lower-level protocols as it does for the higher-level ones. In particular, a lot of work is still going on at the ISO network and transport layers, so implementations of protocols above those layers aren't being aggressively pursued. So something has to happen "now" to provide a medium in which the higher-level protocols can be developed. Since TCP/IP is mature and essentially provides identical functionality, it's an ideal medium for that development 🧚
  • b. Implementing gateways at the IP and ISO IP layers is probably not of general use in the long term. In effect, it would require each Internet host to support both TP4 and TCP. So a better strategy is a graceful migration path from TCP/IP to ISO protocols for the ARPA Internet, once the ISO protocols have matured enough πŸ‘

Both of these arguments point to gatewaying happening at or above the transport layer service access point. Also, the first argument suggests the best move is to gateway exactly AT the transport service access point, so that the most ISO layers can be developed πŸ”₯

NOTE: This memo does not intend to act as a migration or intercept document. It is intended ONLY to meet the needs discussed above. However, it would not be unexpected for the protocol described in this memo to form part of an overall transition plan. The description of such a plan, however, is COMPLETELY beyond the scope of this memo. πŸ™ˆ

Finally, in general, building gateways between other layers of the TCP/IP and ISO protocol suites is problematic at best πŸ’€

To summarize: the primary motivation for the standard in this memo is to make it easier to gain experience with higher-level ISO protocols (session, presentation, and application). The stability and maturity of TCP/IP are ideal for providing solid transport services, no matter the actual implementation ✨

3. The Model 🧩

The [ISO-8072] standard describes the ISO transport service definition, which we'll call TP from here on πŸ’–

ASIDE: This memo references the ISO specifications rather than the CCITT recommendations. The differences between these parallel standards are quite small, and can be ignored (for this memo, without loss of generality). For the relationships: Transport service [ISO-8072] [X.214] Transport protocol [ISO-8073] [X.224] Session protocol [ISO-8327] [X.225]

The ISO transport service definition describes the services offered by the TS-provider (transport service) and the interfaces used to access those services. This memo focuses on how the ARPA Transmission Control Protocol (TCP) [RFC-793] can be used to offer those services and provide those interfaces πŸ¦‹

   +-------------+                                      +-------------+
   |   TS-user   |                                      |   TS-user   |
   +-------------+                                      +-------------+
           |                                                   |
           | TSAP interface                     TSAP interface |
           |  [ISO-8072]                                       |
           |                                                   |
   +------------+   ISO Transport Services on the TCP    +------------+
   |   client   |----------------------------------------|   server   |
   +------------+              (this memo)               +------------+
           |                                                   |
           | TCP interface                       TCP interface |
           |  [RFC-793]                                        |
           |                                                   |

For expository purposes, here are the abbreviations:

  • TS-peer: a process that implements the protocol described by this memo
  • TS-user: a process talking using the services of a TS-peer
  • TS-provider: the black-box entity implementing the protocol described by this memo

For this memo, which describes version 1 of the TSAP protocol, all aspects of [ISO-8072] are supported with one exception: Quality of Service parameters πŸŽ€

In the spirit of CCITT, this one is left "for further study" πŸ“š Version 2 of the TSAP protocol will most likely support the QOS parameters for TP by mapping them onto various TCP parameters πŸ‘€

TP supports the notion of a session port (termed a TSAP ID), but the list of reserved ISO TSAP IDs isn't clearly defined yet. So this memo takes the approach of isolating the TCP port space from the TSAP ID space, and uses a single TCP port: TCP port 102 is reserved for this purpose. This protocol manages its own TSAP ID space, independent of TCP. Appendix A of this memo lists reserved TSAP IDs for version 1 of this TSAP protocol. Future editions of the "Assigned Numbers" document [RFC-960] are expected to update this list. (Curious readers are encouraged to read [ISO-8073] and try to figure out exactly what a TSAP ID is πŸ™ƒ)

Last but not least, the ISO TSAP is fundamentally symmetric in behavior. There's no underlying client/server model 🫢 Instead of a server listening on a well-known port, when a connection is established, the TS-provider generates an INDICATION event. The TS-user presumably catches it and acts on it. Although this could be implemented by having a server "listen" by hanging on the INDICATION event, from the ISO TSAP's point of view, all TS-users just sit around in the IDLE state until they either generate a REQUEST or accept an INDICATION πŸ’…

4. The Primitives ✨

Okay bestie, so the protocol assumes that TCP [RFC-793] gives it a set of service primitives. Here are the events first πŸ‘€

  • connected - open succeeded (either ACTIVE or PASSIVE)
  • connect fails - ACTIVE open failed
  • data ready - data can be read from the connection
  • errored - the connection has errored and is now closed
  • closed - an orderly disconnection has started

And the actions πŸ’…

  • listen on port - PASSIVE open on the given port
  • open port - ACTIVE open to the given port
  • read data - data is read from the connection
  • send data - data is sent on the connection
  • close - the connection is closed (pending data is sent)

The protocol also offers its own service primitives to the TS-user, as defined in [ISO-8072]. The events are:

  • T-CONNECT.INDICATION
    • a TS-user (server) is notified that connection establishment is in progress
  • T-DISCONNECT.INDICATION
    • a TS-user is notified that the connection is closed
  • T-CONNECT.CONFIRMATION
    • a TS-user (client) is notified that the connection has been established
  • T-DATA.INDICATION
    • a TS-user is notified that data can be read from the connection
  • T-EXPEDITED DATA.INDICATION
    • a TS-user is notified that "expedited" data can be read from the connection

And the actions πŸ¦‹

  • T-CONNECT.RESPONSE
    • a TS-user (server) indicates that it will honor the request
  • T-DISCONNECT.REQUEST
    • a TS-user indicates that the connection is to be closed
  • T-CONNECT.REQUEST
    • a TS-user (client) indicates that it wants to establish a connection
  • T-DATA.REQUEST
    • a TS-user sends data
  • T-EXPEDITED DATA.REQUEST
    • a TS-user sends "expedited" data

5. The Protocol πŸ’–

So the goal here is to offer a TP interface on top of TCP. The good news is that TCP already does almost everything the TS-provider offers the TS-user, so the hard stuff in the transport layer (e.g., three-way handshakes, choice of ISS, windowing, multiplexing, ad infinitum) is all handled by TCP already πŸ™Œ

Even though TP is symmetric, it's still useful to think about the protocol through a client/server lens πŸŽ€

The info that TSAP-peers swap around comes in packets called "TPKT"s. The format is described in the next section. For what we're about to go through, every TPKT has a code, and it's one of these:

  • CR - request connection
  • CC - confirm connection
  • DR - request disconnection
  • DT - data
  • ED - expedited data

A TSAP server starts by LISTENing on TCP port 102. When a TSAP client successfully connects to that port, the protocol kicks off πŸš€

A client decides to connect when a TS-user issues a T-CONNECT.REQUEST action. That action specifies the TSAP ID of the remote TS-user, whether expedited data is to be supported, and (optionally) some initial TS-user data. The client looks at the TSAP ID it was given to figure out the IP address of the server. If the expedited data option was requested, the client opens a passive TCP port in non-blocking mode and notes the port number. This TCP port is called the "expedited port". Then the client tries to open a TCP connection to the server on port 102. If that doesn't work, the client fires T-DISCONNECT.INDICATION for the TS-user, giving the reason for the failure, and closes the expedited port if there is one 😭 If it does work, the client sends a TPKT with code CR containing:

  • the TSAP ID of the TS-user on the client's host (the "caller")
  • the TSAP ID of the TS-user that the client wants to talk to (the "called")
  • if the expedited data option was requested, the TSAP ID of the expedited port for the client's host
  • any TS-user data from the T-CONNECT.REQUEST

Now the client just waits for a response ⏳

The server gets the TPKT and validates its contents (checking the version number, verifying that the code is CR, and so forth). If the packet is invalid, the server sends a TPKT with code DR specifying "PROTOCOL ERROR", closes the TCP connection, and goes back to the LISTEN state πŸ’€

If the packet is valid, the server checks which TSAP ID the remote TS-user wants to talk to. If the TS-user it names can be located and started (e.g., the right program that implements the protocol is there), the server starts that TS-user by firing T-CONNECT.INDICATION. Otherwise, the server sends a TPKT with code DR specifying either "SESSION ENTITY NOT ATTACHED TO TSAP" or "REMOTE TRANSPORT ENTITY CONGESTED AT CONNECT REQUEST TIME", whichever fits, closes the TCP connection, and goes back to the LISTEN state.

Now the server waits for either a T-CONNECT.RESPONSE or a T-DISCONNECT.REQUEST from the TS-user it started. If it's the latter, the server sends a TPKT with code DR containing the reason for the disconnect that the TS-user supplied.

After that, the server closes the TCP connection and goes back to the LISTEN state πŸ”

If it's a T-CONNECT.RESPONSE instead, the server checks whether an expedited port was specified in the connection request. If one was, the server opens a second TCP connection and connects to the specified port. If that connection fails, the server sends a TPKT with code DR specifying "CONNECTION NEGOTIATION FAILED", closes the TCP connection, and goes back to the LISTEN state. If the connection succeeds, the server notes the local port number it used to connect to the expedited port ✨

If the TPKT with code CR didn't specify an expedited port, but the server's TS-user says it wants to use expedited data, then the server sends a TPKT with code DR specifying "CONNECTION NEGOTIATION FAILED", fires T-DISCONNECT.INDICATION with this error to the TS-user, closes the TCP connection, and goes back to the LISTEN state.

Next, the server sends a TPKT with code CC containing:

  • the TSAP ID of the TS-user responding to the connection (usually the "called")
  • if an expedited port was specified in the TPKT with code CR, the TSAP ID of the port number on the server's host that was used to connect to the expedited port
  • any TS-user data from the T-CONNECT.RESPONSE

Once the TPKT is sent, the server enters the SYMMETRIC PEER state 🫢

The client gets the TPKT and validates it (checking the version number, verifying that the code is CC or DR, and so forth). If the packet is invalid, the client sends a TPKT with code DR specifying "PROTOCOL ERROR", fires T-DISCONNECT.INDICATION with this error to the TS-user, and closes the TCP connection (and the expedited port, if there is one).

If the packet's code is DR, the client fires T-DISCONNECT.INDICATION with the reason given in the TPKT to the TS-user, and closes the TCP connection (and the expedited port, if there is one).

If the packet's code is CC, the client checks whether an expedited port was specified and whether a connection is waiting on that expedited port. If not, a protocol error has happened, a TPKT with code DR is returned, T-DISCONNECT.INDICATION is fired, and so on. Otherwise, the client checks the remote address that connected to the expedited port. If it's different from the port listed in the TPKT with code CC, a protocol error has happened. Otherwise, everything's good 🌈 Two TCP connections have now been established: one for all TPKTs except expedited data, and a second one used exclusively for expedited data.

The client now fires T-CONNECT.CONFIRMATION and enters the SYMMETRIC PEER state.

Once both sides have reached the SYMMETRIC PEER state, the protocol is completely symmetric and the client/server idea just kind of disappears πŸ¦‹ Both TS-peers behave the same way from here on:

If the TCP indicates that data can be read, the TS-peer validates the contents of the TPKT it receives. If the packet is invalid, the TS-peer sends a TPKT with code DR specifying "PROTOCOL ERROR", fires T-DISCONNECT.INDICATION with this error to the TS-user, and closes the TCP connection (and the expedited data connection, if there is one). If the TS-peer was the server, it goes back to the LISTEN state.

NOTE: If the expedited data option was requested, then there are two TCP connections that can supply data for reading. The dialogue below assumes that only ED TPKTs are read from the expedited data connection. For simplicity's sake, when reading from TCP the relation between connections and TPKTs is unimportant and this memo URGES all implementations to be very lenient in this regard. When writing to TCP, implementations should use the expedited data connection only to send TPKTs with code ED. Section 7 of this memo discusses the handling of expedited data in greater detail.

If the packet's code is DR, the TS-peer fires T-DISCONNECT.INDICATION with the reason given in the TPKT to the TS-user, and closes the TCP connection (and the expedited data connection, if there is one). If the TS-peer was the server, it goes back to the LISTEN state.

If the packet's code is ED or DT, the TS-peer fires T-DATA.INDICATION or T-EXPEDITED DATA.INDICATION, whichever fits, with the enclosed user data for the TS-user. Then it goes back to the SYMMETRIC PEER state πŸ’œ

If the packet is invalid, the TS-peer sends a TPKT with code DR specifying "PROTOCOL ERROR", fires T-DISCONNECT.INDICATION with this error to the TS-user, and closes the TCP connection (and the expedited data connection, if there is one). If the TS-peer was the server, it goes back to the LISTEN state.

If the TCP indicates that an error has happened and the connection has closed, the TS-peer fires T-DISCONNECT.INDICATION to the TS-user with the reason for the failure. If the expedited data connection is still open, it gets closed. If the TS-peer was the server, it goes back to the LISTEN state.

If the TS-user issues a T-DATA.REQUEST or T-EXPEDITED DATA.REQUEST action, the TS-peer sends a TPKT with code DT or ED containing the TS-user data. Then it goes back to the SYMMETRIC PEER state.

If the TS-user issues a T-DISCONNECT.REQUEST action, the TS-peer sends a TPKT with code DR containing the reason for the disconnect that the TS-user supplied. The TS-peer then closes the TCP connection (and the expedited data connection, if there is one). If the TS-peer was the server, it goes back to the LISTEN state. Bye bye πŸ‘‹

Now for the (augmented) state tables, which explain the whole thing in a more organized way πŸ“ The server starts in state S0 and the client starts in state C0. "TCP:" refers to an event or action from the TCP service, and "SS:" refers to an event or action from the TS-user (e.g., the ISO session service [ISO-8327]).

                        S E R V E R   S T A T E S

   state        event                   action                      goto
   -----        -----                   ------                      ----
   S0                                   TCP: listen on port 102     S1

   S1           TCP: connected          TCP: read TPKT
                                        parse, on error
                                          TCP: send DR, close       S0
                                        code is CR
                                          start session server
                                          SS: T-CONNECT             S2
                                                .INDICATION
                                        otherwise,
                                          TCP: send DR, close       S0

Okay so the state tables keep going, and the S2 rows are next πŸ’…

   S2           SS: T-CONNECT.RESPONSE  if expedited option,
                                          TCP: open port EXPD
                                        TCP: send CC                P0

   S2           SS: T-DISCONNECT        TCP: send DR, close         S0
                        .REQUEST

Any event that shows up for a state not listed above counts as an error, and here's how that gets handled πŸ™ˆ

   state        event                   action                      goto
   -----        -----                   ------                      ----
   S*           TCP: other              if TCP is open, TCP: close  S0
                                        otherwise ignore            S0
   S*           SS: other               SS: T-DISCONNECT
                                              .INDICATION
                                        if TCP is open, close       S0

Now the client side πŸŽ€

                        C L I E N T   S T A T E S

   state        event                   action                      goto
   -----        -----                   ------                      ----
   C0           SS: T-CONNECT.REQUEST   if expedited option,
                                          TCP: non-blocking
                                               listen on port EXPD
                                        TCP: open port 102          C1

   C1           TCP: connected          TCP: send CR                C2

   C1           TCP: connect fails      TCP: close
                                        SS: T-DISCONNECT            C0
                                                 .INDICATION


   C2           TCP: data ready         TCP: read TPKT
                                        parse, on error
                                          TCP: send DR, close
                                          SS: T-DISCONNECT          C0
                                                .INDICATION
                                        code is CC
                                          if expedited option,
                                             verify port EXPD
                                             connected correctly,
                                             if not, treat as error
                                          SS: T-CONNECT             P0
                                                .CONFIRMATION
                                        code is DR
                                          TCP: close
                                          SS: T-DISCONNECT          C0
                                                .INDICATION
                                        otherwise
                                          TCP: send DR, close
                                          SS: T-DISCONNECT          C0
                                                .INDICATION

Same deal for anything weird on the client side. It's an error, and it gets handled like this πŸ’€

   state        event                   action                      goto
   -----        -----                   ------                      ----
   C*           TCP: other              if TCP is open, close       C0
                                        otherwise ignore            C0

   C*           SS: other               SS: T-DISCONNECT
                                              .INDICATION
                                        if TCP is open, close       C0

And finally, the peer states 🧚

                          P E E R   S T A T E S

   state        event                   action                      goto
   -----        -----                   ------                      ----
   P0           TCP: data ready         TCP: read TPKT
                                        parse, on error
                                          TCP: send DR, close
                                          SS: T-DISCONNECT          end
                                                .INDICATION
                                        code is DT
                                          SS: T-DATA.INDICATION      P0
                                        code is ED
                                          SS: T-EXPEDITED DATA       P0
                                                .INDICATION
                                        code is DR
                                          TCP: close
                                          SS: T-DISCONNECT          end
                                                .INDICATION
                                        otherwise
                                          TCP: send DR, close
                                          SS: T-DISCONNECT          end
                                                .INDICATION

   P0           TCP: other              TCP: close
                                        SS: T-DISCONNECT            end
                                                  .INDICATION

   P0           SS: T-DATA.REQUEST      TCP: send DT                 P0

   P0           SS: T-EXPEDITED DATA    TCP: send ED                 P0
                        .REQUEST

   P0           SS: T-DISCONNECT        TCP: send DR, close         end
                        .REQUEST

   P0           SS: other               TCP: send DR, close
                                        SS: T-DISCONNECT            end
                                                .INDICATION

6. Packet Format ✨

Two TS-peers swap info over a TCP connection by wrapping it up in well-defined packets 🎁 A packet, which the earlier sections call "TPKT," is basically an object made of a whole number of octets, and its length can vary.

NOTE: For the purposes of presentation, these objects are shown as being 4 octets (32 bits wide). This representation is an artifact of the style of this memo and should not be interpreted as requiring that a TPDU be a multiple of 4 octets in length.

A packet has two parts: a packet-header and a pseudo-TPDU. The packet-header looks the same no matter what kind of packet it is. The pseudo-TPDU follows the [ISO-8073] recommendation very closely, with the exceptions listed below. Per [ISO-8073], each TPDU has two parts: a header and data.

It is EXTREMELY important to observe that TPKTs represent "indivisible" units of data to the TS-user 🌈 So a T-DATA.REQUEST from the TS-user at the sending end should result in exactly one T-DATA.INDICATION (with exactly that data) for the TS-user at the receiving end. To make this work, any INDICATION event from a TPKT should be started ONLY after the entire TPKT has been fully received. Also, the TS-peer should generate exactly one such INDICATION event. The packet length field can hold on the order of 65K octets of user data, which should be way more than any SPDU (Session Protocol Data Unit) needs in a real implementation. Because of that, version 1 of this protocol doesn't need to fragment or re-assemble TS-user data at all πŸ’– If an application shows up that needs an SPDU bigger than 65K octets, this memo will be revised.

The packet-header is laid out like this πŸ‘‘

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |      vrsn     |    reserved   |          packet length        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Where:

1. vrsn (8 bits): This field is always 1 for this memo.

2. packet length (16 bits, min=8, max=65535): The length of entire packet in octets, including packet-header.

The TPDU format (re-phrased from [ISO-8073]) depends on the type of TPDU. Every TPDU starts with a fixed-part header length and the code, and whatever comes after the code changes based on the code's value. In the context of this memo, these codes are valid:

  • CR: connect request
  • CC: connect confirm
  • DR: disconnect request
  • DT: data
  • ED: expedited data

The CR or CC TPDU looks like this πŸ¦‹

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      | header length | code  | credit|     destination reference     |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |       source reference        | class |options| variable data |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |    ...        |      ...      |      ...      |      ...      |
      |    ...        |      ...      |      ...      |      ...      |
      |    ...        |   user data   |      ...      |      ...      |
      |    ...        |      ...      |      ...      |      ...      |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Where:

3. header length (8 bits, min=6, max=min(254,packet length-6)): The TPDU-header length in octets, including parameters but excluding the header length field and user data (if any).

4. code (4 bits): The type of TPDU. In the context of this memo, the values are:

            value       meaning
            -----       -------
             14         CR: connection request  (binary 1110)
             13         CC: connection confirm  (binary 1101)
              8         DR: disconnect request  (binary 1000)
             15         DT: data                (binary 1111)
              1         ED: expedited data      (binary 0001)
            all other   reserved

5. credit (4 bits): This field is always ZERO on output and ignored on input.

6. destination reference (16 bits): This field is always ZERO on output and ignored on input.

7. source reference (16 bits): This field is always ZERO on output and ignored on input.

8. class (4 bits): This field is always 4 (binary 0100) on output and ignored on input. It is anticipated that future versions of this protocol will make use of this field.

9. options (4 bits): This field is always ZERO on output and ignored on input.

10. variable data ((header length - 6) octets): This portion of the TPDU is of variable length. For most TPDUs, this portion is empty (the header length field of the TPDU is exactly 6). The contents of the variable data consist of zero or more "parameters." Each parameter has this format:

            parameter code        1 octet in size
            parameter length      1 octet in size, value is the number
                                    of octets in parameter value
            parameter value       parameter data

Normally, the parameter length is 1 octet. Any implementation conforming to this version of the protocol must recognize all parameter types listed in [ISO-8073]. Apart from the parameters listed below, these parameters are simply ignored.

  • Parameter name: Transport service access point identifier (TSAP-ID) of the client TSAP
  • Parameter code: 193 (binary 1100 0001)
  • Parameter length: variable
  • Parameter value: TSAP-ID attributes

Each TSAP-ID consists of 1 or more attributes. Each attribute has this format:

Okay so the attribute stuff is giving tiny labeled boxes πŸ“¦βœ¨. Every attribute gets a code, a length, and then its value, bestie. Only two attributes exist in version 1, and everything else is reserved πŸ”’.

   Attribute code      1 octet in size
   Attribute length    1 octet in size, value is the number
                         of octets in attribute value
   Attribute value     attribute data

In version 1 of this protocol, only two attributes are defined. All others are reserved πŸ™ˆ

   Attribute name:     Internet Address

   Attribute code:     1
   Attribute length:   6
   Attribute value:    IP address (4 octets)
                       session port (2 octets, unsigned
                       integer)

This attribute is ALWAYS required πŸ’– Values for session port can be found in Appendix A of this memo πŸŽ€

   Attribute name:     Internet Address for Expedited Data

   Attribute code:     2
   Attribute length:   6
   Attribute value:    IP address (4 octets)
                       TCP port (2 octets, unsigned integer)

This attribute is required ONLY if expedited data is to be exchanged πŸ”₯ The attribute value is an <IP address, TCP port> pair that the TS-peer picks for use with expedited data πŸ¦‹

Now the parameters, which are the extra add-ons 🧚 Here's the first one:

Parameter name:       TSAP-ID of the server TSAP
Parameter code:       194 (binary 1100 0010)
Parameter length:     variable
Parameter value:      TSAP-ID attributes

Next up is the additional option selection parameter, and this one is lowkey the star of the show πŸ‘‘

Parameter name:       Additional option selection
Parameter code:       198 (binary 1100 0110)
Parameter length:     1
Parameter value:      additional flags

The additional flags octet is 8 bits of optional flags 🌸 Only one bit actually matters for this memo. The rest should be ZERO on output and ignored on input 🫢 That one bit says whether the transport expedited data service is going to be used. If the bit is set (bit mask 0000 0001), or this parameter just doesn't show up in the TPDU, then the expedited data service is requested. If the parameter is in the TPDU and the bit is not set, then the service is disabled πŸ’€ And if the service is requested, the TSAP-ID of the sender of the TPDU has to include an attribute that says which internet address to use for expedited data 😭

The last parameter is the alternative protocol classes one 🌈

Parameter name:       Alternative protocol classes
Parameter code:       199 (binary 1100 0111)

Parameter length:     variable
Parameter value:      64 (binary 0100 0000) in each octet

This one is used as a NOOP in the variable data. Its use is HIGHLY discouraged πŸ™ˆ But for implementors who want to line up the user data part of the TPDU on word (or page) boundaries, using this parameter for filling is recommended πŸ“

Then comes the user data field, the actual tea β˜•

11.  user data            (packet length - header length - 5)
                             octets

This part of the TPDU is the actual user data, most probably one or more SPDUs (session protocol data units) πŸ’œ

Okay, now the DR TPDU. Here's the layout 🧁

    0                   1                   2                   3
    0 1  2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | header length | code  | credit|     destination reference     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       source reference        |     reason    | variable data |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    ...        |      ...      |      ...      |      ...      |
   |    ...        |      ...      |      ...      |      ...      |
   |      ...      |   user data   |      ...      |      ...      |
   |    ...        |      ...      |      ...      |      ...      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The fields are the same as a CR or CC TPDU, with a few exceptions ✨ Here they are:

where:

8.  reason                        8 bits

This replaces the class/option fields of the CR or CC TPDU πŸ’… Any value from [ISO-8073] can go in this field. This memo uses several of them, and here they are:

    value       meaning
    -----       -------
      1         Congestion at TSAP
      2         Session entity not attached to TSAP
      3         Address unknown (at TCP connect time)
    128+0       Normal disconnect initiated by the session
                entity
    128+1       Remote transport entity congestion at connect
                request time
    128+3       Connection negotiation failed
    128+5       Protocol Error
    128+8       Connection request refused on this network
                connection

Now the DT or ED TPDU, which is the data-carrying one πŸ¦‹ Here's its layout:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-+
   | header length | code  | credit|         TPDU-NR and EOT       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   user data   |      ...      |      ...      |      ...      |
   |    ...        |      ...      |      ...      |      ...      |
   |    ...        |      ...      |      ...      |      ...      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
where:

After the credit field (which is always ZERO on output and ignored on input), there's one more field before the user data 🌷

6.  TPDU-NR and EOT               16 bits

This field is always ZERO on output and ignored on input 🧚

7. Expedited Data ✨

This memo uses a second TCP connection to handle expedited data, and it does not use the TCP URGENT mechanism πŸ”₯ The main downside is that single-threaded implementations of TCP might struggle to run two connections at the same time 😬 But there are a few upsides to this approach:

  • a. Using one connection for the expedited data semantics would mean the TSAP peer has to manage a set of buffers that are separate from TCP 🧩 The peer would, once it gets an indication of TCP urgent information, have to buffer all preceding TPKTs until the TCP buffer is empty. Then the expedited data gets handed to the TS-user. Once the expedited data is flushed, the buffered (non-expedited) data can be passed up to the receiving user.
  • b. It assumes implementations handle TCP urgency correctly. That might be an untrue assumption, especially when TCP urgency happens while the send window is zero-sized πŸ’€ It also assumes implementations can signal this event to the TCP-user in a meaningful way. In a single-threaded implementation, that's not likely πŸ™ˆ

Given a reasonable TCP implementation, the TS-peer needs to listen on two TCP sockets, either in polling or interrupt mode 🫢 When the TS-peer gets data, TCP has to indicate which connection should be read from.

The only tricky part of the protocol is that the client has to be able to start a passive OPEN for the expedited port, and then wait to read from another connection πŸŒ€ Between the passive OPEN and the other connection supplying data, the server will connect to the expedited port before it sends data on the other connection. To sum up Section 5, the sequence of events with respect to TCP is:

time      client                          Server
----      ------                          ------
0.                                        passive OPEN of port 102

1.        T-CONNECT.REQUEST from user
          passive OPEN of expedited
          port (non-blocking)

2.        active OPEN of port 102

3.        send CC TPKT

4.                                        port 102 connected

5.                                        receive CC TPKT
                                          T-CONNECT.INDICATION to
                                          user
                                          T-CONNECT.RESPONSE from
                                          user

6.                                        active OPEN to expedited
                                          port

7.        expedited port connected

8.                                        send CR TPKT

9.        receive CR TPKT
          verify expedited port
          connected correctly

Multi-threaded implementations of TCP should be able to support this sequence of events without any great difficulty πŸŒΈπŸ’œ

8. Conclusions ✨

okay so there are two design decisions worth talking about, bestie 🫢 The first one is the packet format. It's pretty obvious that the TP packet format was the one picked for this memo πŸ“¦ Yes, it means a few fields just get ignored (like source reference), but it's not giving "too much overhead" πŸ’… On a connection request packet (the worst case), there are 6 bytes of "zero on output, ignore on input" fields. Since the packet overhead processing is fixed anyway, asking implementers to allocate an extra 1.5 words is totally reasonable, not unreasonable!! πŸŽ€ Also, some of these fields (like class) might get used in future versions of the protocol as people learn more 🌸

The second decision is about how the TCP and TSAP port space gets administered 🌈 Honestly, it's probably a very bad idea to take on any responsibility whatsoever for managing this addressing space, even after ISO has stabilized 😭 There are two issues here. First, at what level do the TCP and TSAP port spaces interact? Second, who defines what that interaction looks like? For the first one, it's wholly undesirable to require that each TSAP port maps to a unique TCP port. The admin headache for the TCP "numbers czar (and czarina)" would be non-trivial πŸ’€ So it's desirable to allocate a single TCP port, namely port 102, as the place where the "ISO Transport Services" live in the TCP domain πŸ¦‹ For the second one, the interaction defined in Appendix A of this memo is embryonic at best πŸ™ˆ It will no doubt get replaced once the ISO world reaches convergence on how services are addressed in ISO TP. So readers (and implementors) are asked to keep in mind that this part of the memo is guaranteed to change. Unfortunately, the authors aren't allowed the luxury of waiting for an ISO consensus 😀 So the minimal effort approach in the appendix below was adopted. Iconic, honestly πŸ‘‘

A prototype implementation of the protocol in this memo is available for 4.2BSD UNIX 🧚 If you're interested, contact the authors for a copy. Quick peek at how it works: each ISO service is its own separate program. A daemon listens on TCP port 102, checks a database when a connection request packet comes in, and fires off the right program for the ISO service requested πŸ“ Given how BSD TCP works, once the child fires, responsibility for that connection is delegated to the child, and the daemon goes right back to listening for new connection requests πŸ’œ The prototype consists of both the daemon program and subroutine libraries that get loaded with programs providing ISO services ✨


9. References πŸ“š

[ISO-8072] ISO. "International Standard 8072. Information Processing Systems -- Open Systems Interconnection: Transport Service Definition." (June, 1984)

[ISO-8073] ISO. "International Standard 8073. Information Processing Systems -- Open Systems Interconnection: Transport Protocol Specification." (June, 1984)

[ISO-8327] ISO. "International Standard 8327. Information Processing Systems -- Open Systems Interconnection: Session Protocol Specification." (June, 1984)

[RFC-791] Internet Protocol. Request for Comments 791 (September, 1981) (See also: MIL-STD-1777)

[RFC-793] Transmission Control Protocol. Request for Comments 793 (September, 1981) (See also: MIL-STD-1778)

[RFC-960] Assigned Numbers. Request for Comments 960 (December, 1985)

[X.214] CCITT. "Recommendation X.214. Transport Service Definitions for Open Systems Interconnection (OSI) for CCITT Applications." (October, 1984)

[X.224] CCITT. "Recommendation X.224. Transport Protocol Specification for Open Systems Interconnection (OSI) for CCITT Applications." (October, 1984)

[X.225] CCITT. "Recommendation X.225. Session Protocol Specification for Open Systems Interconnection (OSI) for CCITT Applications." (October, 1984)

[X.410] CCITT. "Recommendation X.410. Message Handling Systems: Remote Operations and Reliable Transfer Server." (October, 1984)


Appendix A: Reserved TSAP IDs πŸŽ€

Version 1 of this protocol uses a relatively simple encoding scheme for TSAP IDs πŸ’– A TSAP ID is an attribute list with two parameters: a 32-bit IP address and a 16-bit port number. This is used to identify both the client TSAP and the server TSAP. When it appears in a TPKT with code CR or CC, the TSAP ID is encoded in the variable data part. For the client TSAP it looks like this:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      193      |       8       |       1       |       6       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       a       |       b       |       c       |       d       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              port             |                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

And for the server TSAP it looks like this:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      194      |       8       |       1       |       6       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       a       |       b       |       c       |       d       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              port             |                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

(Neither of these examples include an attribute for a TCP connection for expedited data πŸ™ˆ If one were present, the length of the TSAP ID attribute would be 16 instead of 8, and the 8 bytes following the Internet address would be "2" for the attribute code, "6" for the attribute length, and then 6 octets for the Internet address to use for expedited data, 4 octets for IP address, and 2 octets for TCP port.)

Where [a.b.c.d] is the IP address of the host where the respective TSAP peer resides, and port is a 16-bit unsigned integer describing where in the TSAP port space the TS-user lives 🧚

Port value ranges:

   Port value        Designation
   ----------        -----------
       0             illegal
      1-4096         privileged
   4097-65535        user

The following table lists the "official" TSAP ID port numbers as of the first release of this memo 🌈 It's expected that future editions of the "Assigned Numbers" document[RFC-960] will contain updates to this list.

   Port    name        ISO service
   ----    ----        -----------
   1       echo        unofficial echo
   2       sink        unofficial data sink
   3       FTAM        File Transfer, Access, and Management
   4       VTS         ISO-8571 Virtual Terminal Service
   5       MHS         Message Handling System [X.411]
                       CCITT X.400
   6       JTM         Job Transfer and Manipulation
                       ISO 8831/8832
   7       CASE        Common Application Service Elements
                       Kernel ISO-8650/2

If anyone knows of a list of "official" ISO services, the authors would be super interested πŸ₯ΊπŸ«Ά

πŸ“¦ where this page comes from