118 lines
5.5 KiB
Go
118 lines
5.5 KiB
Go
package netsplit
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"net"
|
|
"net/netip"
|
|
|
|
"go4.org/netipx"
|
|
)
|
|
|
|
// SplitErr is used to wrap an error with context surrounding when/how that error was encountered.
|
|
type SplitErr struct {
|
|
// Wrapped is the originating error during a split (or other parsing operation).
|
|
Wrapped error
|
|
// Nets are the subnets parsed out/collected so far.
|
|
Nets []*netip.Prefix
|
|
// Remaining is an IPSet of subnets/addresses that haven't been, or were unable to be, split out.
|
|
Remaining *netipx.IPSet
|
|
// LastSubnet is the most recently split out subnet.
|
|
LastSubnet *netip.Prefix
|
|
// RequestedPrefixLen is the network prefix length size, if relevant, that was attempted to be split out of Remaining.
|
|
RequestedPrefixLen uint8
|
|
}
|
|
|
|
// NetSplitter is used to split a network into multiple nets (and any remaining prefixes/addresses that didn't fit).
|
|
type NetSplitter interface {
|
|
SetParent(pfx net.IPNet)
|
|
Split() (nets []*netip.Prefix, remaining *netipx.IPSet, err error)
|
|
}
|
|
|
|
// BaseSplitter is used to encapsulate the "parent" network to be split.
|
|
type BaseSplitter struct {
|
|
network *net.IPNet
|
|
}
|
|
|
|
/*
|
|
CIDRSplitter is used to split a network based on a fixed prefix size.
|
|
It attemps to split the network into as many networks of size PrefixLength as cleanly as possible.
|
|
*/
|
|
type CIDRSplitter struct {
|
|
// PrefixLength specifies the CIDR/prefix length of the subnets to split out.
|
|
PrefixLength uint8 `json:"prefix" xml:"prefix,attr" yaml:"network Prefix Length"`
|
|
*BaseSplitter `json:"net" xml:"net,omitempty" yaml:"network,omitempty"`
|
|
}
|
|
|
|
/*
|
|
HostSplitter is used to split a network based on total number of hosts.
|
|
It attempts to evenly distribute addresses amoungs subnets.
|
|
*/
|
|
type HostSplitter struct {
|
|
// NumberHosts is the number of hosts to be placed in each subnet to split out.
|
|
NumberHosts uint `json:"hosts" xml:"hosts,attr" yaml:"Number of Hosts Per Subnet"`
|
|
// Strict, if true, will return an error from Split if the network cannot split into subnets of NumberHosts-addressable networks exactly.
|
|
Strict bool `json:"strict" xml:"strict,attr,omitempty" yaml:"Strictly Equal Hosts Per Subnet"`
|
|
*BaseSplitter `json:"net" xml:"net,omitempty" yaml:"network,omitempty"`
|
|
}
|
|
|
|
/*
|
|
SubnetSplitter is used to split a network into a specific number of subnets of equal prefix lengths
|
|
as cleanly as poossible.
|
|
*/
|
|
type SubnetSplitter struct {
|
|
// NumberSubnets indicates the number of subnets to split the network into.
|
|
NumberSubnets uint `json:"nets" xml:"nets,attr" yaml:"Number of Target Subnets"`
|
|
// Strict, if true, will return an error from Split if the network sizes cannot split into equally-sized networks.
|
|
Strict bool `json:"strict" xml:"strict,attr,omitempty" yaml:"Strictly Equal Subnet Sizes"`
|
|
*BaseSplitter `json:"net" xml:"net,omitempty" yaml:"network,omitempty"`
|
|
}
|
|
|
|
/*
|
|
VLSMSplitter is used to split a network via VLSM (Variable-Length Subnet Masks) into multiple PrefixLengths,
|
|
in which there are multiple desired subnets of varying lengths.
|
|
*/
|
|
type VLSMSplitter struct {
|
|
/*
|
|
Ascending, if true, will subnet smaller networks/larger prefixes near the beginning
|
|
(ascending order) instead of larger networks/smaller prefixes (descending order).
|
|
You almost assuredly do not want to do this.
|
|
*/
|
|
Ascending bool
|
|
// PrefixLengths contains the prefix lengths of each subnet to split out from the network.
|
|
PrefixLengths []uint8 `json:"prefixes" xml:"prefixes>prefix" yaml:"Prefix Lengths"`
|
|
*BaseSplitter `json:"net" xml:"net,omitempty" yaml:"network,omitempty"`
|
|
}
|
|
|
|
/*
|
|
StructuredResults is used for serializing prefixes into a structured/defined data format.
|
|
*/
|
|
type StructuredResults struct {
|
|
XMLName xml.Name `json:"-" xml:"results" yaml:"-"`
|
|
// Original is the provided parent network/prefix.
|
|
Original *netip.Prefix `json:"orig" xml:"orig,attr,omitempty" yaml:"Original/Parent network"`
|
|
// HostAddr is nil if Original falls on a network prefix boundary, otherwise it is the specified host address.
|
|
HostAddr *netip.Addr `json:"host" xml:"host,attr,omitempty" yaml:"Host Address,omitempty"`
|
|
// Canonical is the canonical network of Original (e.g. with host bits masked out). It is nil if Original.Addr() falls on the (lower) boundary.
|
|
Canonical *netip.Prefix `json:"masked" xml:"masked,attr,omitempty" yaml:"Bound Original/Parent network"`
|
|
// Splitter contains the spplitter and its options used to split the network.
|
|
Splitter *SplitOpts `json:"splitter" xml:"splitter,omitempty" yaml:"Splitter,omitempty"`
|
|
// Allocated contains valid subnet(s) in Original per the user-specified subnetting rules.
|
|
Allocated []*ContainedResult `json:"subnets" xml:"subnets>subnet,omitempty" yaml:"Subnets"`
|
|
// Unallocated contains subnets from Original that did not meet the splitting criteria or were left over from the split operation.
|
|
Unallocated []*ContainedResult `json:"remaining" xml:"remaining>subnet,omitempty" yaml:"Remaining/Unallocated/Left Over,omitempty"`
|
|
}
|
|
|
|
type SplitOpts struct {
|
|
XMLName xml.Name `json:"-" xml:"splitter" yaml:"-"`
|
|
CIDR *CIDRSplitter `json:"cidr,omitempty" xml:"cidr,omitempty" yaml:"CIDR Splitter,omitempty"`
|
|
Host *HostSplitter `json:"host,omitempty" xml:"host,omitempty" yaml:"Host Splitter,omitempty"`
|
|
Subnet *SubnetSplitter `json:"subnet,omitempty" xml:"subnet,omitempty" yaml:"Subnet Splitter,omitempty"`
|
|
VLSM *VLSMSplitter `json:"vlsm,omitempty" xml:"vlsm,omitempty" yaml:"VLSM Splitter,omitempty"`
|
|
}
|
|
|
|
// ContainedResult is a single Network (either an allocated subnet or a remaining block).
|
|
type ContainedResult struct {
|
|
XMLName xml.Name `json:"-" yaml:"-" xml:"subnet"`
|
|
Network *netip.Prefix `json:"net" xml:"net,attr,omitempty" yaml:"network,omitempty"`
|
|
}
|