Published on (
 See this if you're having trouble printing code examples

FreeBSD Basics

TCP Protocol Layers Explained


Also in FreeBSD Basics:

Fun with Xorg

Sharing Internet Connections

Building a Desktop Firewall

Using DesktopBSD

Using PC-BSD

In the next few articles, I'd like to concentrate on IP packets and the information that can be found within the headers of an IP packet. This week, we'll cover the various fields in the layer-3 and -4 headers in preparation for next week, when we'll capture and view this information using the "tcpdump" utility. We'll then be in good shape to see how this information relates to packet filter rules and firewalls.

Your FreeBSD system uses TCP/IP as its networking protocol. The best definition I've seen for a protocol is from, and I quote it here:

"In information technology, a protocol (pronounced PROH-tuh-cahl, from the Greek protocollon, which was a leaf of paper glued to a manuscript volume, describing its contents) is the special set of rules that end points in a telecommunication connection use when they communicate. Protocols exist at several levels in a telecommunication connection. There are hardware telephone protocols. There are protocols between each of several functional layers and the corresponding layers at the other end of a communication. Both end points must recognize and observe a protocol. Protocols are often described in an industry or international standard."

Before your FreeBSD system can send data over a network connection, the TCP/IP protocol must first package that data into IP packets. An IP packet is simply a chunk of data that has had labelling information appended to the beginning of the data; like the Greek protocollon, this labelling information, called a header, is used to describe the data that follows the header.

All IP packets have at least one header, which is known as the IP header; sometimes this header is also called a Layer 3 or network header. The IP header is simply a series of bits which have been grouped into fields of a set size. All IP headers have the same structure; the only difference will be which bits have been set to "1" to either turn on a field's value or to represent a binary number within a field. Let's take a closer look at the fields in an IP header:

4 8 16 32 bits
Ver. IHL Type of service Total length
Identification Flags Fragment offset
Time to live Protocol Header checksum
Source address
Destination address
Option + Padding

An IP packet has 14 fields; let's go through these fields one at a time.

This is a 4-bit field that indicates the IP version, written in binary. For example if you are using IPv4, the bits will be set to 0100; if you are using IPv6, the bits will be set to 0110.

IHL or header length
This 4-bit field indicates how long the IP packet header is; this value is used to distinguish which part of the IP packet is the header, and which part is the actual data. If you take a look at the picture of the IP packet, you'll notice that it is 32 bits wide. Now take a look at the length of the packet: the data is not part of the header, the options are optional, but all other fields are required. This means that the minimum header length is five 32-bit words, or binary 0101. You'll sometimes see these words translated into bytes; that is, five words multiplied by 4 bytes (32 bits divided by 8 bits to make a byte) equals a header length of 20 bytes. If the options are used, the header length will be at least six 32-bit words. Since this is a 4-bit field, the maximum length will be 2 to the power of 4 minus 1, or 15. This effectively limits the size of an IP header to 60 bytes (15 words multiplied by 4 bytes).

Type of Service (sometimes called TOS) flags
This field is 8 bits long; the first 3 bits are called precedence bits and the last 5 bits represent the type of service flags. These flags were originally created to prioritize which packets should be delivered and which packets could be dropped if a router became congested. Since then, other protocols have been invented to prioritize traffic and most routers ignore these flags even if they have been set.

Total length; also called packet length or datagram length
This 16-bit field represents the total length of the IP packet, meaning both the data and the header. The minimum size is 21 bytes (default header size plus one byte of data). Since this field is 16 bits long, the maximum packet size is 2 to the power of 16 minus one, or 65,535 bytes. (The minus one represents the illegal length value of 0.)

Every IP packet is given an identification number when it is created; that number is contained within this 16-bit field. It is possible for an IP packet to be separated into smaller "fragments" before it reaches its final destination; each fragment still belongs to the original IP packet, so each fragment will have the same identification number.

This field contains three flags as follows:

Fragment offset
If an IP packet has been fragmented, each fragment will have a value in this 13-bit field indicating where this fragment's data fits into the original IP packet. For example, let's pretend an IP packet containing 128 bytes of data was fragmented into two fragments each containing 64 bytes of data. The fragment containing the first 64 bytes of data would have a fragment offset of 0 as its data belongs at the very beginning of the original IP packet. The fragment containing the last 64 bytes of data needs to indicate that its data starts after the first 64 bytes. Since the number in this field represents an 8-byte multiple, its fragment offset will be 8 (8 multiplied by 8 = 64 bytes).

Time to Live (often called TTL)
Whenever an IP packet passes through a router, the router will decrease the TTL by one; if the TTL ever reaches 0, the packet will be thrown away under the assumption that it must be undeliverable as it hasn't been delivered by now. The original TTL value depends upon the operating system; your FreeBSD system uses a default TTL of 64. Since this is an 8-bit field, the maximum allowable TTL is 255 (2 to the power of 8 minus 1; the minus 1 is for the non-allowable TTL of 0).

This 8-bit value specifies which protocol's data is contained within the IP packet and gives a good indication of what type of information will be contained within the data portion of the packet. The protocol numbers that appear in this field are found in the "/etc/protocols" file on your FreeBSD system.

For example, the protocol number 1 represents the ICMP protocol. This means that this IP packet does not contain any data from an application; instead, it contains a small amount of ICMP data. We'll be taking an in-depth look at ICMP and how it affects your firewall in a separate article.

A protocol number of 6 indicates the TCP protocol. You may remember from earlier articles that TCP is a connection-oriented transport. This IP packet will have an additional header known as a TCP header that will be located just after the IP header and before the beginning of the actual data that is being delivered.

A protocol number of 17 indicates the UDP protocol, which is the connectionless transport. This IP packet will have a UDP header located just after the IP header and before the beginning of the data that is being delivered.

Header Checksum
Whenever an IP header is created or modified, a CRC (cyclic redundancy check) is run on the bits contained within the IP header. Basically, some math (the CRC algorithm) is done which results in an answer known as the checksum. When the IP packet is received, the same CRC is repeated on the header; if this results in the same answer (checksum), all of the bits of the IP header must have arrived in the correct order. If the CRC results in a different checksum, some of the bits in the header didn't arrive, meaning the IP packet was somehow damaged during transit.

Source Address
This will be the IP address of the host that sent the IP packet.

Destination Address
This will be the IP address of the host that is to receive the data contained within the IP packet.

Options and Padding
This is the only field in an IP packet which is optional, as all other fields are mandatory. This field is used to provide special delivery instructions not covered by the other fields in an IP header. It can allow for up to 40 bytes worth of extra instructions; these instructions must be in 32-bit words. If an instruction doesn't quite fill up a 32-bit word, the missing bits will be filled in with "padding" bits.

The last field in an IP packet is called the data field. This will be the actual data that is being sent from one host to another. The data field may start with a Layer 4 header, which will give additional instructions to the application that will be receiving the data; alternately, it may be an ICMP header and not contain any user data at all.

Now that we've examined what is contained in a Layer 3 (IP) header, let's move on to the Layer 4 header. A Layer 4 header occurs at the very beginning of the IP data field and can be either a TCP header or a UDP header. Let's start with the fields that will be found in a Layer 4 TCP header:

16 32 bits
Source port Destination port
Sequence number
Acknowledgement number
Offset Reserved U A P R S F Window
Checksum Urgent pointer
Option + Padding

Note that a TCP header is also composed of 32-bit words; like an IP header, the default size is 20 bytes if the option field is not used. Let's summarize the fields that are available in a TCP header:

Source Port
This 16-bit number represents the name of the application that sent the data in the IP packet. On your FreeBSD system, the file /etc/services lists which applications use which port numbers. We also saw these port numbers when we used the "sockstat" utility in Understanding BSD Daemons. There are 65,535 possible port numbers (2 to the power of 16 minus 1).

Destination Port
This 16-bit number represents the name of the application that is to receive the data contained within the IP packet. This is one of the major differences between a Layer 3 and a Layer 4 header: the Layer 3 header contains the IP address of the computer that is to receive the IP packet; once that packet has been received, the port address in the Layer 4 header ensures that the data contained within that IP packet is passed to the correct application on that computer.

Sequence Number
TCP is responsible for ensuring that all IP packets sent are actually received. When an application's data is packaged into IP packets, TCP will give each IP packet a sequence number. Once all the packets have arrived at the receiving computer, TCP uses the number in this 32-bit field to ensure that all of the packets actually arrived and are in the correct sequence.

Acknowledgement Number
This number is used by the receiving computer to acknowledge which packets have successfully arrived. This number will be the sequence number of the next packet the receiver is ready to receive.

Header Length or Offset
This is identical in concept to the header length in an IP packet, except this time it indicates the length of the TCP header.

These 6 bits are unused and are always set to 0.

Control Flags
TCP uses six control flags with each flag being a unique bit. If the bit is set to 1, the flag is on; if the bit is set to 0, the flag is off. The order of the flags is:

We'll be seeing these flags again when we run "tcpdump" and when we take a look at creating packet filter rules.

Window Size
Every TCP packet contains this 16-bit value that indicates how many octets it can receive at once. When IP packets are received, they are placed in a temporary area of RAM known as a buffer until the receiving computer has a chance to process them; this value represents how big a buffer the receiving host has made available for this temporary storage of IP packets.

Unlike IP, TCP is responsible for ensuring that the entire IP packet arrived intact. TCP will run a CRC on the entire IP packet (not just the header) and place the resulting checksum in this field. When the IP packet is received, TCP re-runs the CRC on the entire packet to ensure the checksum is the same.

Urgent Pointer
If the Urgent flag was set to on, this value will indicate where the urgent data is located.

Options and Padding
Like IP options, this field is optional and represents additional instructions not covered in the other TCP fields. Again, if an option does not fill up a 32-bit word, it will be filled in with padding bits.

This will be the actual data being sent and will not include any additional headers.

Finally, let's take a look at a Layer 4 UDP header. Unlike TCP, UDP does not create a connection or guarantee the delivery of data. Accordingly, a UDP header has very few fields as compared to a TCP header:

16 32 bits
Source port Destination port
Length Checksum

A UDP header is always 8 bytes as it does not contain any options. The UDP header fields are as follows:

Source Port
Like TCP, this field indicates which application sent the data contained within the IP packet.

Destination Port
Again, indicates which application is to receive the data contained within the IP packet.

Indicates the length (in bytes) of the UDP header and the data. Since all UDP headers are 8 bytes long, if you subtract 8 from this number you'll find out the size of the data being sent.

Since UDP is not responsible for ensuring that the data actually arrives, a checksum is optional; if it is not used, this field will be set to 0.

Again, this will be the actual data being sent and will not include any additional headers.

We've actually made it through all of the fields in the Layer 3 and Layer 4 headers of an IP packet. These fields should make more sense next week when we examine a dump file created by the tcpdump utility.

Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.

Read more FreeBSD Basics columns.

Return to the BSD DevCenter.

Copyright © 2009 O'Reilly Media, Inc.