Summary

  • A limited-scope IPv6 address value can recur in different zones. A multihomed node therefore supplies a separate local zone index, often selected through an interface name, and consumes that context before any packet crosses the wire.
  • RFC 6874 tried in 2013 to put a ZoneID inside URI syntax. RFC 9844 obsoleted that approach in 2025 and instead required user interfaces to collect, validate and locally map zone information without turning it into a portable address or HTTP identity.

The copy that preserved the wrong thing

An operator diagnoses a device through fe80::1%eth0, copies the value into a ticket and asks a colleague to reproduce the test. On the second host, the address parser still recognizes fe80::1. The suffix may name another interface, fail to resolve or select a network unrelated to the first test.

The copy preserved syntax while discarding jurisdiction. The first machine had authority to interpret eth0 because it owned the interface table. The second received no portable proof of which physical or virtual link the operator meant.

That is not a defect in link-local addressing. RFC 4291 defines link-local unicast for use on a single link. Routers must not forward packets with link-local source or destination addresses to other links. Two separate links may each contain a node called fe80::1 without either value claiming global uniqueness.

The ambiguity arises at a node attached to both links. The 128 address bits distinguish neither one. What the application lacks is not another part of the IPv6 address but a local statement about where this use of the address belongs.

Scope was a size; zone was an instance

RFC 4007, published in March 2005, supplied the vocabulary that makes the problem tractable. Scope describes the size of a topological region. A zone is one particular instance of a region of that scope.

Link-local is therefore a scope. The maintenance Ethernet and an isolated service adapter are two link-local zones. Confusing the terms would collapse a shared architectural property—how far an address may reach—with a node’s contingent knowledge—which connected region it means now.

A node attached to several zones of the same scope assigns its own zone indexes. The index must disambiguate the node’s choices, but it is strictly local. The far end of the same link may assign a different number. No protocol requires two kernels to coordinate their interface tables.

RFC 4007 recommended the textual form <address>%<zone_id>. Implementations should accept a non-negative decimal identifier and may accept implementation-defined strings such as interface names. Since the address supplies the scope, the text after % need only select among zones of that scope.

The form carries boundaries as important as its grammar. A zone identifier is meaningless on a global address and should not be used with loopback. The combined text is for use within a node. It must not be sent on the wire unless every interpreting node has agreed on its semantics.

The footnote is thus not a small global namespace appended to IPv6. It is a compact presentation of one host’s decision context.

A custody chain built into the socket API

The basic IPv6 socket interface already represented address and local selector separately. RFC 3493, published in February 2003, defines sockaddr_in6 with a sin6_addr field for the address and a 32-bit sin6_scope_id field.

An application hands both to its local kernel. The scope identifier does not extend the 128 bits and does not become an IPv6 packet field. It guides a local routing choice, then stops.

RFC 3493 also defines mappings between interface names and indexes. if_nametoindex() asks the executing system to resolve a name. An unknown name fails. It does not consult an Internet registry for eth0, and it does not ask the destination what the sender’s name should mean.

This produces a custody chain. A human-readable UI may collect a name. The application maps it through the current operating system. The socket carries the resulting number within the process-to-kernel boundary. The IP layer applies the limited scope. The remote node receives none of the sender’s interface vocabulary.

Each transfer narrows what can be claimed. Accepting a string does not prove that it maps. Mapping to an index does not prove the interface is up. A successful send does not authenticate the respondent. Treating the combined text as one self-proving address erases precisely these checkpoints.

Canonical address text stopped before the suffix

IPv6 addresses admit multiple equivalent spellings. RFC 5952 reduced that variation in August 2010 with rules for zero compression, letter case and brackets when a literal address is paired with a port. Canonical text helps logs, search, configuration and comparison.

RFC 9844 later made an important qualification: RFC 5952 does not cover RFC 4007’s zone extension. Canonicalizing the address bits cannot canonicalize a host’s interface names. Even a numeric index remains local state rather than durable address material.

Default zones do not remove the distinction. RFC 4007 recommends defaults and normally uses zero to represent one. RFC 9844 records that not every operating system supplies a usable default and names Linux as an example.

When an application succeeds without an explicit selector, it has shown that some local context completed that operation. It has not shown that the address carried the choice. Porting the same call to another system can expose the hidden assumption.

An audit record should therefore preserve the address, the zone text supplied, the index resolved, the executing host and the time. Saving only the canonical address loses the choice. Saving only the index loses the operator’s expression and the map in which the number was valid.

A local footnote entered a global grammar

URI syntax forced the boundary into view. RFC 3986, published in January 2005, describes URIs as having global scope, even though an action associated with one may depend on the end user’s context. It also reserves % to introduce percent-encoding. A literal percent sign used as data is represented by %25.

RFC 6874 attempted to combine the forms in February 2013. In an HTTP URI, it proposed a bracketed literal such as [fe80::a%25en1]: %25 represented the delimiter percent sign, followed by the local ZoneID.

The use case was practical. A browser or other URI-driven tool needed a way to address a link-local device through one of several interfaces. Yet the RFC itself said the ZoneID was meaningful only at the originating node and should be removed before inclusion in an outgoing HTTP request.

The footnote looked like part of the URI in the address bar but had to cease being part of it before the URI governed a network message. That tension reached beyond parsing. Should the suffix affect an HTTP origin? Should it persist in history or bookmarks? Should a proxy see it? Which layer should decode %25, and how would another decoding pass change it?

Percent-encoding was not the fundamental difficulty. A temporary argument in the sender’s namespace had entered a representation meant to be stored, compared and carried between contexts. A different separator would not decide which layer owned its meaning.

Obsoleting a syntax without abandoning the task

In August 2025, RFC 9844 completely obsoleted RFC 6874. Browser implementers had found the URI approach impracticable. It also reverted RFC 6874’s update to RFC 3986; verified erratum 8552 on RFC 6874 records that changed relationship.

The replacement did not invent a third escape sequence. It moved the obligation. A user interface accepting an address other than global unicast must allow the user to enter or select a zone identifier. The complete % form is preferred, while a separate field, a list, another delimiter or a separate parameter may be used where appropriate.

The UI keeps the address and zone identifier separate, maps the latter to a local interface index and should report a bad identifier as an error. POSIX inet_pton() cannot by itself convert fe80::1%eth0. A program needs getaddrinfo(), or it must split the input and combine inet_pton() with if_nametoindex().

RFC 9844 explicitly excludes the semantics of browser-fetched URIs. It does not create a portable link-local HTTP origin or revive the suffix as transmitted identity. It standardizes the ability to supply local context to software that needs it.

This was a reduction in syntax and an improvement in accountability. The UI that can ask the user owns input. The operating system that knows the interfaces owns mapping. The protocol carries only the meaning that another node can share.

Input freedom created a validation duty

RFC 4007 did not assign a universal character repertoire or length to zone identifiers. The meaning of nonnumeric strings remained implementation-defined. That flexibility allowed operating-system names but prevented applications from relying on a single global grammar for safety.

RFC 9844 advises UIs to impose an appropriate length and reject dangerous input such as NUL. Held erratum 8553 on RFC 4007 identifies the missing character and length restrictions and points to RFC 9844’s security treatment.

A zone string can cross a form, shell, configuration file, URI widget, log pipeline and system API. Layers can decode, truncate or normalize at different times. A value displayed to the operator can differ from the one that ultimately produces an interface index.

Keeping fields separate reduces the number of interpreters asked to understand a combined mini-language. The application can validate address syntax as an address, validate the zone under local rules, and compare the resolved interface with what it presents for confirmation.

The result still has a bounded evidentiary value. A successful operation through %eth0 shows that the name resolved on that host and that the selected path worked for that operation. It does not authenticate the remote node, prove ownership of the address, promise global reachability or make the interface name portable.

A complete record made from nonportable parts

The most useful operational record is not a magic string that works everywhere. It is a set of facts whose scopes are explicit: the IPv6 value, the local identifier entered, the index produced, the host that owned the map, the interface state and the time of execution.

Such a record supports reproduction without pretending that reproduction is automatic. A second host can inspect its own topology, select the intended link and create a fresh local mapping. If it cannot, the failure exposes missing context instead of silently reusing the wrong path.

IPv6 zone identifiers solved a coordination problem by refusing to coordinate too much. Standards defined scopes, zones, API fields and UI obligations. Individual nodes retained their interface namespaces. Packets did not acquire local labels that receivers could not interpret.

The address needed a local footnote because the operation needed local knowledge. The footnote remained trustworthy only while it admitted that limit.

Sources