DEV Community

William Baptist
William Baptist

Posted on

Checking Whether Two IPv4 Subnets Overlap in Python

Two subnet labels may describe some of the same addresses. Before treating them as separate ranges, compare them. This small command-line program reports overlap, equality and containment without contacting either network.

This runs on Python 3.10 or later from any command window. Only the standard library is used.

1. Choose practice ranges

An IPv4 address has four dot-separated numbers, such as 192.0.2.10. A subnet describes a range of these addresses. CIDR notation puts a slash and prefix length after the network address: 192.0.2.0/24.

A prefix fixes the first part of the address. A larger prefix length describes a smaller range. 192.0.2.128/25 is the upper half of 192.0.2.0/24. These example addresses come from a documentation range; the checker never sends packets.

Use these two pairs:

192.0.2.0/24     192.0.2.128/25
192.0.2.0/25    192.0.2.128/25
Enter fullscreen mode Exit fullscreen mode

The first pair shares addresses. The second pair is adjacent without sharing any.

2. Save the checker

Save this as CheckOverlap.py in a practice folder:

import ipaddress as IpAddress
import json as Json
import sys as Sys


def CheckOverlap(FirstText, SecondText):
    First = IpAddress.IPv4Network(FirstText, strict=True)
    Second = IpAddress.IPv4Network(SecondText, strict=True)
    return {"First": str(First), "Second": str(Second),
            "Overlap": First.overlaps(Second), "Equal": First == Second,
            "FirstInsideSecond": First.subnet_of(Second),
            "SecondInsideFirst": Second.subnet_of(First)}


def Main():
    if len(Sys.argv) != 3:
        print("Usage: python3 CheckOverlap.py FIRST_CIDR SECOND_CIDR", file=Sys.stderr)
        return 2
    try:
        Report = CheckOverlap(Sys.argv[1], Sys.argv[2])
    except ValueError as Problem:
        print(f"Check stopped: {Problem}", file=Sys.stderr)
        return 2
    print(Json.dumps(Report, indent=2))
    return 1 if Report["Overlap"] else 0


if __name__ == "__main__":
    Sys.exit(Main())
Enter fullscreen mode Exit fullscreen mode

IPv4Network parses IPv4 network descriptions. The examples use slash-prefix notation. The library also accepts some other forms, including IPv4 masks; this program does not implement its own format validator. IPv6 is outside this check.

Host bits are the part of an address that identifies an individual address within a subnet. strict=True rejects an address with host bits set for the chosen prefix. For example, 192.0.2.1/24 stops instead of silently turning into 192.0.2.0/24. Use the intended network address; do not remove the strict check merely to make a questionable entry pass.

3. Separate overlap, equality and containment

overlaps asks whether the ranges share any addresses. subnet_of includes equality: two identical networks are each a subnet of the other. The separate Equal field makes that case visible.

FirstInsideSecond and SecondInsideFirst depend on argument order. Overlap and equality do not. The comparison uses address-range arithmetic, not a list of every address, so a broad range does not require probing or expanding all its hosts.

The report includes network and broadcast addresses when comparing ranges. It does not count usable hosts or reserve particular addresses for a deployment.

4. Check a contained subnet

Open a command window in the folder and run:

python3 CheckOverlap.py 192.0.2.0/24 192.0.2.128/25
Enter fullscreen mode Exit fullscreen mode

Use your installation's Python 3 command if it is not named python3. The output is:

{
  "First": "192.0.2.0/24",
  "Second": "192.0.2.128/25",
  "Overlap": true,
  "Equal": false,
  "FirstInsideSecond": false,
  "SecondInsideFirst": true
}
Enter fullscreen mode Exit fullscreen mode

JSON is a text format for named values. The ranges overlap, but are not equal. The second is inside the first; the first is not inside the second. Reverse the command's arguments and the two containment fields swap.

python3 CheckOverlap.py 192.0.2.128/25 192.0.2.0/24
Enter fullscreen mode Exit fullscreen mode
{
  "First": "192.0.2.128/25",
  "Second": "192.0.2.0/24",
  "Overlap": true,
  "Equal": false,
  "FirstInsideSecond": true,
  "SecondInsideFirst": false
}
Enter fullscreen mode Exit fullscreen mode

The exit code is 1 for overlap, 0 for disjoint ranges and 2 for a usage or input error. Overlap is a review signal here, not automatically a configuration fault: nested ranges can be intentional.

5. Check adjacent and equal ranges

Run:

python3 CheckOverlap.py 192.0.2.0/25 192.0.2.128/25
Enter fullscreen mode Exit fullscreen mode

The output is:

{
  "First": "192.0.2.0/25",
  "Second": "192.0.2.128/25",
  "Overlap": false,
  "Equal": false,
  "FirstInsideSecond": false,
  "SecondInsideFirst": false
}
Enter fullscreen mode Exit fullscreen mode

The ranges touch at a boundary but share no address, so the exit code is 0. The first ends at 192.0.2.127, and the second begins at 192.0.2.128.

Now compare 192.0.2.0/24 with itself.

python3 CheckOverlap.py 192.0.2.0/24 192.0.2.0/24
Enter fullscreen mode Exit fullscreen mode
{
  "First": "192.0.2.0/24",
  "Second": "192.0.2.0/24",
  "Overlap": true,
  "Equal": true,
  "FirstInsideSecond": true,
  "SecondInsideFirst": true
}
Enter fullscreen mode Exit fullscreen mode

Overlap, Equal and both containment fields are true; the exit code is 1. A /32 describes one address and can also overlap a larger range containing it. A /0 covers all IPv4 addresses.

This check does not inspect interfaces, routing tables, firewall rules, address allocation or reachability. A successful comparison cannot prove that a network plan is safe or that a connection will work.

Keep the intended configuration unchanged while reviewing the result. If a range overlaps, check why it is present and which system owns the allocation before changing anything. Reports include network labels, so keep them private when they describe work or personal infrastructure.

References

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.