SCTP is transport layer protocol with functions similar to TCP and some unique additions. Although it is not very popular in the Internet world, this protocol plays important role in telecommunication networks. It is used as a transport for various SIGTRAN protocols and it is the default transport protocol in EPC.
There is a Wikipedia article which provides a basic overview of SCTP's features. Another good document is SCTP: What is it, and how to use it? by Randal Stewart, Michael Tuxen and Peter Lei. In this article I want to provide SCTP overview from network developer point of view, which (in my opinion) means to dig into some specifications. What you will find here is a quick walkthrough the parts that I find most interesting, with references to the corresponding sections in RFC 4960, the SCTP specification.
SCTP packet structure
A SCTP packet contains common header and one or more chunks. The common header has the same structure for each SCTP packet. It contains:
- source port number (16 bits)
- destination port number (16 bits)
- verification tag (32 bits)
- checksum (32 bits)
The packet sample on fig. 2 is common header, stripped from an INIT message (INIT chunk is collapsed, for better readability). More details at Section 3.1.
A SCTP chunk represents a protocol message, which can be used by the protocol itself (e.g. INIT, which is the first step in association establishment), or can contain user data (DATA chunk). It has three fixed-length parameters and a variable length value. Each chunk is 4 byte aligned. This means that the whole chunk size have to be multiple of 4 bytes. If it is not, zero byte padding is added to achieve the multiple-of-4bytes requirement. The padding shouldn't be more than 3 bytes. 4 byte padding doesn't make sense, because the message is already 4 byte aligned. Each chunk has git the following fields:
- chunk type - 8 bits, can be considered as and indetificator of the SCTP message. E.g. INIT, DATA, HEARTBEAT, etc.
- chunk flags - 8 bits, specific for each chunk type.
- chunk length - 16 bits, the length of the chunk in bytes, including all header fields (type, flags, length) plus the length of the value, excluding the padding.
- chunk value - variable length parameter. Contains various chunk parameters, which depend on the chunk type.
Fig. 3 shows SACK message, which contains common packet header and SACK chunk. The chunk's size is 16 bytes, which means that there is no padding. Chunk structure is described in Section 3.2. All chunk definitions can be found in Section 3.3.
The value of each chunk has specific format too. It contains two fixed-sized parameters and variable length value. Each parameter in the chunk must be 4 byte aligned, so the chunk parameter itself may also contain padding. The logic is the same as for the chunk value. Here is the structure of each parameter:
- chunk parameter type - 16 bits, the type of the parameter in the chunk.
- chunk parameter length - 16 bits, the length of the parameter, without the padding.
- chunk parameter value - the actual value for the specified parameter type.
Wireshark makes packet decoding easy, but we will 'decode' one chunk manually, just to see how it's done. The packet from fig. 3 contains a SACK chunk and has got 4 parameters. Let's examine the first one - Cumulative TSN ACK:
- Open sack.pcapng with Wireshark. We are not interested in Ethernet or IP data - we'll examine only the SCTP. Click on the frame (it is only one) and from the protocol list select Stream Control Transmission Protocol. The SCTP data is marked on the HEX editor at the bottom of the window.
- The common header has fixed length parameters. We have got 0x115c and 0xc668 as source and destination port numbers (4444 and 50792). Then there are 32 bits for verification tag - 0x88e5e376 and checksum 0x883432df. That's all for the common header. Nothing fancy here, thanks to the fixed length parameters.
- An SCTP chunk follows. Its header is fixed length, so lets read it. 8 bits chunk type (0x03), 8 bits flags (0x00) and 16 bits length (0x0010). Now we can get the payload. 0x0010 is 16, which means that the chunk contains 16 bytes (not bits, the length is in bytes). Let's convert it to bits (16*8 = 128) and subtract the length of the parameters read up to now. 128 - 8 (type) - 8 (flags) - 16 (length) = 96. This means that the following 96 bits are the chunk data. Check again the packet in the HEX view and you'll see that we have got exactly 96 bits left. This means that the chunk parameter value is 8a 70 48 4a 00 01 9f fa 00 00 00 00.
- Now we know the chnk type - 0x03. A quick look up in Section 3.2 shows that the chunk is Selective Acknowledgement (SACK). We need to find the chunk definition - it is in Section 3.3.4 . It starts with a description of the message. Right now we are not interested in this, we only want to parse the parameters and their values.
- After the description in Section 3.3.4, there is a 'bit map' of the whole message and details for each parameter. We start parsing them one by one.
- Chunk type, flags and length are already parsed. We know that the flags value is 0x00 and the description says that the flags for SACK are always 0. No surprises here.
- The next one is Cumulative TSN Ack: 32 bits. This means that its value is 0x8a70484a, which is 2322614346. The payload that remains unparsed is 00 01 9f fa 00 00 00 00.
- The next parameter in the list is Advertised Receiver Window Credit (a_rwnd): 32 bits. Its value is 0x00019ffa, which is 106490. The unparsed part of the payload now is 00 00 00 00.
- Next one - Number of Gap Ack Blocks: 16 bits (unsigned integer). Its value is 0x0000, which means that there are no 'Gap Ack Blocks' parameters in this chunk. Good news - less work for us. Now we have to parse only 00 00.
- The next parameter is Number of Duplicate TSNs: 16 bit. Its value is 0x0000. This means that there are no 'Duplicate TSNs' parameters.
- According to the last two parsed parameters, there are no 'Gap Ack Block Start' and 'Gap Ack Block End', so we are done.
The same approach can be applied for decoding any parameter in Section 3.2. Just follow the field list and pay attention for optional parameters.
So what we have discussed so far? We know why SCTP was designed and where it is used and we have introduced ourselves to some key terms. We have also learned the structure of the SCTP packet and how to decode the common header and the chunks. Good start, but the fun part is about to come. Stay tuned for the next part, which will discuss the protocol procedures and the messages involved in them.