v0.2.5
ADDED: * num-addrs subcommand, to get the number of hosts/addresses in a given prefix length * get-net subcommand, to more easily get a single subnet from either the beginning or the end of a prefix. (MUCH FASTER than CIDR-splitting!)
This commit is contained in:
102
netsplit/funcs_prefixgetter.go
Normal file
102
netsplit/funcs_prefixgetter.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package netsplit
|
||||
|
||||
import (
|
||||
`fmt`
|
||||
`net/netip`
|
||||
|
||||
`go4.org/netipx`
|
||||
)
|
||||
|
||||
// Split is to conform to a NetSplitter, though a PrefixGetter is *technically* not a splitter.
|
||||
func (p *PrefixGetter) Split() (nets []*netip.Prefix, remaining *netipx.IPSet, err error) {
|
||||
|
||||
var ok bool
|
||||
var base netip.Prefix
|
||||
var vlsmS *VLSMSplitter
|
||||
var addr netip.Addr
|
||||
var maxPfxLen uint8 = maxBitsv4
|
||||
var ipsb *netipx.IPSetBuilder = new(netipx.IPSetBuilder)
|
||||
|
||||
if p == nil || p.PrefixLength == 0 || p.BaseSplitter == nil || p.network == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = validate.Struct(p); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// If the position is "first", we can simply call a VLSM.
|
||||
if p.Pos == "first" {
|
||||
vlsmS = &VLSMSplitter{
|
||||
Ascending: false,
|
||||
Explicit: false,
|
||||
PrefixLengths: []uint8{p.PrefixLength},
|
||||
BaseSplitter: p.BaseSplitter,
|
||||
}
|
||||
if nets, remaining, err = vlsmS.Split(); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if p.Pos != "last" {
|
||||
err = ErrUnknownPos
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise this gets... messy.
|
||||
if base, ok = netipx.FromStdIPNet(p.network); !ok {
|
||||
err = ErrBadBoundary
|
||||
return
|
||||
}
|
||||
if !base.IsValid() {
|
||||
err = ErrBadBoundary
|
||||
return
|
||||
}
|
||||
ipsb = new(netipx.IPSetBuilder)
|
||||
ipsb.AddPrefix(base.Masked())
|
||||
|
||||
// First if it's a single host prefix, ezpz gg no re.
|
||||
if base.Addr().Is6() {
|
||||
maxPfxLen = maxBitsv6
|
||||
}
|
||||
if p.PrefixLength == maxPfxLen {
|
||||
nets = make([]*netip.Prefix, 1)
|
||||
nets[0] = new(netip.Prefix)
|
||||
addr = netipx.PrefixLastIP(base)
|
||||
fmt.Println(addr.String())
|
||||
if *nets[0], err = addr.Prefix(int(p.PrefixLength)); err != nil {
|
||||
return
|
||||
}
|
||||
ipsb.Remove(addr)
|
||||
if remaining, err = ipsb.IPSet(); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise this gets... interesting.
|
||||
/*
|
||||
For IPv4, performance NORMALLY would be "fine" on modern hardware with:
|
||||
1. straight CIDR-splitting
|
||||
2. grabbing the last prefix
|
||||
3. condensing the leading prefixes to a new IPSet
|
||||
But even this can take a long time (see CIDRSplitter.Split comments).
|
||||
|
||||
In almost all cases (unless subnetting like, n+12 prefix length),
|
||||
IPv6 takes WAY too long.
|
||||
|
||||
So use the same function (LastSubnetPfx) for both cases.
|
||||
*/
|
||||
nets = make([]*netip.Prefix, 1)
|
||||
nets[0] = new(netip.Prefix)
|
||||
if *nets[0], err = LastSubnetPfx(base, p.PrefixLength); err != nil {
|
||||
return
|
||||
}
|
||||
ipsb.RemovePrefix(*nets[0])
|
||||
if remaining, err = ipsb.IPSet(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user