Different Types of Internet Packets
The physical network supports different types of logical networks like Novell (IPX), Microsoft (NetBEUI), AppleTalk, and of course, TCP/IP. Each logical network uses discrete data messages called packets, as defined in the last chapter. The packets can be actual messages on the transmission line (which has a lot more information included) or simply the message you're sending.
The logical network packet at the generic level consists of information about the source, destination, and data payload. Each logical network offers varying degrees of features and interfaces (protocols). All packet types and protocols are available with network programming. Each type has significant strengths and weaknesses. Like shopping for tools, your choice of packet type depends on how you use it.
You can choose from four basic Internet packet protocols: raw IP, ICMP, UDP (unreliable messaging), and TCP (streaming) all layered on top of the physical network (see Figure 3.1). This chapter describes each type and presents their advantages, disadvantages, and typical uses.
The Fundamental Network Packet
If you could actually see the bits that travel from one computer to the other, what would you see? Each protocol is very different, but they all share one common necessary feature: They all carry the program's message. Some protocols include a source address, while some require a destination. You may think that not requiring a destination is a little unusual, but some protocols (like UUCP) use the connection as the address to the destination.
The Internet Protocol (IP) [RFC791] requires a packet to have three basic elements: source, destination, and data. (The data payload includes its length.) These elements provide the packet a level of autonomy. No matter where a packet is, you can identify where it came from, where it's going, and how big it is.
The packet's autonomy is an important feature of the Internet. As long as the packet is alive (the data is timely and relevant), routers can move data to its destination when the packet is launched onto the network.
Packet Aliasing
Packet autonomy also has a downside. While a packet provides a way of getting to anywhere from anywhere, a malicious programmer can easily trick the network. The network does not require that the source host's address be validated. Aliasing or spoofing (masking the true identity and assuming a different one) the hardware address is difficult, but programs can alias other IDs. Please note that later Linux kernels do not allow spoofing.
As discussed in Chapter 2, "TCP/IP Network Language Fluency," the network packet is in network byte (or big endian) order. With that in mind, take a look at a structure definition of how the network packet appears in Listing 3.1, and Figure 3.2 displays the physical layout.
Listing 3.1 IP Structure Definition
/************************************************************/ /*** IP Packet definition ***/ /************************************************************/ #typedef unsigned int uint; #typedef unsigned char uchar; struct ip_packet { uint version:4; /* 4-bit version [note] */ uint header_len:4; /* header length in words [note] */ uint serve_type:8; /* how to service packet [note] */ uint packet_len:16; /* total size of packet in bytes */ uint ID:16; /* packet ID [note] */ uint __reserved:1; /* always zero */ uint dont_frag:1; /* flag to permit fragmentation */ uint more_frags:1; /* flag for "more frags to follow"*/ uint frag_offset:13; /* to help reassembly */ uint time_to_live:8; /* permitted router hop cnt [note] */ uint protocol:8; /* ICMP, UDP, TCP [note] */ uint hdr_chksum:16; /* ones-comp. checksum of header */ uint IPv4_source:32; /* IP address of originator */ uint IPv4_dest:32; /* IP address of destination */ uchar options[ ]; /* up to 40 bytes [note] */ uchar data[ ]; /* message data up to 64KB [note] */ };
Notice that the packet structure includes many more fields than the basic four fields discussed earlier in this chapter. The IP subsystem uses these additional fields for controlling the packet. For example, the dont_frag field tells the network that, instead of cutting up the message into smaller chunks, it should either accept the message completely or drop it.
Most of the fields are simple enough that the comments next to them provide sufficient description. The remaining fields require a longer description. The following sections define the IP fields that you can modify or use. This text is not exhaustive; if you want to learn more about each field, please refer to a good text on TCP/IP protocols.
version Field
The first IP field is the version number for the IP protocol version. Most of the values are either reserved or unassigned; for example, IPv4 places a 4 in this field. The few defined values are listed in Table 3.1.
Table 3.1 version Field Values
Value |
Description/Use |
4 |
IPv4 |
5 |
Stream IP Datagram mode (experimental IP) |
6 |
IPv6 |
7 |
TP/IX (the "next" Internet Protocol) |
8 |
The "P" Internet Protocol |
9 |
TUBA |
The only chance you have to fill this field is when you create a raw socket and you elect to fill the header yourself (using socket option IP_HDRINCL). Even then, you may set the field to 0. The zero flags the kernel to fill in the appropriate value for you.
header_len Field
This field tells the receiver the header length in 32-bit words. Since the value 0 is reserved (and meaningless), the greatest length is 15 words or 60 bytes. Again, the only circumstance in which you fill this field is with a raw socket packet and IP_HDRINCL. Since all IP headers are at least 20 bytes, the minimum value for this field is 5 (20/4) bytes.
serve_type Field
The serve_type field indicates how to manage the packet. It has two subfields: a precedence subfield (ignored on most systems) and a type of service (TOS) subfield. You normally set TOS with the setsockopt() system call. TOS has four options: Minimum Delay, Maximum Throughput, Maximum Reliability, and Minimum Cost (monetary). No special service selected means normal management. (See Chapter 9, "Breaking Performance Barriers," for details on setsockopt() and its values.)
ID Field
The IP subsystem gives each packet a unique ID. With only a 16-bit field, you can imagine that the numbers get used up quickly. Nevertheless, by the time the IP subsystem reuses an ID, the previous packet of the same value will probably have expired.
The ID helps reassemble fragmented packets. If you elect to manage the header (IP_HDRINCL), you must manage the IDs yourself.
Custom IDs
Keep in mind that your program is not the only one that may send messages if you choose to manipulate the header yourself. The IP subsystem keeps track of the IDs. You must use caution (and extra programming) to reduce the likelihood of selecting an ID that the subsystem recently used or may use.
dont_frag, more_frags, frag_offset Flags and Field
These flags manage how (or if) your packet fragments. If while traversing the network a lengthy packet has to go through a constricted network segment (one that cannot support the frame size), the router may try to break up the packet into smaller pieces (fragmentation). A fragmented packet remains fragmented until it arrives at the destination. Because each fragment adds its own IP header, the overhead diminishes performance.
Kernel Fragment Reassembler
You can choose to reassemble fragmented packets with the Linux kernel when the host is a router. This option is part of the firewall/router section in the kernel configuration. Please note that it takes time to reassemble packets, especially if they are scattered and arrive at different times. However, since the destination has to reassemble the packet anyway, selecting this option reduces traffic on the network inside the firewall.
The dont_frag bit tells the router or host not to break up the packet. If you set this bit and the packet is too large for a constricted network segment, the router drops the packet and returns an error (ICMP) packet.
The more_frags bit tells the destination to expect more pieces of the fragmented packet. The last fragment sets this bit to 0. (A nonfragmented packet sets this bit to 0.) If you are configuring the header manually, always set this bit to 0.
The frag_offset field indicates where in the packet the fragment belongs. Because packet fragments may travel through different routes in the network, they may arrive at different times. The destination has to reassemble the packet, and it uses the offset to place the fragment in its proper location.
The frag_offset field is only 13 bits long—far too short for a packet that can be up to 64KB. The offset is multiplied by 8 to place the actual byte position in the packet. This means that each fragment (except the last) must be a multiple of 8. The IP subsystem completely manages the fragmentation and reassembly of your packet; you don't need to worry about it.
With these fields and the packet ID, the IP subsystem can fragment and reassemble your packet. If the subsystem cannot get all the pieces within a specified time, it drops the packet and sends an error back to the originator.
time_to_live (TTL) Field
This field originally counted the number of seconds a packet could survive on the network during transit. Later, the meaning changed to the number of router hops. A hop is the transition through a host or router (node) where the node actively moves a packet from one network to another.
This 8-bit field permits up to 255 router hops before being discarded. When a router or forwarding host gets the packet, it decrements this field by one. If the field equals zero before arriving at the destination, the node drops the packet and sends an error to the source. The TTL field keeps the network from bouncing a packet around indefinitely.
Use the IP_TTL socket option to set this value (see Chapter 9). Alternatively, you can set it directly if you elect direct IP header manipulation (IP_HDRINCL).
protocol Field
Every packet on the Internet has an assigned protocol value, and ICMP (IPPROTO_ICMP or 1), UDP (IPPROTO_UDP or 17), and TCP (IPPROTO_TCP or 6) each own a code. The protocol tells the system how to treat the incoming packet. You can set this value with the SOCK_RAW option in the socket() system call. The protocol value is the last parameter of the call. The kernel's netinet/in.h header file lists many more. (Remember that even though the kernel includes a protocol definition, it might not support it.)
options Field
The IP subsystem can pass several options with each packet. These options include routing information, timestamps, security measures, routing record, and route alerts. This field can be up to 40 bytes long. Because some of the options are system dependent, you are unlikely to ever touch these options directly.
data Field
Your message goes here and can include up to 65,535 bytes (minus 60 bytes, the maximum size of the header). The data section includes any header information that the higher protocols need. For example, ICMP requires 4 bytes, UDP requires 8 bytes, and TCP requires 20–60 bytes.
The Internet packet system bases all its IPv4 packets on this structure. Each layer on top of this adds features and reliability.