TT Lab
Get started
Learn Learning paths Courses

Addresses, Subnets and Gateways

Build a Tool That Computes Addresses

Continue in TT Lab

Goal

Build a Python tool that takes an address and a mask and computes the network address, the broadcast address, the usable range and the number of hosts. Then use it to decide whether two addresses are in the same subnet, to classify ranges, and to check for overlaps. At the end, pick the prefix that fits the required number of hosts and leave a design note.

Why it matters

Firewall rules, network policies and VPC design all stand on top of this calculation. But if you keep doing it by hand, you will eventually get it wrong, and the mistake usually shows up only after an outage. It is better to build a tool once and keep using it.

/31 and /32 are especially important. If you code the host count as just "subtract 2 from the total," these two produce 0 and -1, and the tool returns those values without any error. It is the kind of lie a checker will not catch, and only someone who knows the exceptions can avoid it.

Steps

  1. Work out three ranges by hand and write them to /root/cidr/01-hand.txt, one per line. The ranges are 192.168.40.130/26, 10.10.6.75/20 and 172.20.200.9/23, and each line must contain the CIDR, network address, broadcast address, first host, last host and number of hosts.
  2. Create /root/cidr/subnet.py. python3 subnet.py 203.0.113.77/28 and python3 subnet.py 203.0.113.77 255.255.255.240 must give the same answer, and the output is six lines: prefix= network= broadcast= first= last= hosts=. Save the results of both runs to /root/cidr/02-tool.txt.
  3. Fix the tool so that it handles /31 and /32 correctly. For both, broadcast=none; for /31 both addresses are hosts (hosts=2), and for /32 the single address is the host itself (hosts=1). Write the results of running 10.0.0.5/31 and 10.0.0.5/32, and the reason for them, to /root/cidr/03-edge.txt.
  4. Create /root/cidr/same.py. python3 same.py <주소/프리픽스> <상대주소> (address/prefix, then the other address) prints a single word, same or different. Run five pairs and save them to /root/cidr/04-same.txt in the form 주소/프리픽스 상대주소 판정 (address/prefix, other address, verdict).
  5. Create /root/cidr/classify.py. python3 classify.py <주소> (address) prints one of private link-local loopback cgnat multicast public. Run nine addresses and save them to /root/cidr/05-class.txt in the form 주소 분류 (address, classification).
  6. Split 10.60.8.0/22 into four /24 ranges and write them to /root/cidr/06-split.txt, one per line, in the form 네트워크/24 first= last= hosts= (network/24, then the first host, last host and number of hosts).
  7. Decide whether each candidate overlaps the four existing ranges and write the result to /root/cidr/07-overlap.txt. If it overlaps, write 후보 overlap=겹치는대역 (candidate, then the overlapping range); if not, write 후보 free (candidate, then free).
  8. Write a design note in /root/cidr/08-report.md. It must include the smallest prefix that fits each of the three required host counts (120, 600 and 30 hosts), what you gain by laying ranges out contiguously, and when to use /31 and /32.

Notes

Calculate three ranges by hand

Mistakes happen when the prefix is not a multiple of 8. Work out the block size (2 to the power of the number of host bits), then find the multiple of it that contains the address; that is the network address.

For example, for /26 the block size is 64, so the boundaries are 0, 64, 128 and 192. 130 falls in the 128 block.

Check your work with python3 -c "import ipaddress; n=ipaddress.ip_network('192.168.40.130/26', strict=False); print(n.network_address, n.broadcast_address, n.num_addresses-2)".

Build the calculation tool

/26 and 255.255.255.192 mean the same thing. When two arguments come in, join them as 주소/마스크 (address/mask) and pass the result to the same function.

For example, ipaddress.ip_network("203.0.113.77 255.255.255.240".replace(' ', '/'), strict=False).

The grader looks for the output keys (prefix= network= broadcast= first= last= hosts=) exactly as written, so do not change them. The number of hosts is the total number of addresses minus the network address and the broadcast address.

Handle the /31 and /32 exceptions

num_addresses - 2 becomes 0 for /31 and -1 for /32. The tool returns those values without any error, so only someone who knows the exceptions can avoid them.

If the prefix is 31 or more, send it down a different branch. On that branch there is no broadcast address (broadcast=none), the first host is the network address itself, the last host is the last address of the range, and the number of hosts is the total number of addresses.

In the explanation file, write which RFC allows this and on which kind of link.

Decide whether two addresses are in the same subnet

The check fits on one line — is the other address inside my range? Use ipaddress.ip_address(other) in ipaddress.ip_network(mine, strict=False).

In the first two pairs the addresses are the same and only the mask differs. Here you can see how one wrong mask turns the computer next to you into one on the other side of the planet.

The output must be a single word, same or different. The grader asks again with pairs that are not in the instructions.

Classify the nature of each range

Build a list of rules, look for the first match from the top, and if nothing matches, the answer is public.

These are the ranges you need — loopback 127.0.0.0/8, link-local 169.254.0.0/16, CGNAT 100.64.0.0/10, multicast 224.0.0.0/4, and private 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.

172.32.0.1 and 100.100.5.5 are the traps. The 172 private range is a /12, so it runs from 172.16 through 172.31, and 100.64.0.0/10 is handed out by carriers to subscribers, so it is neither private nor public.

Split a range into smaller ones

Cutting a /22 into /24 ranges gives 2 to the power of (24-22), that is, four. ipaddress.ip_network("10.60.8.0/22").subnets(new_prefix=24) hands you the four in order.

On each line, put the network (with its prefix), the first host, the last host and the number of hosts. Each piece has 254 hosts.

Check whether ranges overlap

If you judge overlap by eye, you will get it wrong. The ipaddress module's overlaps() method tells you whether two ranges share even a single address.

There is a reason 172.17.0.0/16 is in the list. Docker's default bridge uses that range, so if the internal network uses 172.17, containers cannot reach internal servers.

If a candidate overlaps, write 후보 overlap=겹치는대역 (candidate, then the overlapping range); if not, write 후보 free (candidate, then free).

Leave a design note

Find the smallest power of 2 that holds the required number of hosts plus 2. For 120 hosts you need at least 122, so 128, which means 7 host bits and a prefix of /25.

The point about contiguous layout is that adjacent ranges can be advertised as one merged range. That is also the real reason classes disappeared.

It is also good to note that in the cloud you have to subtract additional reserved addresses.