Chapter 03 · Part I · The basics

IP addresses & subnets

An IP address looks like four friendly numbers with dots between them. Underneath it is a single 32-bit number, split in two: one part names a network, the other names a machine on it. Where that split falls decides who your computer talks to directly and who it hands to the router. This chapter takes the number apart, bit by bit.

32 bitsin an IPv4 address: 2³² = 4,294,967,296 possible values (RFC 791)
17,891,328private IPv4 addresses in the three RFC 1918 blocks, reused in every home and office
128 bitsin an IPv6 address: 2¹²⁸ ≈ 3.4 × 10³⁸ values; one standard /64 subnet holds 2⁶⁴ (RFC 8200, RFC 4291)

Common mix-up: the subnet mask never travels in a packet. A packet carries only a source and a destination address. The mask lives in each machine's own settings, and it's used for one decision: is this destination on my wire, or do I give it to the gateway? Two machines on the same wire with different masks can disagree about that, and the network quietly half-works.

Four bytes

The dotted quad

Every packet on the internet carries two addresses in its header: where it came from and where it's going. In IPv4, defined by RFC 791 in 1981, each of those is a field exactly 32 bits wide. Computers see 32 ones and zeros. People would rather not, so we chop the 32 bits into four 8-bit pieces, called octets, write each one as an ordinary decimal number from 0 to 255, and put dots between them. That's the dotted quad: 192.168.86.23 is just a friendlier way of writing

11000000 10101000 01010110 00010111
192 = 128+64 · 168 = 128+32+8 · 86 = 64+16+4+2 · 23 = 16+4+2+1. Each octet's bits are worth 128, 64, 32, 16, 8, 4, 2 and 1, left to right.

The dots are pure decoration. The same address is the single number 3,232,257,559, and some software will accept it in that form (try typing it into a browser's address bar some time, though most will rewrite it for you). What matters is that an address is a number, so addresses can be compared, masked and counted with ordinary arithmetic. Everything else in this chapter follows from that.

A 32-bit field allows 2³² values: 4,294,967,296. That sounded endless when the ARPANET had a few hundred hosts. It isn't, and the fixes for running out, private ranges and NAT now and IPv6 eventually, show up all through this site. For the moment the important point is smaller. An address doesn't just name a machine. Part of it names the network the machine lives on, and routers only ever look at that part.

Go deeper: the classful era, and why it ended

The original design split addresses at fixed places, based on the first few bits. If the first bit was 0, it was a class A address: the first octet named the network and the last three named the host, so there were 128 class A networks with about 16.7 million hosts each. A leading 10 meant class B: two octets of network, two of host, about 65,000 hosts per network. A leading 110 meant class C: three octets of network, one of host, 254 hosts. Class D (1110) was multicast, and class E (1111) was held in reserve.

The trouble was the sizes. A university with 2,000 machines was too big for a C and wasted 63,000 addresses in a B. Class B networks were being handed out fast enough to run out years before anything else did, and every new network was another line in every backbone router's table. In 1993 RFC 1519 threw the classes away and let the split fall on any bit. That's CIDR, and it's how every address has worked since; RFC 4632 is the current version. You still hear "class C" used to mean "a /24", but the class rules themselves are dead.

Drawing the line

Network, host, and the mask

Think of a street address. "23 Elm Street" has two parts: the street, which a mail carrier uses to get to the right neighborhood, and the house number, which only matters once they're there. An IP address works the same way. The left-hand bits are the network part, shared by every machine on the same local network. The right-hand bits are the host part, different for each machine. Routers out on the internet only care about the network part; the host part only matters at the last step.

The address alone doesn't say where the split is. A separate 32-bit number does: the subnet mask. A mask is a run of ones followed by a run of zeros. The ones cover the network part and the zeros cover the host part. 255.255.255.0 is 24 ones and 8 zeros, so on a machine with that mask, 192.168.86.23 means "host 23 on network 192.168.86.0".

Since a mask is always some ones and then zeros, you only need to say how many ones. That count is the prefix length, written after a slash: 192.168.86.23/24. This is CIDR notation, from Classless Inter-Domain Routing, and it's how routers, cloud consoles and most of this site write things. The older dotted mask and the slash say exactly the same thing.

network = address AND mask · broadcast = network OR (NOT mask)
AND keeps a bit only where the mask has a 1, so it zeroes the host part. OR with the inverted mask sets every host bit to 1. Those two results are the first and last addresses of the block.

A prefix of length p leaves 32 − p host bits, so the block holds 232−p addresses. Two of them are spoken for. The one with every host bit 0 is the network address, the name of the block itself; you'll see it in routing tables but never on a machine. The one with every host bit 1 is the broadcast address, which means "everyone here". Everything in between is usable. A /24 has 256 addresses and 254 hosts; that's why home routers hand out .1 to .254.

Each extra bit of prefix halves the block. A /25 is half a /24, 128 addresses; a /26 is a quarter, 64; a /30 has 4 addresses and only 2 hosts, which is why it was the classic size for a link between two routers. Going the other way, a /23 is two /24s glued together, 192.168.86.0 to 192.168.87.255, and it is perfectly normal for 192.168.86.255 to be an ordinary host address inside it. Blocks always start on a multiple of their own size; a /26 can start at .0, .64, .128 or .192, and nowhere else.

PrefixMaskAddressesUsable hostsTypical use
/8255.0.0.016,777,21616,777,214All of 10.0.0.0; a huge enterprise plan
/16255.255.0.065,53665,534A campus, or a cloud VPC
/20255.255.240.04,0964,094A large office floor plan; a cloud default subnet
/24255.255.255.0256254Nearly every home and small-office LAN
/26255.255.255.1926462A small VLAN: cameras, printers, a lab
/30255.255.255.25242A link between two routers, the old way
/31255.255.255.25422A point-to-point link, the thrifty way (RFC 3021)
/32255.255.255.25511One single host; a route to exactly one address
Go deeper: /31, /32, and wildcard masks

On a link with exactly two ends, the network and broadcast addresses are wasted: there's nobody else to broadcast to. RFC 3021 lets a point-to-point link use a /31, two addresses, both usable, no broadcast. Most router operating systems accept it, and on a backbone with thousands of links it halves the address bill.

A /32 is a block of one. You won't usually assign it to an ordinary LAN interface, but it appears constantly in routing tables as a host route: "to reach exactly this one address, go this way." Loopback addresses on routers, VPN peers and many overlay networks are /32s. Tailscale, for example, gives each device a single address and routes to it as a /32 rather than putting the whole tailnet on one shared subnet.

Cisco access lists and OSPF configurations use the wildcard mask, which is the mask turned inside out: 0.0.0.255 instead of 255.255.255.0. Ones mean "don't care". The calculator below shows it alongside the normal mask so you can stop converting in your head.

Instrument 1

A subnet calculator you can break

Type an address, pick a prefix, and watch the bit math. The top row is the address; click any of its bits to flip it. The second row is the mask; click a bit there to move the line between network and host. The bottom two rows are computed: AND for the network, OR with the inverted mask for the broadcast. You can also type an address with a slash, like 10.4.7.200/21.

Network–
Broadcast–
First host–
Last host–
Usable hosts–
Mask–
Wildcard–
This address is–

The calculator does the arithmetic on a real 32-bit unsigned number, the same way a kernel does. Try 192.168.86.255 at /24 and then at /23, or 169.254.17.4, or a /31.

Neighborhoods with rules

Private, loopback, link-local and other special ranges

Most of the 4.3 billion addresses are ordinary public ones, assigned by IANA to five regional registries and from them to ISPs and companies. But a few blocks carry special meanings, and you will meet all of them on your own machines. IANA keeps the official list in its special-purpose address registry, described in RFC 6890.

Private addresses, from RFC 1918, are the ones your home network uses: 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. Anyone may use them without asking, as often as they like, on the condition that they never appear on the public internet. Internet routers drop them. That's what makes it safe for millions of homes to be numbered 192.168.1.x at once, and it's also why you need NAT to get out (Chapter 7). Note the odd one: 172.16.0.0/12 runs from 172.16.0.0 to 172.31.255.255, not just 172.16.x.x, a detail that catches people writing firewall rules.

Loopback is 127.0.0.0/8, nearly 17 million addresses that all mean "this machine". RFC 1122 says a packet to 127-anything must never leave the host; it goes down the network stack and straight back up. 127.0.0.1 is the one everyone uses, and "localhost" is its name. When a program listens only on 127.0.0.1, nothing on the network can reach it, which is exactly why developers do it.

Link-local is 169.254.0.0/16, from RFC 3927. A machine that is told to get an address automatically, and finds no DHCP server to give it one, picks a random address in 169.254.1.0 to 169.254.254.255, checks with ARP that nobody else has it, and uses it. It can now talk to other machines on the same wire that did the same thing, and to nothing else: routers never forward 169.254 packets. Microsoft calls this APIPA, and ipconfig labels it "Autoconfiguration IPv4 Address".

In practice a 169.254 address is a smell, and a very useful one. It almost always means "this interface asked for DHCP and nobody answered." The cable is plugged into a dead port, the Wi-Fi association failed halfway, the DHCP server is down, or the interface is a virtual one with nothing behind it. A Windows laptop with Hyper-V switches, bridges and old VPN adapters can show several adapters sitting on 169.254 addresses at once, each one a little island that nothing will ever answer. They are harmless by themselves, but they are extra interfaces for every networking program to consider, and that matters later (Chapter 12).

Shared address space is 100.64.0.0/10, from RFC 6598, set aside in 2012 for carrier-grade NAT. An ISP running out of public addresses puts its customers' routers on 100.64 addresses and NATs them again at its own edge. It was carved out separately from RFC 1918 precisely so it couldn't collide with the 192.168 or 10 networks those customers use at home. You'll meet it twice on this site: as the sign of a CGNAT in Chapter 8, and as the range Tailscale assigns its device addresses from, because a private overlay needs addresses unlikely to clash with any LAN it runs on.

BlockRangeMeaningDefined in
0.0.0.0/80.0.0.0 – 0.255.255.255"This network"; 0.0.0.0 alone means "no address yet" or "any address"RFC 1122, RFC 6890
10.0.0.0/810.0.0.0 – 10.255.255.255PrivateRFC 1918
100.64.0.0/10100.64.0.0 – 100.127.255.255Shared address space for carrier-grade NATRFC 6598
127.0.0.0/8127.0.0.0 – 127.255.255.255Loopback: this hostRFC 1122
169.254.0.0/16169.254.0.0 – 169.254.255.255Link-local (APIPA): no DHCP answeredRFC 3927
172.16.0.0/12172.16.0.0 – 172.31.255.255PrivateRFC 1918
192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24three /24sDocumentation and examples onlyRFC 5737
192.168.0.0/16192.168.0.0 – 192.168.255.255PrivateRFC 1918
224.0.0.0/4224.0.0.0 – 239.255.255.255Multicast (the old class D)RFC 5771
240.0.0.0/4240.0.0.0 – 255.255.255.254Reserved (the old class E)RFC 1112, RFC 6890
255.255.255.255/32one addressLimited broadcast: everyone on this linkRFC 919
Go deeper: how a link-local address gets picked

RFC 3927 is careful about collisions, because there's no server keeping track. The host picks an address at random from 169.254.1.0 through 169.254.254.255 (the first and last /24 are reserved), seeding the random choice from something stable such as its MAC address so it tends to pick the same one each time. It then sends a few ARP probes: "who has 169.254.17.4?" with its own sender address left as 0.0.0.0, so it doesn't claim anything yet. If anyone answers, it picks again. If nobody does, it announces the address with gratuitous ARPs and starts using it.

A host is supposed to keep asking for DHCP in the background and drop the link-local address as soon as a real one arrives. That's why unplugging and replugging a cable, or toggling Wi-Fi, so often "fixes" a 169.254 address: it simply triggers another DHCP attempt (Chapter 4).

Talking to everyone

Broadcast, and where it stops

Sometimes a machine needs to reach everyone nearby without knowing who's there. The most important example comes first in every machine's life: a laptop joining a network has no address yet, so it can't ask any particular server for one. It shouts a DHCP request to 255.255.255.255, the limited broadcast address, and every machine on the link hears it. ARP, the protocol that turns an IP address into a hardware address (Chapter 2), also asks its question as a broadcast.

A broadcast reaches exactly as far as the local link, the set of machines that share a switch or a Wi-Fi access point without a router in between. Routers stop broadcasts. That boundary has a name, the broadcast domain, and in the simplest network it's the same thing as the subnet. It's one of the reasons networks are split into subnets at all: a thousand chatty machines on one link means every machine has to listen to every broadcast from all the others.

The second kind is the directed broadcast, the all-ones host address of a particular subnet, like 192.168.86.255 for 192.168.86.0/24. In principle it lets someone far away broadcast to a remote subnet. In practice that turned out to be an excellent way to amplify attacks (a single forged ping to a directed broadcast would draw hundreds of replies at a victim), and since RFC 2644 in 1999 routers must not forward directed broadcasts unless someone has turned it on deliberately.

IPv6 has no broadcast at all. Anything that would have been a broadcast is sent to a multicast group instead, and only the machines that joined that group need to wake up. ff02::1, the all-nodes group, is the closest thing to "everyone".

The one decision

Local, or via the gateway?

Here is where all the bit-twiddling pays off. Every time a machine sends an IP packet, before anything else, it asks one question: is the destination on my own link? If yes, it can deliver the packet directly. If no, it has to give the packet to a router, its default gateway, and let the router worry about it.

The test is a two-line calculation. Take your own address and AND it with your own mask: that's your network. Take the destination address and AND it with your mask, the same one: that's the network the destination would be on, as far as you can tell. If the two results are equal, the destination is local. If not, it's somewhere else.

What happens next is different for the two answers, and the difference is in the hardware address. On an Ethernet or Wi-Fi link, a frame has to be addressed to a MAC address. If the destination is local, the machine uses ARP to find the destination's own MAC and sends the frame straight there. If the destination is remote, it uses ARP to find the gateway's MAC instead, and sends the frame to the router with the destination IP address unchanged. The IP header says "this is for 198.51.100.20"; the Ethernet frame around it says "give this to the router". That's the whole trick of routing at the first hop.

Take a laptop at 192.168.86.23/24 with gateway 192.168.86.1. Its network is 192.168.86.0. A printer at 192.168.86.40 ANDs to 192.168.86.0: same, so the laptop ARPs for the printer and talks to it directly. Now it tries 192.168.1.1, the admin page of a second router upstream. 192.168.1.1 ANDs to 192.168.1.0, which is not 192.168.86.0, so the packet goes to 192.168.86.1, even though both addresses are private and both are "in the house". That is what a double NAT looks like from the laptop's chair: the network it's on, 192.168.86.0/24, sits behind a router whose own outside address is on a different private network, 192.168.1.0/24, run by another router (Chapter 8).

When the masks are wrong

Because each machine runs the test with its own mask, a wrong mask breaks things in lopsided ways. Give that laptop a /16 by mistake and it believes 192.168.1.1 is local. It ARPs for it on its own Wi-Fi, nobody answers (the real 192.168.1.1 is on the far side of a router), and after a few seconds Windows reports "Destination host unreachable" from the laptop's own address. Meanwhile the internet works fine, because 198.51.100.20 still ANDs to something else and goes to the gateway. Half-broken networks like that are almost always a mask or gateway typo.

The opposite mistake, a mask that's too long, is quieter. The laptop thinks a neighbor is remote and sends the packets to the router, which forwards them back out the same interface to the neighbor. It works, a little slower, and many routers send back an ICMP redirect message saying "next time, go direct". Some people never notice.

Go deeper: the routing table is the real answer

"Local or gateway" is a simplification of what the operating system actually does. When you configure an address and mask, the system adds a connected route to its routing table: 192.168.86.0/24, on-link, via this interface. The default gateway becomes a route too: 0.0.0.0/0 via 192.168.86.1. Every packet is then looked up in the table, and the most specific matching route wins. The same-subnet test is just that lookup with only two routes in the table.

With more interfaces the table grows, and things get interesting. A VPN adds its own routes; an overlay network adds /32s for each peer; a virtual switch adds another connected network. When two interfaces claim overlapping networks, the longest prefix still wins, and when they tie, the interface metric breaks the tie. Chapter 10 builds that lookup, and you can watch it choose.

Instrument 2

Same subnet, or not?

Host A wants to send to host B. Set A's address, mask and gateway, and B's address and mask. The top lines do A's test, AND by AND. The picture plays out what A does next: ARP for B directly, or ARP for the gateway and hand the packet over. B's own mask decides where B really lives, so you can set up a mismatch and watch the ARP go unanswered.

A's network–
B under A's mask–
A decides–
A ARPs for–
Outcome–

"Where B really is" defaults to Auto: B counts as on A's wire when B's own address and mask put A on B's network. Override it to model a cable in the wrong port.

The bigger number

IPv6: 128 bits and the end of scarcity

IPv6, now specified in RFC 8200, is the long-term answer to running out. Its addresses are 128 bits, four times as long, which allows about 3.4 × 10³⁸ of them. That isn't "a lot more". It's enough that the design stops treating addresses as something to ration.

128 bits written as dotted decimals would be sixteen numbers long, so IPv6 uses hexadecimal instead: eight groups of four hex digits, separated by colons. 2001:0db8:0000:0086:1c2b:3dff:fe4e:5f60. Two shortcuts keep it readable. Leading zeros in a group can be dropped, so 0db8 becomes db8 and 0000 becomes 0. And one run of all-zero groups can be replaced by a double colon, once per address: 2001:db8:0:0:0:0:0:1 is 2001:db8::1. RFC 5952 sets the canonical way to write them, lowercase and as short as possible, so that the same address always looks the same in logs.

The split between network and host still exists, and it's still written with a slash, but IPv6 settles where it usually falls. Nearly every LAN is a /64: the first 64 bits are the network prefix, handed down from your ISP and router, and the last 64 bits are the interface identifier, chosen by the device itself. A /64 holds 2⁶⁴ addresses, about 18 billion billion, on one LAN. Nobody will ever fill it, and that's the point: devices can pick their own addresses at random with essentially no chance of colliding. That's SLAAC, stateless address autoconfiguration (RFC 4862): the router announces the prefix, and each device appends an identifier of its own.

Every IPv6 interface also gets a link-local address in fe80::/10 the moment it comes up, whether or not anything else is configured. Unlike IPv4's 169.254, this isn't a failure sign; it's normal and necessary, because IPv6's neighbor discovery and router discovery run over link-local addresses. Since every interface has one in the same range, a link-local address alone doesn't say which interface to use, so you'll see it written with a zone: fe80::1%12 on Windows, fe80::1%en0 on a Mac.

And NAT mostly goes away. With 2⁶⁴ addresses per LAN, there's no shortage for translation to paper over. Each device gets a global address, packets carry it end to end, and two devices that want to reach each other can, as long as the firewalls between them allow it. That last clause is important. A home router doesn't translate IPv6, but it should still run a stateful firewall that drops unsolicited inbound connections, which is the protection people used to credit to NAT anyway.

IPv6 prefixMeaningIPv4 cousin
::1/128Loopback127.0.0.1
::/128Unspecified, "no address yet"0.0.0.0
fe80::/10Link-local; on every interface, always169.254.0.0/16, but healthy
fc00::/7 (in practice fd00::/8)Unique local addresses, for private useRFC 1918 private ranges
2000::/3Global unicast: real, routable addressesPublic IPv4
ff00::/8Multicast; ff02::1 is all nodes on the link224.0.0.0/4 and broadcast
2001:db8::/32Documentation and examples only192.0.2.0/24 and friends
Go deeper: where the interface identifier comes from, and ARP's replacement

The original recipe built the 64-bit identifier from the interface's 48-bit MAC address, by splitting it in half, inserting ff:fe in the middle and flipping one bit. That's the "ff:fe" you can see in the middle of the example address on this page. It was tidy and stable, and it meant a laptop carried the same identifier from network to network, which anyone could use to follow it around. Modern systems use temporary random identifiers for outgoing connections (RFC 8981) and stable-but-opaque ones otherwise.

IPv6 doesn't use ARP. Its Neighbor Discovery protocol (RFC 4861) does the same job with ICMPv6 messages sent to a special multicast group derived from the address being looked up, so only the machine that might own the address needs to listen, instead of every machine on the link. Neighbor Discovery also carries the router advertisements that tell devices their prefix and default gateway.

The local-or-gateway decision is the same idea with a twist. A host learns which prefixes are on-link from router advertisements, not by assuming that its own address and mask tell the whole story. Everything else is routed via a router's link-local address, which is why an IPv6 default route usually points at something starting fe80.

Cheat sheet

Terms from this chapter

Octet
Eight bits; one of the four numbers in a dotted quad, 0 to 255.
Network part / host part
The left bits shared by everyone on a subnet, and the right bits unique to each machine.
Subnet mask
A 32-bit run of ones then zeros that marks where the network part ends. 255.255.255.0 is /24.
Prefix length / CIDR
The number of ones in the mask, written after a slash: 192.168.86.0/24. RFC 4632.
Network address
All host bits zero: the name of the block. Not given to a machine.
Broadcast address
All host bits one: everyone on this subnet. 255.255.255.255 is everyone on this link.
Default gateway
The router a host sends anything non-local to.
Private address
10/8, 172.16/12, 192.168/16 (RFC 1918). Free to reuse, never routed on the internet.
Loopback
127.0.0.0/8 and ::1. Packets never leave the machine.
Link-local / APIPA
169.254.0.0/16: self-assigned when DHCP doesn't answer. In IPv6, fe80::/10, always present.
Shared address space
100.64.0.0/10 (RFC 6598), for carrier-grade NAT. Also where Tailscale numbers its devices.
/64
The standard IPv6 subnet: 64 bits of prefix, 64 bits of interface identifier.
Where this comes from

Sources