subnet

package
v0.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2026 License: CC0-1.0 Imports: 7 Imported by: 0

Documentation

Overview

Package subnet provides utilities for working with IP subnets, including well-known CIDR ranges, IP address arithmetic, and network manipulation. It supports both IPv4 and IPv6 operations such as splitting, extending, narrowing, and enumerating subnets.

Index

Constants

This section is empty.

Variables

View Source
var (
	CIDRLocal          = MustCIDR("127.0.0.0/8")
	CIDRCommonDefault1 = MustCIDR("192.168.1.0/24")
	CIDRCommonDefault2 = MustCIDR("192.168.0.0/24")
	CIDRCommonDefault3 = MustCIDR("192.168.2.0/24")
	CIDRFritzBox1      = MustCIDR("192.168.178.0/24")
	CIDRFritzBox2      = MustCIDR("192.168.188.0/24")
	CIDRTpLink1        = MustCIDR("192.168.68.0/24")
	CIDRTpLink2        = MustCIDR("192.168.50.0/24")
	CIDRHuawei1        = MustCIDR("192.168.100.0/24")
	CIDRHuawei2        = MustCIDR("192.168.3.0/24")
	CIDRHuawei3        = MustCIDR("192.168.8.0/24")
	CIDRZyxel1         = MustCIDR("192.168.4.0/24")
	CIDRZyxel2         = MustCIDR("192.168.10.0/24")
	CIDRGoogleWifi     = MustCIDR("192.168.86.0/24")
	CIDRMotorola       = MustCIDR("192.168.10.0/24")

	// From Yggdrasil doc:
	//
	//   Yggdrasil uses the 200::/7 region of the IPv6 network space.
	//   This region was set aside for NSAP-mapped IPv6 addresses in RFC1888,
	//   which was (AFAIK) never used and eventually deprecated in RFC4048
	//   (with further explanation in RFC4548).
	CIDRYggdrasilNetwork = MustCIDR("200::/7")

	// CJDNS use [ULA] address space.
	//
	// [ULA]: https://en.wikipedia.org/wiki/Unique_local_address
	CIDRHyperboria = MustCIDR("FC00::/8")

	CIDRMycelium = MustCIDR("400::/7")
)

Some well known CIDRs. May overlap. Most info is from here. TODO: Add more well known subnets.

Functions

func Capacity

func Capacity(network *net.IPNet) big.Int

Capacity returns the total number of IP addresses in the network, including the network address and broadcast address.

func Contains

func Contains(parent, child *net.IPNet) bool

Contains reports whether child is a subnet of parent (or equal to parent). It checks that child's network is entirely contained within parent's network.

func Extend

func Extend(network *net.IPNet, bits int, num *big.Int) (net.IPNet, error)

Extend creates a supernet of the given network by reducing the prefix length by the specified number of bits. The num parameter selects which supernet to return (0 for the one containing the original network, 1 for the next, etc.). For example, Extend(192.168.1.0/24, 1, 0) returns 192.168.0.0/23, and Extend(192.168.1.0/24, 1, 1) returns 192.168.2.0/23. Returns an error if bits is negative, num is negative, or the resulting prefix length would be less than 0.

func FromRange

func FromRange(first, last net.IP) (net.IPNet, error)

FromRange constructs a network from its first and last IP addresses. Returns an error if the range doesn't represent a valid CIDR block (i.e., if the range isn't aligned to a power-of-2 boundary).

func IPIndex

func IPIndex(network *net.IPNet, i *big.Int) (net.IP, error)

IPIndex returns the IP address at the given index within the network. Index 0 corresponds to the network address, and the maximum valid index is 2^(host_bits) - 1, where host_bits = total_bits - prefix_length. Returns an error if the index is negative or out of range.

func MustCIDR

func MustCIDR(s string) net.IPNet

func Narrow

func Narrow(network *net.IPNet, bits int, num *big.Int) (net.IPNet, error)

Narrow creates a subnet of the given network by increasing the prefix length by the specified number of bits. The num parameter selects which subnet to return (0 for the first subnet, 1 for the second, etc.). For example, Narrow(192.168.1.0/24, 1, 0) returns 192.168.1.0/25, and Narrow(192.168.1.0/24, 1, 1) returns 192.168.1.128/25. Returns an error if bits is negative, num is negative, the resulting prefix length would exceed the maximum (32 for IPv4, 128 for IPv6), or num is out of range for the specified bits.

func Next

func Next(ip net.IP) net.IP

Next returns the next IP address after ip, wrapping around to all zeros if ip is the maximum address (all 0xFF bytes).

func Overlap

func Overlap(nets []*net.IPNet) bool

Overlap reports whether any of the provided networks overlap with each other. Returns false for empty list or single network.

func Prev

func Prev(ip net.IP) net.IP

Prev returns the previous IP address before ip, wrapping around to all 0xFF bytes if ip is the minimum address (all zeros).

func Range

func Range(network *net.IPNet) (net.IP, net.IP)

Range returns the first (network) and last (broadcast) IP addresses in the network.

func Split

func Split(network *net.IPNet) (*net.IPNet, *net.IPNet, error)

Split divides a network into two equal halves by incrementing the prefix length by one. Returns an error if the network cannot be split further (e.g., /32 for IPv4 or /128 for IPv6).

func Subnets

func Subnets(network *net.IPNet, prefix *big.Int) ([]*net.IPNet, error)

Subnets returns all subnets of the given network with the specified prefix length. The prefix must be greater than or equal to the network's current prefix length and less than or equal to the maximum (32 for IPv4, 128 for IPv6). Returns an error if the prefix is invalid.

Types

type IPAllocator

type IPAllocator interface {
	// Reserve marks an IP as reserved.
	Reserve(ip net.IP)

	// Alloc returns a free IPv4 addr and marks it as reserved.
	// It returns nil if there is no free IPv4 addrs available in this allocator.
	Alloc4() net.IP

	// Alloc returns a free IPv6 addr and marks it as reserved.
	// It returns nil if there is no free IPv6 addrs available in this allocator.
	Alloc6() net.IP

	// Free removes the reserved mark from an IP. If the IP was not reserved,
	// this is a no-op.
	Free(ip net.IP)

	// FreeAll removes all reserved marks, making all previously allocated IPs
	// available again.
	FreeAll()
}

All methods of IPAllocator should be thread-safe.

func NewIPAllocator

func NewIPAllocator(subnet4, subnet6 *net.IPNet) IPAllocator

NewIPAllocator creates a new IPAllocator with optional IPv4 and IPv6 subnets. Either or both subnets can be nil.

func NewRandomIPAllocator

func NewRandomIPAllocator(config *RandomIPAllocatorConfig) IPAllocator

NewRandomIPAllocator creates a new IPAllocator that uses two SubnetAllocators to dynamically allocate subnets on demand. When existing subnets are full, new subnets are allocated from the underlying SubnetAllocators. Config is optional; pass nil for default behavior.

type RandomAllocatorConfig

type RandomAllocatorConfig struct {
	// Filter is an optional callback to validate randomly generated subnets.
	// If Filter returns false, the subnet is rejected and another random
	// subnet will be tried. This is useful for avoiding subnets already
	// in use by the system.
	Filter func(*net.IPNet) bool
}

RandomAllocatorConfig holds configuration for NewRandomAllocator.

type RandomIPAllocatorConfig

type RandomIPAllocatorConfig struct {
	// IPv4Config is optional configuration for the IPv4 SubnetAllocator.
	// If nil, a default random allocator is used.
	IPv4Config *RandomAllocatorConfig
	// IPv6Config is optional configuration for the IPv6 SubnetAllocator.
	// If nil, a default random allocator is used.
	IPv6Config *RandomAllocatorConfig
}

RandomIPAllocatorConfig holds configuration for NewRandomIPAllocator.

type SubnetAllocator

type SubnetAllocator interface {
	// Prefixes returns a list of unique prefix lengths supported by this allocator.
	Prefixes() []int

	// Reserve marks a subnet as reserved. If the subnet is not within any of the
	// available subnets, the call is silently ignored.
	Reserve(subnet *net.IPNet)

	// Alloc returns a free subnet with the provided prefix length and marks it as reserved.
	// It returns nil if:
	//   - The prefix length is not supported (not present in available subnets).
	//   - All subnets with that prefix length are already reserved.
	Alloc(prefix int) *net.IPNet

	// Free removes the reserved mark from a subnet. If the subnet was not reserved,
	// this is a no-op.
	Free(subnet *net.IPNet)

	// FreeAll removes all reserved marks, making all previously allocated subnets
	// available again.
	FreeAll()
}

SubnetAllocator manages allocation of IP subnets in thread-safe way to track which subnets are in use.

func NewAllocator

func NewAllocator(available []*net.IPNet) SubnetAllocator

NewAllocator creates a new SubnetAllocator with the provided available subnets. The allocator will only support prefix lengths that are present in the available subnets. The available slice is copied internally; modifications to the original slice after creation have no effect on the allocator.

func NewRandomAllocator

func NewRandomAllocator(config *RandomAllocatorConfig) SubnetAllocator

NewRandomAllocator creates a SubnetAllocator that randomly allocates /24 subnets within 10.0.0.0/8, avoiding 0-24 values for second and third octets. The config parameter is optional; pass nil for default behavior.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL