Frontend Labs
⋯

Part III — The Internet Layer (IPv4)

IP delivers a packet from any host to any other host, best-effort. No guarantees of delivery, order, timing, or (for the payload) integrity. Everything above IP exists to paper over those gaps.

10. The IPv4 address and header, field by field

10.1 The address

32 bits, written as four dotted-decimal octets: 192.168.1.50 = 11000000.10101000.00000001.00110010. Range 0.0.0.0–255.255.255.255, ~4.29 billion values — far too few, which is why NAT (Ch. 12) and IPv6 (Part IV) exist.

An address has two parts, split by the subnet mask:

192.168.1.50 / 24
|__________|   |__|
   address    prefix length (bits of network portion)

netmask /24 = 255.255.255.0 = 11111111.11111111.11111111.00000000
network part:  192.168.1   (first 24 bits - identifies the link)
host part:     .50         (last 8 bits - identifies the host on that link)
  • Network address (all host bits 0): 192.168.1.0 — names the subnet, not assignable to a host.
  • Broadcast address (all host bits 1): 192.168.1.255 — reaches every host on the subnet.
  • Usable host range: 192.168.1.1 – 192.168.1.254 → 2^8 − 2 = 254 hosts.
  • The "−2" does not apply to /31 links (RFC 3021, point-to-point, 2 usable) or /32 (single host).

Classful addressing is dead. You may still hear "Class A/B/C" (the pre-1993 scheme where the first bits fixed the mask). Since CIDR (Classless Inter-Domain Routing, 1993), the mask is always explicit. Ignore classes except as historical vocabulary; the class-based default masks in some old tools are a trap.

10.2 The IPv4 header

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version|  IHL  |    DSCP   |ECN|          Total Length          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Identification         |Flags|      Fragment Offset    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Time to Live |    Protocol   |         Header Checksum        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       Source IP Address                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Destination IP Address                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options (0-40 bytes, rare)                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Field Bits Purpose / real-world relevance
Version 4 4.
IHL 4 Header length in 32-bit words. 5 = 20 bytes (no options).
DSCP 6 QoS class (Ch. 51). EF = expedited forwarding for VoIP; CS0 = best effort.
ECN 2 Explicit Congestion Notification. 00 not-capable, 10/01 ECT, 11 = CE ("congestion experienced") — a router marks this instead of dropping.
Total Length 16 Whole packet incl. header. Max 65535; real max ≈ PMTU.
Identification 16 Same value on all fragments of one original packet (Ch. 15). Also abused for OS fingerprinting and idle scans.
Flags 3 bit0 reserved(0); DF Don't Fragment; MF More Fragments.
Fragment Offset 13 Position of this fragment in the original, in 8-byte units.
TTL 8 Decremented by 1 per hop. At 0 the packet is dropped and ICMP time-exceeded returned (this powers traceroute). Typical initial values: Linux/macOS 64, Windows 128, some routers 255.
Protocol 8 Payload type: 1 ICMP, 6 TCP, 17 UDP, 47 GRE, 50 ESP (IPsec), 89 OSPF.
Header Checksum 16 Covers the header only. Recomputed at every hop (because TTL changes). Does not protect the payload — that's TCP/UDP's checksum.
Source / Destination 32 each The endpoints. Rewritten only by NAT.

10.3 What a router does with this header

  1. Verify header checksum; drop if bad.
  2. Decrement TTL; if 0, drop + ICMP time-exceeded.
  3. Longest-prefix-match the destination in the forwarding table → next hop + egress interface (Ch. 13).
  4. If egress MTU < packet size: fragment (DF=0) or drop + ICMP (DF=1).
  5. Recompute header checksum (TTL changed).
  6. Resolve next-hop MAC (ARP), build new Ethernet frame, transmit.

The payload is never touched (except by NAT/firew-fixups). No per-flow state.

10.4 War story

A CDN reported that a customer's origin was "unreachable from Asia" but fine from Europe. traceroute from Asia died after 12 hops at a specific router. That router had a bug decrementing TTL by 2; packets with initial TTL 64 that took 32+ hops arrived with TTL 0 and were dropped. Raising the origin's default TTL via sysctl net.ipv4.ip_default_ttl=128 was the pragmatic workaround while the carrier fixed the router. Lesson: TTL is a hop budget; unusually long paths plus buggy hops can exhaust it.

Try it yourself

ip -4 addr show                       # your addresses and prefix lengths
ipcalc 192.168.1.50/24                # network, broadcast, host range
sudo tcpdump -i any -n -v 'ip[8]<5'   # capture packets with TTL < 5 (near-expiry)
sysctl net.ipv4.ip_default_ttl

Generated from real-life-example.md · 8 Oct 2026 16:36