Skip to content

aharwelik/subnet-sanity

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

subnet-sanity banner

subnet-sanity

Offline validator for IP addressing plans that catches the class of mistakes LLMs make when generating network configurations.

Keywords: subnet calculator, VLSM, IP address management, IPAM, network automation, CIDR, overlap detection, Cisco, network engineer, LLM network config validation


Problem

Large language models generate network configurations with a predictable class of errors:

  • Host bits set in a network address (10.0.0.5/24 instead of 10.0.0.0/24)
  • Overlapping subnets silently allocated to different VLANs
  • Gateways outside the subnet or equal to the network/broadcast address
  • Prefix lengths too small to fit the required host count
  • Duplicate allocation names that silently stomp each other in downstream tooling

These errors are individually trivial but collectively cause misrouted traffic, failed switch provisioning, and hours of debug time. subnet-sanity catches all of them before a config reaches a device.


Install

No dependencies. Python 3.10 or later, standard library only.

git clone https://github.com/aharwelik/subnet-sanity
cd subnet-sanity

Run directly from the repo root:

python3 -m subnetsanity --help

Usage

Check a plan

python3 -m subnetsanity check examples/plan.bad.json

Sample output:

----------------------------------------------------------------------
subnet-sanity report: examples/plan.bad.json
----------------------------------------------------------------------

ERRORS (6)
----------------------------------------
  HOST_BITS_SET  [core]
    Host bits are set in '10.0.0.5/24'. Did you mean network address 10.0.0.0/24?
  GATEWAY_OUTSIDE_SUBNET  [servers]
    Gateway 10.0.0.254 is not contained in subnet 10.0.0.0/25.
  GATEWAY_OUTSIDE_SUBNET  [tiny]
    Gateway 192.168.99.1 is not contained in subnet 10.0.1.0/29.
  INSUFFICIENT_CAPACITY  [tiny]
    Subnet 10.0.1.0/29 provides 6 usable hosts, but 10 are required.
    Use /28 which provides 14 usable hosts.
  DUPLICATE_NAME  [core]
    Allocation name 'core' appears 2 times.
  OVERLAPPING_SUBNETS
    Allocations 'core' (10.0.0.0/24) and 'servers' (10.0.0.0/25) overlap.

----------------------------------------------------------------------
Summary: 6 error(s), 4 info(s)
----------------------------------------------------------------------

Exit code is 1 when any error-level finding exists, 0 for a clean plan.

Machine-readable output

python3 -m subnetsanity check examples/plan.bad.json --json

Emits a JSON object with a findings array, each element containing severity, code, message, allocation (when applicable), and detail (structured data for programmatic use).

VLSM carve

python3 -m subnetsanity carve 10.0.0.0/16 24

Sample output:

----------------------------------------------------------------------
subnet-sanity carve: 10.0.0.0/16 -> /24
----------------------------------------------------------------------
Produced 256 subnet(s):
     1.  10.0.0.0/24
     2.  10.0.1.0/24
     ...
   256.  10.0.255.0/24
----------------------------------------------------------------------

Carved subnets are validated using the same checks as check, so any structural problem in the resulting blocks surfaces immediately.

Plan format

{
  "allocations": [
    {
      "name": "core",
      "cidr": "10.0.0.0/24",
      "gateway": "10.0.0.1",
      "required_hosts": 200,
      "vlan": 10
    }
  ]
}

Fields gateway, required_hosts, and vlan are optional.


Checks

Code Severity Description
INVALID_CIDR error CIDR is not parseable
HOST_BITS_SET error Host bits set; corrected network reported
OVERLAPPING_SUBNETS error Two allocations share address space
GATEWAY_OUTSIDE_SUBNET error Gateway not contained in its subnet
GATEWAY_IS_NETWORK_ADDRESS error Gateway equals the network address
GATEWAY_IS_BROADCAST_ADDRESS error Gateway equals the broadcast address
DUPLICATE_NAME error Allocation name used more than once
INSUFFICIENT_CAPACITY error Prefix too small for required_hosts; smallest valid prefix suggested
CLASSIFICATION info RFC1918 private vs public vs reserved

Theory

This tool implements the Identity Normalization invariant from the proof-carrying-ops model.

The canonical identity of a network allocation is its network address and prefix length -- not the address a user typed. Any comparison, overlap check, or containment test is only sound after both operands have been normalized to this canonical form. When an LLM writes 10.0.0.5/24, the host bits in the address encode no routing information; they are noise that causes two logically identical allocations to appear distinct to a naive string-equality check, and causes an overlap detector that compares only the first address to miss real conflicts.

subnet-sanity normalizes every input CIDR through ipaddress.IPv4Network(cidr, strict=False) before any comparison, then separately flags the pre-normalization form as a HOST_BITS_SET error so the source config can be corrected. This normalize-then-validate pattern mirrors the proof obligation in the broader proof-carrying-ops framework: a claim about an allocation is only well-formed when identities are canonical.

See the full proof-carrying-ops model at: https://github.com/aharwelik/proof-carrying-ops


License

MIT. See LICENSE.


Anthony Harwelik -- aharwelik@gmail.com -- https://github.com/aharwelik

About

Offline validator for IP addressing plans. Catches the wrong-mask, overlap, host-bits-set, and gateway-out-of-range errors LLMs make in network configs, plus VLSM carving. Stdlib only (ipaddress). Part of the proof-carrying-ops suite.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages