skip to content

Address Space and Notation

Writing and compressing colon-hex addresses, and reading the prefix to tell whether an address is link-local, unique-local or globally routable. The :: compression rules are a favourite quick test.

on this pageshow

questions

5

How is a 128-bit IPv6 address written as text, and what rules govern compressing it with :: in RFC 5952 canonical form?

level: juniorimportance: must knowfreq 62%

answer

  1. eight sixteen-bit groups
  2. leading zeros go, trailing stay
  3. one double colon only
  4. longest zero run, first on a tie
  5. never for a lone zero group

basics

~20 s

An IPv6 address is eight 16-bit hex groups separated by colons. RFC 5952 canonical form drops leading zeros, uses lowercase, and writes :: once, for the longest run of two or more zero groups, the first run on a tie.

solid answer

~40 s

An IPv6 address is 128 bits, written as eight 16-bit groups of one to four hex digits separated by colons. RFC 4291 lets you drop leading zeros inside a group and replace one run of all-zero groups with `::`, which may appear only once, because a parser could not otherwise tell how many groups each `::` hides. RFC 5952 then fixes one canonical output: lowercase, leading zeros always dropped, a zero group written `0`, `::` used to the maximum on the longest run of zero groups (the first if two runs tie), and never to shorten a single zero group. So `2001:0DB8:0000:0000:0001:0000:0000:0001` becomes `2001:db8::1:0:0:1`. Parsers must still accept every legal RFC 4291 form; the canonical rules govern what software writes.

go deeper

for a junior

Know the shape: eight 16-bit hex groups, leading zeros dropped, :: once for a run of zero groups. Expand and compress a couple of addresses by hand until it is automatic.

for a middle

Explain why :: may appear only once and apply all of RFC 5952's tie-breaks: longest run wins, first on a tie, never a single group, lowercase output.

for a senior

Separate what parsers must accept from what software should emit, and push teams to store and compare addresses as 128-bit values rather than strings in logs and inventories.

for a principal

Treat canonical form as a data-quality standard: inventory, logging and audit tooling across teams should emit RFC 5952 text so that searches, diffs and joins across systems agree.

## The 128 bits and the eight groups An **IPv6 address** is a 128-bit number. Written in full it is eight **groups** (RFC 4291 calls them 16-bit pieces) of four hexadecimal digits, separated by colons: `2001:0db8:0000:0000:0001:0000:0000:0001` Each hex digit is 4 bits, so each group is 16 bits and eight groups make 128. The text form exists for people, logs and configuration files: inside the packet header the address is always the full 128 bits, so compressing the text never changes what goes on the wire. ## What RFC 4291 allows RFC 4291 (the IPv6 addressing architecture) defines the legal text forms: - **Leading zeros** inside a group may be dropped: `0db8` can be written `db8`, `0001` can be written `1`. **Trailing** zeros may not: `cd30` is not `cd3`. - Every group must keep at least one digit, except where `::` stands in. - **`::`** means "one or more groups of zeros". It can compress leading zeros (`::1`), trailing zeros (`2001:db8::`) or a run in the middle. - `::` may appear **only once**. With two of them, as in `2001:db8::1::2`, the reader knows six groups are missing in total but not how they split, so the address is ambiguous and invalid. - Hex digits may be upper or lower case; RFC 4291 states no preference. That flexibility means one address has many legal spellings. RFC 5952 (2010) lists the damage: searches in spreadsheets and logs miss matches, configuration diffs show changes where none happened, and audit scripts need their own parsers. ## What RFC 5952 makes canonical RFC 5952 recommends one output form. Software SHOULD generate it, and every implementation MUST still accept any legal RFC 4291 form as input. | Rule (RFC 5952 section) | Correct | Not canonical | |---|---|---| | Leading zeros MUST be suppressed (4.1) | `2001:db8::1` | `2001:0db8::0001` | | A zero group is written `0` (4.1) | `2001:db8:0:1:1:1:1:1` | `2001:db8:0000:1:1:1:1:1` | | `::` is used to its maximum (4.2.1) | `2001:db8::2:1` | `2001:db8::0:2:1` | | `::` MUST NOT shorten a single zero group (4.2.2) | `2001:db8:0:1:1:1:1:1` | `2001:db8::1:1:1:1:1` | | The longest zero run gets `::` (4.2.3) | `2001:db8:0:1::1` | `2001:db8::1:0:0:0:1` | | On a tie, the first run gets `::` (4.2.3) | `2001:db8::1:0:0:1` | `2001:db8:0:0:1::1` | | Hex letters are lowercase (4.3) | `2001:db8::c0de` | `2001:DB8::C0DE` | Note the difference between "not canonical" and "invalid". `2001:db8::1:1:1:1:1` is a perfectly legal RFC 4291 address (the `::` hides one group); RFC 5952 only says a program must not print it that way. ## Worked compressions 1. `2001:0db8:0000:0000:0000:0000:0002:0001`: drop leading zeros, then one run of four zero groups becomes `::`, giving `2001:db8::2:1`. 2. `2001:0db8:0000:0001:0000:0000:0000:0001`: two zero runs, of one and three groups. The run of three wins, and the lone zero stays as `0`: `2001:db8:0:1::1`. 3. `2001:0db8:0000:0000:0001:0000:0000:0001`: two runs of two tie, so the first is compressed: `2001:db8::1:0:0:1`. 4. Expanding `2001:db8::8:800:200c:417a`: six groups are written, so `::` stands for two, giving `2001:0db8:0000:0000:0008:0800:200c:417a`. 5. The all-zero address is `::` (the unspecified address) and `0:0:0:0:0:0:0:1` is `::1` (loopback). A reliable method for expanding: count the written groups, subtract from eight, insert that many `0000` groups where `::` sits, then left-pad every group to four digits. ## Mixed notation, prefixes and ports - Addresses that embed an IPv4 address in their low 32 bits may end in dotted decimal. RFC 5952 section 5 recommends this for well-known embedding prefixes, with the leading hex part still canonical: `::ffff:192.0.2.1`, not `0:0:0:0:0:ffff:192.0.2.1`. - A **prefix** is written `address/prefix-length`, and the address part may use any legal form. The compression rules still bite: `2001:db8::cd30/60` puts `cd30` in the last group, not the fourth. - With a port number, RFC 5952 section 6 says the bracket style from URIs SHOULD be used: `[2001:db8::1]:443`. The form `2001:db8::1:443` is NOT RECOMMENDED, because the port reads as the last group. ## Why it matters in practice Treat addresses as 128-bit values and compare them as values. Canonical form is for what software writes: - **Logs**: one spelling per address means a plain text search finds every line about it. - **Configuration and inventories**: diffs show only real changes, not someone's preferred padding. - **Audits and joins across systems**: two tools that both emit RFC 5952 text agree without a custom parser. It is not a substitute for parsing what a user or a peer typed: input can arrive in any legal RFC 4291 form, and a program that compares raw strings will treat `2001:db8::1` and `2001:DB8:0:0:0:0:0:1` as different hosts.

  • Is 2001:db8::1:1:1:1:1 a valid IPv6 address, given that RFC 5952 forbids :: for a single zero group?
    Yes. RFC 4291 defines `::` as one or more zero groups, so it parses to `2001:db8:0:1:1:1:1:1`. RFC 5952 governs output: software should not generate that spelling, but it MUST accept any legal RFC 4291 form as input. Rejecting it would be a parser bug.
  • How do you write an IPv6 address together with a transport port number?
    Put the address in square brackets, as in `[2001:db8::1]:443`; RFC 5952 section 6 says this URI style SHOULD be used. Without brackets, `2001:db8::1:443` is ambiguous, because `443` reads as a final hex group and the `::` expands differently.
  • Does compressing an address with :: make IPv6 packets smaller?
    No. The source and destination fields in the IPv6 header are always 128 bits each. `::` and dropped leading zeros exist only in the text form that people and configuration files use; the binary address is identical however it is spelled.

saying these in an interview costs you the question

  • You can use :: twice if each zero run is short enough.
  • Trailing zeros in a group can be dropped just like leading zeros.
  • Canonical form compresses the first zero run even when a later run is longer.
  • A single zero group should become :: to save characters.
  • An address written in uppercase hex is invalid and must be rejected.
open as a page

Reading only the leading bits of an IPv6 address, how do you tell loopback, link-local, unique local and global unicast apart?

level: middleimportance: must knowfreq 52%

basics

~20 s

The high-order bits identify the type: ::1 is loopback, fe80::/10 (fe80 to febf) is link-local, fc00::/7 (fc or fd, in practice fd00::/8) is unique local, and 2000::/3 (first digit 2 or 3) is where global unicast is allocated today.

open as a page

Why is /64 the standard IPv6 subnet size, and how many /64 subnets does a /48 or a /56 site prefix contain?

level: middleimportance: should knowfreq 38%

basics

~20 s

RFC 4291 fixes a 64-bit interface ID for most unicast addresses, so a LAN subnet is /64. A site prefix holds 2 to the power (64 minus its length) of them: 65,536 in a /48, 256 in a /56.

open as a page

A service blocks internal destinations with an IPv4-only deny list (127.0.0.0/8, 10.0.0.0/8, 169.254.0.0/16); which IPv6 address forms slip past it, and how should the check work?

level: seniorimportance: should knowfreq 24%

basics

~10 s

IPv6 loopback ::1, the unspecified ::, link-local fe80::/10, unique local fc00::/7 and IPv4-mapped forms such as ::ffff:127.0.0.1 all bypass it. Parse the address to 128 bits, unwrap mapped IPv4, then test the IPv6 blocks.

open as a page

Why does an IPv6 unique local prefix carry a pseudo-random 40-bit Global ID, and what goes wrong when every site simply uses fd00::/48?

level: middleimportance: nice to knowfreq 16%

basics

~20 s

RFC 4193 gives each site a pseudo-random 40-bit Global ID after fd so two sites' prefixes almost never match. Everyone choosing fd00::/48 recreates the ambiguity of deprecated site-local: merged networks and VPNs collide and must renumber.

open as a page