package netsplit import ( `math/big` `net` "net/netip" `github.com/projectdiscovery/mapcidr` "go4.org/netipx" ) /* Split splits the network defined in a HostSplitter alongside its configuration and performs the subnetting. This strategy attempts to split the network into subnets of equal number of hosts. remaining may or may not be nil depending on if the number of hosts can fit cleanly within equal network sizes on boundaries. An ErrBadNumHosts will be returned if the number of hosts does not match the *addressable* range in a prefix. */ func (h *HostSplitter) Split() (nets []*netip.Prefix, remaining *netipx.IPSet, err error) { var tgt *big.Int var hosts *big.Int var sub netip.Prefix var subPtr *netip.Prefix var split []*net.IPNet var ipsb *netipx.IPSetBuilder = new(netipx.IPSetBuilder) if h == nil || h.NumberHosts == 0 || h.BaseSplitter == nil || h.network == nil { return } if split, err = mapcidr.SplitIPNetByNumber(h.network, int(h.NumberHosts)); err != nil { return } tgt = big.NewInt(0) tgt.SetUint64(uint64(h.NumberHosts)) nets = make([]*netip.Prefix, len(split)) for idx, n := range split { sub, _ = netipx.FromStdIPNet(n) hosts = mapcidr.CountIPsInCIDR(false, false, n) if hosts == nil || tgt.Cmp(hosts) != 0 { err = &SplitErr{ Wrapped: ErrBadNumHosts, Nets: nets, Remaining: remaining, LastSubnet: &sub, RequestedPrefixLen: uint8(sub.Bits()), } ipsb.AddPrefix(sub) } else { subPtr = new(netip.Prefix) *subPtr = sub nets = append(nets, subPtr) } nets[idx] = new(netip.Prefix) *nets[idx] = sub } if remaining, err = ipsb.IPSet(); err != nil { return } return }