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.
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.
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
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.
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.
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.
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.
| Prefix | Mask | Addresses | Usable hosts | Typical use |
|---|---|---|---|---|
| /8 | 255.0.0.0 | 16,777,216 | 16,777,214 | All of 10.0.0.0; a huge enterprise plan |
| /16 | 255.255.0.0 | 65,536 | 65,534 | A campus, or a cloud VPC |
| /20 | 255.255.240.0 | 4,096 | 4,094 | A large office floor plan; a cloud default subnet |
| /24 | 255.255.255.0 | 256 | 254 | Nearly every home and small-office LAN |
| /26 | 255.255.255.192 | 64 | 62 | A small VLAN: cameras, printers, a lab |
| /30 | 255.255.255.252 | 4 | 2 | A link between two routers, the old way |
| /31 | 255.255.255.254 | 2 | 2 | A point-to-point link, the thrifty way (RFC 3021) |
| /32 | 255.255.255.255 | 1 | 1 | One single host; a route to exactly one address |
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.
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.
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.
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.
| Block | Range | Meaning | Defined in |
|---|---|---|---|
| 0.0.0.0/8 | 0.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/8 | 10.0.0.0 – 10.255.255.255 | Private | RFC 1918 |
| 100.64.0.0/10 | 100.64.0.0 – 100.127.255.255 | Shared address space for carrier-grade NAT | RFC 6598 |
| 127.0.0.0/8 | 127.0.0.0 – 127.255.255.255 | Loopback: this host | RFC 1122 |
| 169.254.0.0/16 | 169.254.0.0 – 169.254.255.255 | Link-local (APIPA): no DHCP answered | RFC 3927 |
| 172.16.0.0/12 | 172.16.0.0 – 172.31.255.255 | Private | RFC 1918 |
| 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 | three /24s | Documentation and examples only | RFC 5737 |
| 192.168.0.0/16 | 192.168.0.0 – 192.168.255.255 | Private | RFC 1918 |
| 224.0.0.0/4 | 224.0.0.0 – 239.255.255.255 | Multicast (the old class D) | RFC 5771 |
| 240.0.0.0/4 | 240.0.0.0 – 255.255.255.254 | Reserved (the old class E) | RFC 1112, RFC 6890 |
| 255.255.255.255/32 | one address | Limited broadcast: everyone on this link | RFC 919 |
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).
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".
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).
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.
"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.
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.
"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.
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 prefix | Meaning | IPv4 cousin |
|---|---|---|
| ::1/128 | Loopback | 127.0.0.1 |
| ::/128 | Unspecified, "no address yet" | 0.0.0.0 |
| fe80::/10 | Link-local; on every interface, always | 169.254.0.0/16, but healthy |
| fc00::/7 (in practice fd00::/8) | Unique local addresses, for private use | RFC 1918 private ranges |
| 2000::/3 | Global unicast: real, routable addresses | Public IPv4 |
| ff00::/8 | Multicast; ff02::1 is all nodes on the link | 224.0.0.0/4 and broadcast |
| 2001:db8::/32 | Documentation and examples only | 192.0.2.0/24 and friends |
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.