IP addresses and subnets

Network and host identifiers, subnet masks with AND, IPv4 and IPv6, public and private addresses.

A12.5Networks and the webA level30 min

Do this lesson in the simulator

At GCSE (F10.5) an IPv4 address was four numbers from 0 to 255, and IPv6 was the longer, hexadecimal version. At A level an IP address has a structure: part of it names the network and the rest names the host on that network. A subnet mask says where the split is, and a single bitwise AND, which you met in A7, tells a device whether another address is on its own network or must be reached through a router.

Network and host

An IPv4 address is 32 bits, written as four bytes in denary: 192.168.4.70. It has two parts:

  • the network identifier, the leftmost bits, shared by every device on the same network (subnet);
  • the host identifier, the remaining bits, which is different for each device on that network.

Routers across the Internet only need to know how to reach each network, not each of the billions of hosts, which keeps routing tables manageable.

Subnet masks

A subnet mask is a 32-bit number with 1s in every network bit position and 0s in every host bit position. 255.255.255.0 is 24 ones then 8 zeros: the first three bytes are the network, the last byte the host. The same mask is often written as a prefix length after the address: 192.168.4.70/24.

To find the network identifier, AND the address with the mask. Where the mask is 1 the address bit is kept; where it is 0 the result is 0.

Here is 192.168.4.70/26. The mask is 26 ones, so the last byte of the mask is 11000000, which is 192: the mask is 255.255.255.192. The first three bytes pass through unchanged, so only the last byte needs working:

Binary (last byte) Denary
Address 01000110 70
Mask 11000000 192
Address AND mask 01000000 64

So the network address is 192.168.4.64. With the host bits all set to 1 instead (01111111) you get the network's broadcast address, 192.168.4.127, which sends to every host on the subnet. The all-0s and all-1s host identifiers are reserved for these two uses, so a subnet with h host bits has 2h − 2 usable host addresses. Here h = 6, so 64 − 2 = 62 hosts.

A second example, 10.20.30.40/20: 20 ones make the mask 255.255.240.0. The third byte works out as 30 AND 240: 00011110 AND 11110000 = 00010000 = 16. The fourth byte is ANDed with 0. The network is 10.20.16.0.

Local or through the router?

Before sending, a host ANDs the destination address with its own subnet mask and compares the result with its own network identifier. If they are equal the destination is on the same subnet, and the packet is sent to it directly. If not, the packet goes to the default gateway, the router, to be sent on.

SUBROUTINE SameSubnet(myAddress, otherAddress, mask)
  RETURN (myAddress AND mask) = (otherAddress AND mask)
ENDSUBROUTINE
def to_int(address):
    value = 0
    for part in address.split("."):
        value = value * 256 + int(part)       # shift the bytes in one at a time
    return value

me = to_int("192.168.4.70")
mask = to_int("255.255.255.192")
for other in ["192.168.4.100", "192.168.4.130"]:
    same = me & mask == to_int(other) & mask
    print(other, "same subnet" if same else "send via the router")

import ipaddress                                 # Python's own library agrees
print(ipaddress.ip_network("192.168.4.70/26", strict=False))

Run this in the simulator

Splitting one network into several smaller subnets, subnetting, lets an organisation keep departments' traffic apart, reduce the number of devices that receive each broadcast, and apply different security rules to each subnet.

IPv4 and IPv6

IPv4's 32 bits give 232, about 4.3 billion, addresses. That is fewer than the number of people alive, let alone phones, laptops, televisions, cars and sensors, and most of the regional registries have run out of new IPv4 blocks to hand out. IPv6 was introduced to fix this.

IPv4 IPv6
Size 32 bits 128 bits, about 3.4 × 1038 addresses
Written as four denary numbers, 0 to 255, separated by dots eight groups of four hexadecimal digits, separated by colons
Example 192.168.4.70 2001:0db8:85a3:0000:0000:8a2e:0370:7334

IPv6 addresses can be shortened: leading zeros in a group may be left out, and one run of consecutive all-zero groups may be replaced by ::, so the example is 2001:db8:85a3::8a2e:370:7334. The :: may appear only once, or the reader could not tell how many zero groups each one stands for.

With so many addresses, every device can have its own globally unique IPv6 address, which removes the need for NAT (A12.6). IPv4 and IPv6 are still used side by side, with most devices supporting both.

Public and private addresses

A public (routable) IP address is unique across the whole Internet and is allocated through the Internet registries. Packets addressed to it can be routed to it from anywhere.

A private (non-routable) address is used only inside a local network. Three blocks are reserved for private use, and Internet routers will not forward packets addressed to them:

Private block Prefix Range
10.0.0.0 /8 10.0.0.0 to 10.255.255.255
172.16.0.0 /12 172.16.0.0 to 172.31.255.255
192.168.0.0 /16 192.168.0.0 to 192.168.255.255

Because private addresses never appear on the Internet, millions of homes and schools can all use 192.168.1.x at once without conflict. It saves public addresses, and devices with private addresses cannot be reached directly from outside, which adds a layer of protection. A device with a private address reaches the Internet through a router that has a public address and translates between the two (NAT, A12.6).

Task: local or through the router?

The robot has the address 192.168.4.70 with prefix length 26.

Write to_int(address), which turns a dotted IPv4 string into one integer from 0 to 232 − 1, and to_dotted(value), which turns such an integer back into a dotted string. Work the mask out from the prefix length, not by typing it. Then print, one per line:

  • mask: <dotted mask>
  • network: <dotted network address>, the robot's address AND the mask
  • broadcast: <dotted broadcast address>, the network address with every host bit set to 1
  • hosts: <n>, the number of usable host addresses

Then for each of 192.168.4.100, 192.168.4.130, 172.20.1.9, 8.8.8.8 and 192.168.4.65, in that order, print <address> <where> <kind>: where is local if it is on the robot's subnet and router if not; kind is private if it lies in one of the three private blocks and public otherwise. Use & to find network addresses. That is 9 lines in all. The robot does not drive.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def to_int(address):
    return 0

def to_dotted(value):
    return "0.0.0.0"

robot, bits = "192.168.4.70", 26

Challenges

  1. Work out by hand the network address and number of hosts for 172.16.200.9/21, then check with your program.
  2. Write shorten(ipv6) that removes leading zeros from each group of a full IPv6 address.
  3. A network needs 500 hosts. What is the longest prefix length that gives enough addresses?