This is made difficult by the fact that IP packets may be fragmented. There is no certainty that a full packet is available. The first task of the function is therefore to reassemble a fragmented packet from its constituent parts by means of ip_defrag.17 The corresponding code flow diagram is shown in Figure 12-16.

Figure 12-16: Code flow diagram for ip_defrag.

16Note that kernel 2.6.25 (which was still under development when this book was written) will change the names from NF_IP_* to NF_INET_*. This change unifies the names for IPv4 and IPv6.

17The kernel recognizes that a packet is fragmented either by the set fragment bit or by a non-zero value in the offset field. A zero value in the offset field indicates that this fragment is the last in the packet.

The kernel manages the fragments of an originally composite packet in a separate cache known as a fragment cache. In the cache, fragments that belong together are held in a separate wait queue until all fragments are present.

The ip_find function is then invoked. It uses a hashing procedure involving the fragment ID, source and destination address, and packet protocol identifier to check whether a wait queue has already been created for the packet. If not, a new queue is created and the packet is placed on it. Otherwise, the address of the existing queue is returned so that ip_frag_queue can place the packet on it.18

When all fragments of the packet are in the cache (i.e., the first and last fragment are present and the data in all the fragments equal the expected total length of the packet), the individual fragments are reassembled by ip_frag_reasm. The socket buffer is then released for further processing.

If not all fragments of a packet have arrived, ip_defrag returns a null pointer that terminates packet processing in the IP layer. Processing is resumed when all fragments are present.

Continue reading here: Delivery to the Transport Layer

Was this article helpful?

0 0