=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- An Introduction to the ICMP Protocol by BarKode (barkode@sysfail.org) =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Continuing the line of articles about common internet protocols, here's a look into ICMP, or Internet Control Message Protocol. ICMP is an essential protocol on IP-based networks, as IP is not a "reliable" protocol. For those of you wondering why I keep writing articles covering the basics of standard internet protocols, it's brought on by a number of things. One of them being that System Failure has changed its focus completely. By the time I joined last year, the group had weeded out articles focusing on crime and "how to rip off the phone company" and such. Gears have shifted towards a technical, intelligent magazine for a larger, more intellectual audience. I sincerely hope that the difference has been noticed. Secondly, demographics (e-mails to SysFail) show a crowd that is new to the scene, and helping those people is an important part of what System Failure is all about. ICMP is essential to the operation of an IP -based network for a variey of reasons. IP being "unreliable" (there is no guarantee an IP packet will get to its destination), there must be an error-handling routine. ICMP is that solution. If for some reason a machine can't handle an incoming IP packet, it drops the packet and sends back an ICMP error message to the machine that sent the original packet telling it something is wrong. The most familiar function of ICMP to most people is the Echo Request/Reply set, or "ping" as it's better known. When you ping a machine, you're sending an ICMP message called an "echo request" to that machine. The network layer of that machine will send you back an ICMP "echo reply," if it is so configured to do so. An ICMP packet looks like this: .---------------------------------. | IP Header | ICMP Message Data | `---------------------------------' 20 bytes The actual header of an ICMP packet looks like this: 0 7 8 15 16 31 .-------------------------------------------------. | 8 Bit Type | 8 Bit Code | 16 Bit Checksum | `-------------------------------------------------' The rest of the packet differs between ICMP "types." An ICMP type declares what the function of the ICMP packet is, and how it's to be dealt with by the system. An ICMP "code" is a subtype. For instance, ICMP type "3" code "0" is a "network unreachable" while a type "3" code "1" is a "host unreachable". ICMP type "3" is the "destination unreachable" type. So, when we ping a machine, we create an ICMP "echo request" packet. The type is "8" and code is "0". The packet is created, and assuming you were using an ethernet for this, the packet would look similar to this: 00000000: 00 40 05 16 56 AA 00 00 b4 54 b1 BB 08 00 45 00 00000010: 00 54 54 ed 00 00 40 01 19 d9 d1 AA BB CC d1 BB 00000020: CC EE 08 00 67 74 41 2d 00 00 5a 9b 5b 36 ab 89 00000030: 03 00 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 00000040: 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 00000050: 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 00000060: 36 37 That's what the packet would actually look like on the wire. Let's break it down, protocol by protocol: 00000000: 00 40 05 16 56 AA 00 00 b4 54 b1 bb 08 00 -- -- |_______________| |_______________| |___| | | | Destination Hardware Source Hardware Protocol (16 bits) Address Address (08 00 == IP) (48 bits) (48 bits) This is the ethernet layer, containing the source and destination hardware addresses for the packet, as well as what protocol is encapsulated within it. In this case, 08 00 means its carrying an IP packet. ____ 8 bit Type of || service field 00000000: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 45 00 ||__ (4 bits, msb) Version (ipv4 == 4) | | (4 bits, lsb) Num. of 32 bit words in header, normally 5 This is the IP layer, which contains information necessary to move the packet from network to network, or machine to machine for that matter. The first 4 bits of the first byte of the header specify what IP protocol is in use. On today's internet, we use IPv4, so this would be a 4. The second, least signifigant 4 bits specify how many 32-bit words are located within this packet. You'll find this is often a 5, because there are most often 5 32-bit words in an IP packet, without options. The second byte is the 8-bit type of service field, which we'll dig into deeper in another article. Assume for now that this field gives more detail as to the application that is sending this data and how it should be handled. 16-bit total length (in bytes) | 3-bit flags, | 13-bit Frag Offset | | | | IP Protocol Type (ICMP) (8 bits) | (16bits) | | | Fragment |(8bit)| (16bits) Source IP (32 bits) | ID | TTL | Checksum | Destination IP (32 bits) _|_ _|_ _|_ | | _|_ ____|____ _______|______ | | | | | | | | | | | | | | 00000010: 00 54 54 ed 00 00 40 01 19 d9 d1 AA BB CC d1 BB | 00000020: CC EE -- -- -- -- -- -- -- -- -- -- -- -- -- -- | |___| | |____________________________________________________| The 16-bit total length is the length of the whole datagram, in bytes. Fragment ID (sometimes just "ID"), Flags and Frag offset will be discussed in another article. The "Time To Live" is the maximum amount of hops this packet can go through before it is discarded and the sender is delivered a message saying that the packet didn't get to its destination. Each hop decrements this field by one before sending the packet along. The protocol type in this case is a "1", specifying ICMP as the protocol in use. The checksum is a matter of one's complement notation against the header on both the sending and receiving machines, and we'll look into this more specifically in the next article. The rest is self-explanatory. Now for the ICMP packet itself. ICMP Type - Echo Request (8) | Identifier - UNIX implementations use the PID | ICMP Code, 0 | of the calling process | | | | | Checksum | Sequence Number | | _|_ ___| _|_ __________________ | | | | | | | | | | 00000020: -- -- 08 00 67 74 41 2d 00 00 5a 9b 5b 36 ab 89 | 00000030: 03 00 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 | 00000040: 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 ---- 56 bytes of 00000050: 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 | data 00000060: 36 37 | (Variable) ___| The first two bytes are the ICMP type and code, respectively. The checksum works the same as it does for IP. The identfier is set to the PID on UNIX machines, usually. Either way, it's a unique identifier for whatever purpose the machine needs. Using the PID is a good idea, as it allows a machine to determine what process the packet belongs to. Anyone who has used ping knows what the sequence number is. The sequence number is an incrementing number for each packet sent, allowing a process, or person for that matter, to track their packets. The rest of the data is piggybacked onto the packet to pad it to meet the minimum transmission unit for the network media, as well as to send some more data with the packet in order to test speed between two places. The echo reply is then generated, and the packets look very similar. The exceptions being the source/destination HW and IP addresses are switched, and the ICMP type is changed from "8" to "0" (Echo Reply). **** We'll look more into this and other topics in the next System Failure. For those of you that are interested in protocol analyzation, I suggest picking up a good sniffer/network analyzer and watching what goes by on your network. You might find some interesting things, and it's a good way to learn about protocols and their implementation on different operating systems and networks. Hope you enjoyed, and keep those e-mails coming. -bk References: I. "TCP/IP Illustrated, Volume 1: The Protocols" W. Richard Stevens, January 1994. (Addison-Wesley Professional Computing Series). ISBN:0201633469