What an IP address is

An IP address (Internet Protocol address) is the logical address of a network interface in an IP network. Where a MAC address is burned into a network card and only matters on the local link, an IP address is assigned by whoever runs the network and says where the interface is: which network it belongs to, and which host it is within that network. Routers use that structure to move packets across many networks, the way a postal service uses a country, city and street.

IPv4 (Internet Protocol version 4) is the version of IP defined in RFC 791 in 1981, and still carries most traffic inside company networks. Its addresses are 32 bits long, which gives 232, about 4.3 billion, addresses. That turned out to be too few for the internet, which is why private addresses, network address translation (NAT) and eventually IPv6 exist.

Dotted-decimal notation

Thirty-two ones and zeros are unreadable, so an IPv4 address is written as four octets (groups of 8 bits), each shown as a decimal number from 0 to 255, separated by dots. Python's ipaddress module shows what is behind the notation (see Number Systems for binary itself):

import ipaddress

address = ipaddress.IPv4Address("192.168.1.10")
print(" ".join(f"{byte:08b}" for byte in address.packed))
print(int(address))
print(ipaddress.IPv4Address(3232235786))
11000000 10101000 00000001 00001010
3232235786
192.168.1.10

address.packed gives the four bytes; each is printed as 8 binary digits. To the computer the address is just one 32-bit number, 3232235786, and converting that number back gives the familiar notation again.

Try it: an octet in binary

Convert one octet between decimal and its 8 bits, and see which place values (128 down to 1) add up to the number.

Convert

A whole number from 0 to 255, or 8 bits such as 10101000.

The network part and the host part

Every IPv4 address consists of two parts. The leading bits, the network part (or prefix), are the same for all hosts on one network. The remaining bits, the host part, are different for each host on it. Where the boundary lies is not visible in the address itself; it is configured together with the address.

The subnet mask

A subnet mask is a 32-bit value that marks which bits of an IPv4 address belong to the network part: ones for the network bits, then zeros for the host bits. It is written in dotted decimal like an address. The mask 255.255.255.0 is 24 ones followed by 8 zeros, so with 192.168.1.10 the first three octets (192.168.1) are the network and the last octet (10) is the host.

The address 192.168.1.10 in decimal and binary, with the mask 255.255.255.0 below it. The first 24 bits, where the mask has ones, are the network part; the last 8 bits, where the mask has zeros, are the host part. Decimal Binary Mask /24 192 168 1 10 11000000 10101000 00000001 00001010 11111111 11111111 11111111 00000000 Network part: 24 bits (192.168.1) Host part: 8 bits
The mask has ones under the network bits and zeros under the host bits. 192.168.1.10 with mask 255.255.255.0 is host 10 on network 192.168.1.0.

Prefix notation and CIDR

Because a mask is always a run of ones followed by zeros, it is enough to say how many ones there are. That number is the prefix length, written after a slash: 192.168.1.10/24 means "mask of 24 ones", which is 255.255.255.0. This notation comes from CIDR (Classless Inter-Domain Routing, RFC 1519 in 1993, now RFC 4632): the system that lets the boundary between network and host lie at any bit, instead of only at the fixed class boundaries described below.

import ipaddress

interface = ipaddress.IPv4Interface("192.168.1.10/24")
print(interface.ip)
print(interface.network)
print(interface.netmask)
print(interface.with_netmask)
print(f"{int(interface.netmask):032b}")

for prefix in (8, 16, 24, 26, 30):
    net = ipaddress.IPv4Network(f"0.0.0.0/{prefix}")
    print(f"/{prefix:<2} = {net.netmask}")
192.168.1.10
192.168.1.0/24
255.255.255.0
192.168.1.10/255.255.255.0
11111111111111111111111100000000
/8  = 255.0.0.0
/16 = 255.255.0.0
/24 = 255.255.255.0
/26 = 255.255.255.192
/30 = 255.255.255.252

An IPv4Interface is an address together with its prefix, as configured on a network card. From it Python derives the network the host belongs to (192.168.1.0/24) and the mask. The loop shows common prefix lengths and their masks. With 8 host bits, a /24 has 28 = 256 addresses, of which 254 can be given to hosts: the all-zeros host part is the network address and the all-ones host part is the broadcast address. Calculating these values for any prefix is the subject of Subnetting.

Classful addressing (history)

Before CIDR, the first bits of an address fixed where the network part ended. You may still see these classes in older documentation, and exams may ask you to recognize them by the first octet:

Class First octet Default mask Purpose
A 1–126 /8 (255.0.0.0) Very large networks (127 is loopback)
B 128–191 /16 (255.255.0.0) Medium networks
C 192–223 /24 (255.255.255.0) Small networks
D 224–239 none Multicast
E 240–255 none Reserved (experimental)

The classes were abandoned because they wasted addresses and made routing tables explode. An organization with 2,000 hosts was too big for a class C (254 hosts) and received a class B with 65,534 host addresses, most of which stayed unused. With CIDR, any prefix length is allowed, so that organization gets a /21 (2,046 hosts), and providers can summarize many customer networks into one route. The words live on only as nicknames: people still say "a class C" when they mean a /24.

Private addresses

A private IP address is an address from one of three ranges that RFC 1918 reserved in 1996 for use inside organizations. Anyone may use them without asking a registry, and the same ranges are reused in millions of networks. Internet routers do not route them, so a private address only has meaning inside its own network. To reach the internet, a router or firewall at the edge translates private addresses to a public one with NAT.

They exist because there are not enough public IPv4 addresses for every device. Your laptop at home, your phone and the office printer all have private addresses; only the edge of the network has a public one.

import ipaddress

RFC1918 = [
    ipaddress.ip_network("10.0.0.0/8"),
    ipaddress.ip_network("172.16.0.0/12"),
    ipaddress.ip_network("192.168.0.0/16"),
]

for net in RFC1918:
    print(f"{str(net):<15} {net[0]} - {net[-1]}  ({net.num_addresses:,} addresses)")

print()
for text in ["10.20.30.40", "172.31.255.254", "172.32.0.1", "192.168.1.10", "203.0.113.7"]:
    address = ipaddress.ip_address(text)
    private = any(address in net for net in RFC1918)
    print(f"{text:<15} private: {private}")
10.0.0.0/8      10.0.0.0 - 10.255.255.255  (16,777,216 addresses)
172.16.0.0/12   172.16.0.0 - 172.31.255.255  (1,048,576 addresses)
192.168.0.0/16  192.168.0.0 - 192.168.255.255  (65,536 addresses)

10.20.30.40     private: True
172.31.255.254  private: True
172.32.0.1      private: False
192.168.1.10    private: True
203.0.113.7     private: False

Special addresses

Several other ranges have a fixed meaning. The ones you will meet in practice:

Range Name What it is for
0.0.0.0 Unspecified "No address yet", as the source of a Dynamic Host Configuration Protocol (DHCP) request, or "all local addresses" when a server listens; 0.0.0.0/0 is the default route
127.0.0.0/8 Loopback The host itself; never leaves the machine
169.254.0.0/16 Link-local (APIPA, Automatic Private IP Addressing) Self-assigned when no DHCP server answers
100.64.0.0/10 Shared address space Between a provider's carrier-grade NAT (CGNAT) and its customers (RFC 6598)
192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 Documentation For examples in books and manuals (RFC 5737); never used on real networks
224.0.0.0/4 Multicast Group addresses (the old class D)
240.0.0.0/4 Reserved The old class E; not usable
255.255.255.255 Limited broadcast All hosts on the local network; never routed

Loopback

A loopback address is an address in 127.0.0.0/8, most often 127.0.0.1, that refers to the host itself. Traffic to it never reaches a network card; the operating system hands it straight back. It lets programs on one machine talk to each other over IP (a web app to its local database, for example), and ping 127.0.0.1 tests the host's own IP stack. The name localhost points to it. Routers have a different "loopback": a virtual interface, such as interface Loopback0, with a normal address that stays up as long as the router does, used as a stable management address.

APIPA

APIPA (Automatic Private IP Addressing) is the mechanism by which a host that gets no answer from a DHCP server gives itself an address from 169.254.0.0/16 (strictly 169.254.1.0 to 169.254.254.255, RFC 3927), after checking with the Address Resolution Protocol (ARP) that no other host uses it. The name comes from Microsoft; the standard calls these IPv4 link-local addresses. They only work between hosts on the same link and have no gateway, so in practice a 169.254.x.x address on a user's PC is a symptom: "DHCP did not work". Check the cable, the VLAN of the switch port and the DHCP server or relay.

A small classifier shows the special ranges side by side. It checks a list of networks in order, so the /32 for the limited broadcast comes before the reserved /4 that contains it:

import ipaddress

SPECIAL = {
    "255.255.255.255/32": "limited broadcast",
    "0.0.0.0/8": "this network",
    "10.0.0.0/8": "private (RFC 1918)",
    "100.64.0.0/10": "shared address space (CGNAT)",
    "127.0.0.0/8": "loopback",
    "169.254.0.0/16": "link-local (APIPA)",
    "172.16.0.0/12": "private (RFC 1918)",
    "192.0.2.0/24": "documentation",
    "192.168.0.0/16": "private (RFC 1918)",
    "198.51.100.0/24": "documentation",
    "203.0.113.0/24": "documentation",
    "224.0.0.0/4": "multicast",
    "240.0.0.0/4": "reserved",
}


def classify(text):
    address = ipaddress.ip_address(text)
    for network, kind in SPECIAL.items():
        if address in ipaddress.ip_network(network):
            return kind
    return "public unicast"


for text in ["127.0.0.1", "169.254.12.34", "100.72.1.9", "224.0.0.5",
             "255.255.255.255", "172.20.1.1", "198.51.100.20"]:
    print(f"{text:<16} {classify(text)}")
127.0.0.1        loopback
169.254.12.34    link-local (APIPA)
100.72.1.9       shared address space (CGNAT)
224.0.0.5        multicast
255.255.255.255  limited broadcast
172.20.1.1       private (RFC 1918)
198.51.100.20    documentation

Try it: IPv4 calculator

Enter an address with its prefix length or mask to see its network and broadcast address, the usable range, the number of hosts, its historical class and whether it is private, public or special.

For example 192.168.10.25/24 or 192.168.10.25 255.255.255.0.

Unicast, broadcast and multicast

An IPv4 packet can be addressed to one, all or some hosts:

  • Unicast: one sender, one receiver. Almost all traffic, such as web browsing or a file copy, is unicast.
  • Broadcast: to every host on a network. The limited broadcast 255.255.255.255 reaches all hosts on the local network, for example a DHCP discover from a host that has no address yet. A directed broadcast is the last address of a subnet, such as 192.168.1.255 for 192.168.1.0/24. Routers never forward limited broadcasts, and by default do not forward directed broadcasts either, because they were abused for attacks.
  • Multicast: to a group of hosts that asked to receive it, using an address from 224.0.0.0/4. Routing protocols such as Open Shortest Path First (OSPF) use it (OSPF talks to 224.0.0.5), and so do video streaming and some service discovery protocols.

IPv4 has no separate anycast address type; IPv6 replaces broadcast with multicast altogether.

The default gateway

A host can only deliver a packet directly to a destination on its own subnet: it looks up the destination's MAC address with ARP and sends the frame. For anything else it needs a router. The default gateway is the address of the router on the host's own subnet to which the host sends every packet whose destination is not on that subnet. It is usually the first or last usable address of the subnet, such as 192.168.1.1.

PC1 (192.168.1.10) and PC2 (192.168.1.25) connect to switch SW1 in subnet 192.168.1.0/24. SW1 connects to router R1, whose interface 192.168.1.1 is the default gateway. R1 connects to the internet, where a server with address 203.0.113.80 is. Subnet 192.168.1.0/24 SW1 R1 192.168.1.1 default gateway PC1 192.168.1.10 PC2 192.168.1.25 Internet Server 203.0.113.80
PC1 reaches PC2 directly through the switch. To reach the server it sends the packet to its default gateway, R1.

Local or remote: how a host decides

Before sending, the host applies its own subnet mask to the destination address with a bitwise AND, which keeps the network bits and sets the host bits to zero. If the result equals its own network address, the destination is local. Otherwise it is remote, and the packet goes to the gateway: the host uses ARP to find the gateway's MAC address, and sends the frame there with the final destination still in the IP header.

import ipaddress

host = ipaddress.IPv4Interface("192.168.1.10/24")
gateway = ipaddress.IPv4Address("192.168.1.1")
mask = int(host.netmask)

for text in ["192.168.1.25", "192.168.2.25", "203.0.113.80"]:
    destination = ipaddress.IPv4Address(text)
    network = ipaddress.IPv4Address(int(destination) & mask)
    print(f"{destination} AND {host.netmask} = {network}")
    if network == host.network.network_address:
        print(f"  local: send directly to {destination}")
    else:
        print(f"  remote: send to the default gateway {gateway}")
192.168.1.25 AND 255.255.255.0 = 192.168.1.0
  local: send directly to 192.168.1.25
192.168.2.25 AND 255.255.255.0 = 192.168.2.0
  remote: send to the default gateway 192.168.1.1
203.0.113.80 AND 255.255.255.0 = 203.0.113.0
  remote: send to the default gateway 192.168.1.1

Note that 192.168.2.25 is remote even though it is also a private address in the same building: what counts is the subnet, not whether the address "looks close". In Python you can write the same test shorter as destination in host.network.

Try it: network address with bitwise AND

Enter an address and a mask to see the AND bit by bit, and the broadcast address that OR with the inverted mask gives.

For example 192.0.2.130.

Dotted decimal, for example 255.255.255.192.

How a host gets its address

A host can get its IPv4 settings in two ways:

  • Static: an administrator types the address, mask, gateway and Domain Name System (DNS) servers into the device. Used for devices that others must find at a fixed address: routers, switches, servers, printers.
  • Dynamic: the host asks a DHCP server, which leases it an address with all the other settings. Used for almost all clients. See DHCP.

Checking the address

On Linux, the ip command from iproute2 shows the address and the default route:

ip -4 addr show dev eth0
ip route show default
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.1.10/24 brd 192.168.1.255 scope global dynamic noprefixroute eth0
       valid_lft 85833sec preferred_lft 85833sec
default via 192.168.1.1 dev eth0 proto dhcp src 192.168.1.10 metric 100

inet 192.168.1.10/24 is the address with its prefix, brd the broadcast address, and dynamic with a valid_lft means it came from DHCP with a lease. The default route, default via 192.168.1.1, is the default gateway. On Windows, ipconfig shows the same (ipconfig /all adds the MAC address, DHCP server and DNS servers):

ipconfig
Windows IP Configuration


Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . : example.com
   Link-local IPv6 Address . . . . . : fe80::1c4a:7e2f:9b3d:2a61%12
   IPv4 Address. . . . . . . . . . . : 192.168.1.20
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1

On a Cisco router, addresses are configured statically per interface, and one command gives an overview of all interfaces:

R1(config)# interface GigabitEthernet0/0
R1(config-if)# ip address 192.168.1.1 255.255.255.0
R1(config-if)# no shutdown
R1(config-if)# end
R1# show ip interface brief
Interface              IP-Address      OK? Method Status                Protocol
GigabitEthernet0/0     192.168.1.1     YES manual up                    up
GigabitEthernet0/1     203.0.113.2     YES manual up                    up
GigabitEthernet0/2     unassigned      YES unset  administratively down down

ip address takes the address and a dotted-decimal mask; no shutdown enables the interface, because router interfaces are shut down by default. In show ip interface brief, Status is layer 1 (is there a link?) and Protocol is layer 2 (does the data link work?). administratively down means someone, or the default configuration, shut the interface down. This is often the first command run when a ticket reports a site as unreachable.