ICMP and Network Diagnostics
IP itself is a fire-and-forget datagram service: it carries a packet toward a destination and, if something goes wrong, simply drops it — no apology, no explanation. The Internet Control Message Protocol (ICMP) is the feedback channel that fills that silence. Specified for IPv4 in RFC 792 (J. Postel, September 1981, STD 5) and redesigned for IPv6 as ICMPv6 in RFC 4443 (Conta, Deering & Gupta, March 2006, Standards Track, obsoleting RFC 2463), ICMP is not a layer above IP but “an integral part of IP” that rides inside IP datagrams (IPv4 protocol number 1; IPv6 Next Header 58) to report delivery errors and answer diagnostic queries (RFC 792, RFC 4443 §1). Two of the most-used network tools on earth —
pingandtraceroute— are nothing but ICMP with a stopwatch, and the single most important control message (Fragmentation Needed / Packet Too Big) is what makes Maximum Transmission Unit and Path MTU Discovery work. This note is the protocol/specification view of the messages and the tools built on them; the kernel paths that generate and consume ICMP live in The IP Layer and IP Routing Decision and Forwarding.
Mental Model — IP’s Out-of-Band Control Channel
Think of ICMP as a set of notes slipped back to the sender by any router or host along a packet’s path. There are two flavours. Error messages are unsolicited: a router that cannot forward your packet drops it and mails back a note saying why (no route, hop limit hit, too big to fragment). Query/informational messages are request-reply pairs you send on purpose to interrogate the network (echo a host, ask its clock). Crucially, ICMP has no ports and no reliability of its own — an ICMP error is a best-effort courtesy that may itself be lost, and it always quotes a chunk of the packet that triggered it so the sender can figure out which connection it refers to.
flowchart TB SRC["source host<br/>sends IP datagram"] -->|"packet"| R1["router"] R1 -->|"forwards"| R2["router (MTU too small,<br/>or hop limit = 0,<br/>or no route)"] R2 -.->|"drops packet"| X["✗"] R2 ==>|"ICMP error back to source<br/>(type/code + quoted header<br/>of the offending packet)"| SRC SRC -->|"ICMP Echo Request (ping)"| DST["destination host"] DST -->|"ICMP Echo Reply"| SRC
How ICMP closes the feedback loop IP leaves open. What it shows: when forwarding fails, the failing node discards the packet and returns an ICMP error carrying the type/code of the problem plus a copy of the original packet’s header so the source can correlate it; separately, echo request/reply is a deliberate round-trip probe. The insight: ICMP is diagnostic and control, never a data-carrying transport — and because errors are best-effort and rate-limited, an application must never depend on receiving them, only benefit when it does (RFC 792, RFC 4443 §2.4).
Message Format and the “Quote the Offender” Rule
Every ICMP message begins with three common fields: an 8-bit Type (what kind of message), an 8-bit Code (a sub-reason within that type), and a 16-bit Checksum (RFC 792). What follows depends on the type. For error messages, the body includes a copy of the packet that caused the error: RFC 792 specifies “the internet header plus the first 64 bits of the original datagram’s data.” Those first 64 bits are exactly enough to reach the source and destination ports (for TCP/UDP) or the identifier (for ICMP echo), so the receiving host can demultiplex the error to the right socket. (ICMPv6 is more generous: it quotes as much of the offending packet as fits without exceeding the minimum IPv6 MTU of 1280 octets.)
Two rules keep ICMP from amplifying into a storm. First, RFC 792 mandates that “no ICMP messages are sent about ICMP messages” — an error about an error would ping-pong forever. Second, for a fragmented datagram, an error is generated only for fragment zero, so one oversized datagram cannot elicit an error per fragment. ICMPv6 hardens these further (see rate-limiting below).
The checksum differs subtly between versions and it matters. ICMPv4’s checksum covers only the ICMP message. ICMPv6’s checksum additionally covers a pseudo-header drawn from the IPv6 header — source address, destination address, payload length, and next-header value (RFC 4443 §2.3). RFC 4443 states it “is the 16-bit one’s complement of the one’s complement sum of the entire ICMPv6 message … prepended with a ‘pseudo-header’ of IPv6 header fields.” This binds the message to its addresses and thwarts certain spoofing/redirection attacks that plain ICMPv4 was vulnerable to.
The IPv4 Message Taxonomy (RFC 792)
RFC 792 defines these types; the numbers are load-bearing because tools and firewalls reference them directly:
| Type | Name | Notable codes |
|---|---|---|
| 0 | Echo Reply | 0 |
| 3 | Destination Unreachable | 0 net, 1 host, 2 protocol, 3 port, 4 fragmentation needed & DF set, 5 source route failed |
| 4 | Source Quench | 0 (congestion signal — deprecated) |
| 5 | Redirect | 0 net, 1 host, 2 ToS+net, 3 ToS+host |
| 8 | Echo Request | 0 |
| 11 | Time Exceeded | 0 TTL exceeded in transit, 1 fragment reassembly time exceeded |
| 12 | Parameter Problem | 0 |
| 13 / 14 | Timestamp / Timestamp Reply | 0 |
| 15 / 16 | Information Request / Reply | 0 (obsolete) |
A few of these deserve prose rather than a table cell.
Destination Unreachable (type 3) is the workhorse error. Net unreachable (code 0) and host unreachable (code 1) mean a router had no route to the network or host. Port unreachable (code 3) is what a host returns when a UDP datagram arrives for a port with no listener — this is how classic traceroute detects the final hop. Fragmentation needed and DF set (code 4) is the linchpin of Path MTU Discovery, discussed in its own section below.
Time Exceeded (type 11) fires when a packet’s Time-To-Live (TTL) field — decremented by every router — hits zero (code 0), or when a fragmented datagram cannot be reassembled before its timer expires (code 1). The TTL-exceeded case is the entire engine of traceroute.
Redirect (type 5) is a router telling a host “you sent this to me, but there’s a better first-hop router on this same link — use it next time.” It is a legitimate optimization but also a spoofing hazard (an attacker can forge redirects to hijack a host’s routing), which is why most hosts now ignore or heavily restrict ICMP redirects.
Source Quench (type 4) was an early, crude congestion signal — a router drowning in packets asked senders to slow down. It proved ineffective and harmful and has been formally deprecated (routers should not send it, hosts should ignore it); modern congestion control uses loss and ECN instead (see Congestion Control Fundamentals and AIMD). Timestamp and Information Request messages are largely historical and typically blocked, as timestamp replies can leak clock information useful to attackers.
Ping — Echo Request and Reply
ping is the “is it alive, and how far away?” probe. The tool sends an ICMP Echo Request (type 8) to a target; a healthy target must respond with an ICMP Echo Reply (type 0) copying back the request’s payload, Identifier, and Sequence Number fields. The identifier lets one host run several concurrent pings without confusing their replies (traditionally the sending process’s PID); the sequence number increments per probe so the tool can detect loss and reordering and match each reply to its request. Because the reply echoes the request verbatim, the sender measures round-trip time (RTT) by timestamping departure and subtracting on return, and computes loss as the fraction of sequence numbers never answered.
Note what ping does not prove. A successful echo shows the ICMP echo path works in both directions; it does not prove that TCP to port 443 works, nor that the path can carry full-size packets (echo requests are small by default). “Ping works but the app hangs” is a real and common signature — often an MTU black hole (below). Conversely, “ping fails but the app works” is equally common, because many hosts and firewalls drop echo requests by policy while permitting everything else.
Traceroute — Weaponizing TTL and Time Exceeded
traceroute (Van Jacobson’s original design) maps the path to a destination by abusing the TTL-decrement rule. It sends a probe with TTL = 1; the first router decrements it to 0, drops it, and returns a Time Exceeded (type 11, code 0) — revealing router 1’s address. It then sends TTL = 2, eliciting Time Exceeded from router 2; then TTL = 3, and so on, walking the path hop by hop. Each hop’s RTT is measured the same way ping measures it. The walk ends when a probe finally reaches the destination.
How the final hop is detected depends on the probe type, and this is where traceroute implementations diverge:
- Classic UNIX
traceroutesends UDP datagrams to high, unlikely destination ports. Intermediate routers return Time Exceeded; the destination, having no listener on that weird port, returns Destination Unreachable / port unreachable (type 3, code 3) — the “we arrived” signal. - Windows
tracert(andping -tstyle tools) send ICMP Echo Requests with increasing TTL; the destination answers with Echo Reply. - TCP traceroute (
traceroute -T, and tools liketcptraceroute) sends TCP SYN to a real port (e.g. 80/443) so the probes look like legitimate connection attempts and slip through firewalls that block UDP/ICMP; the destination replies with SYN/ACK or RST.
This diversity explains why traceroute output sometimes shows * * * for a hop: that router is configured not to send Time Exceeded (or rate-limits it), or a firewall drops the returning ICMP — the hop is invisible even though packets pass through it fine. Asymmetric routing (the reply taking a different path than the probe) also makes traceroute’s per-hop RTTs noisy and occasionally nonsensical.
Fragmentation Needed and Path MTU Discovery
The most consequential ICMP error for real-world performance is Destination Unreachable / Fragmentation Needed and DF set (type 3, code 4). The scenario: a host sends a packet with the Don’t Fragment (DF) bit set, and it reaches a link whose Maximum Transmission Unit (MTU) — the largest frame that link can carry — is smaller than the packet. The router cannot fragment (DF forbids it) and cannot forward it, so it drops the packet and returns this ICMP error.
RFC 1191 (“Path MTU Discovery”, Mogul & Deering, November 1990) turned this error into a discovery algorithm (RFC 1191). The key trick: RFC 1191 requires the router to put the next-hop MTU into what RFC 792 had left as an “unused” 16-bit field of the ICMP header — so instead of the host having to guess how much smaller to go, the error tells it the exact ceiling. The host algorithm is: start by assuming the path MTU equals the outgoing interface’s MTU and send with DF set; on receiving a Fragmentation-Needed message, drop the estimate to the reported next-hop MTU and retry; converge when packets get through. For legacy routers that report a zero MTU, RFC 1191 supplies a plateau table of common MTU values (65535, 17914, 4352 FDDI, 1500 Ethernet, 1006, 576, down to the 68-octet minimum) so the host can step down to the next-lowest plausible value rather than binary-searching. Stale estimates are aged — RFC 1191 suggests that after ~10 minutes without a decrease, a host should reset its estimate to the first-hop MTU and re-probe, so that a path change to a larger MTU is eventually discovered. This dovetails with TCP’s Maximum Segment Size (MSS): a host must not send segments larger than PMTU − 40 (40 = IPv4 + TCP headers). The full treatment of MTU, MSS, and the DF bit is owned by Maximum Transmission Unit and Path MTU Discovery; here the point is that PMTUD is entirely dependent on this one ICMP error arriving.
ICMPv6 — A Redesign, Not a Port (RFC 4443)
ICMPv6 keeps the type/code/checksum shape but is architecturally more central to IPv6 than ICMP ever was to IPv4. Four differences matter.
It is split cleanly by the high bit of the Type field. Types 0–127 are error messages; types 128–255 are informational messages (RFC 4443 §2.1). This lets a firewall reason about whole categories at once. The core set: Destination Unreachable (type 1, with richer codes — 0 no route, 1 administratively prohibited, 2 beyond source-address scope, 3 address unreachable, 4 port unreachable, 5 source-address policy failure, 6 reject route), Packet Too Big (type 2), Time Exceeded (type 3), Parameter Problem (type 4), and Echo Request/Reply (types 128/129).
Routers never fragment, so Packet Too Big is mandatory. IPv6 removed in-network fragmentation entirely — fragmentation is done only by the source host, using a Fragment extension header (RFC 8200, STD 86). Consequently, when a router meets a packet larger than the outgoing link MTU it must return Packet Too Big (type 2) carrying that MTU: RFC 4443 says it “MUST be sent by a router in response to a packet that it cannot forward because the packet is larger than the MTU of the outgoing link.” Path MTU Discovery in IPv6 is therefore not an optimization bolted onto an “unused field” as in RFC 1191 — it is the only way to send anything larger than the 1280-octet minimum MTU, and it depends utterly on Packet Too Big getting through. Uniquely, Packet Too Big is even sent for packets addressed to multicast destinations, an explicit exception to the usual “don’t error on multicast” rule, precisely because PMTUD must work for multicast too.
The checksum covers the IPv6 pseudo-header (as described above), binding each message to its source/destination addresses.
ICMPv6 absorbs jobs that IPv4 handed to other protocols. In IPv4, address resolution is ARP, a separate link-layer protocol. In IPv6 it is the Neighbor Discovery Protocol (NDP) — Router Solicitation/Advertisement (types 133/134), Neighbor Solicitation/Advertisement (types 135/136), and Redirect (137) — all of which are ICMPv6 messages. Router Advertisements also drive Stateless Address Autoconfiguration (SLAAC). Multicast group management (Multicast Listener Discovery, MLD) is likewise ICMPv6. So ICMPv6 is not an auxiliary diagnostic you can take or leave; it is woven into the basic act of getting an address and finding a neighbour. The NDP mechanics themselves are covered in ARP and Neighbour Discovery; the takeaway here is why ICMPv6 cannot be treated as optional.
Rate Limiting, Filtering, and the “Don’t Blanket-Block ICMP” Lesson
Because an error message can be triggered by an attacker’s spoofed traffic, ICMP is a natural amplification and flooding vector. RFC 4443 §2.4 therefore requires ICMPv6 error rate limiting, recommending a token-bucket scheme (default suggested parameters bucket B = 10, rate N = 10 messages/second for small/mid-size devices), while explicitly warning that limiters “that cannot cope with bursty traffic (e.g., traceroute) are not recommended” (RFC 4443 §2.4). This rate limiting is itself why some traceroute hops show gaps.
The operational lesson that trips up more engineers than any other: you cannot safely blanket-filter ICMP. The reflex “ICMP is just ping, block it for security” breaks core functionality in two ways.
The ICMP black hole. If a firewall or misconfigured router drops the Fragmentation Needed (IPv4) or Packet Too Big (IPv6) message, Path MTU Discovery fails silently. RFC 2923 (“TCP Problems with Path MTU Discovery”, September 2000) documents the exact symptom: “PMTUD fails when the appropriate ICMP messages are not received by the originating host.” The sender keeps retransmitting full-size DF packets that vanish; the connection establishes and then hangs, transferring zero bytes and eventually timing out. RFC 2923 describes it precisely — “a connection that connects and starts to transfer, then eventually terminates after 15 minutes with zero bytes transferred” (RFC 2923). The tell-tale fingerprint is that small transfers and ping work fine while large transfers hang — because only large packets hit the MTU limit that needs the (blocked) ICMP feedback. The right fix is to stop filtering the message; the fallback mitigations are TCP black-hole detection (drop the segment size after repeated timeouts) and, more robustly, Packetization-Layer PMTUD (RFC 4821 / RFC 8899), which probes MTU from inside the transport and does not depend on ICMP at all — cross-linked from Maximum Transmission Unit and Path MTU Discovery.
ICMPv6 breaks far worse than ICMPv4 if filtered. Because NDP, SLAAC, and PMTUD are all ICMPv6, dropping ICMPv6 wholesale can prevent a host from even acquiring an address or resolving its neighbours. RFC 4890 (“Recommendations for Filtering ICMPv6 Messages in Firewalls”, May 2007, Informational) is the canonical guidance (RFC 4890). It states the crux directly: “Compared with the corresponding IPv4 protocol, ICMP, ICMPv6 cannot be treated as an auxiliary function with packets that can be dropped in most cases without damaging the functionality of the network.” RFC 4890 classifies messages into “must not be dropped” (Packet Too Big, the Neighbor/Router Discovery types, and the connectivity-critical errors), “may drop by policy,” and “should drop” (e.g. Router Renumbering). The practical rule: filter ICMP with a scalpel keyed on type/code and address scope, never with a blanket “deny all ICMP.”
Historic ICMP-based attacks reinforce the “handle with care, don’t blindly trust” stance: the Smurf attack (spoofed echo requests to a broadcast address, flooding the spoofed victim with replies), ICMP redirect hijacking, Ping of Death (oversized reassembled echo), and covert ICMP tunneling (smuggling data in echo payloads). The lesson is not “block all ICMP” but “rate-limit, validate, and permit the messages the protocol actually needs.”
See Also
- Directly required by ICMP: Maximum Transmission Unit and Path MTU Discovery — Fragmentation-Needed / Packet-Too-Big is the message PMTUD is built on; ARP and Neighbour Discovery — the NDP messages that are carried as ICMPv6.
- Protocol siblings (this MOC, §2): Internet Protocol Version 4 and Internet Protocol Version 6 — the datagrams ICMP rides inside; IP Addressing and CIDR Subnetting — the prefixes whose reachability you probe with
ping/traceroute. - Kernel mechanism (do not duplicate): The IP Layer and IP Routing Decision and Forwarding — where Linux generates and consumes these messages.
- Congestion: Congestion Control Fundamentals and AIMD — why Source Quench died and loss/ECN replaced it.
- PARENT MOC: Networking and Protocols MOC (§2, IP and Routing).