Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IPBlock convenience functions #76

Merged
merged 10 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pkg/interval/intervalset.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ func (c *CanonicalSet) Min() int64 {
return c.intervalSet[0].Start()
}

func (c *CanonicalSet) Max() int64 {
if len(c.intervalSet) == 0 {
log.Panic("cannot take max from empty interval set")
}
return c.intervalSet[c.NumIntervals()-1].End()
}

// IsEmpty returns true if the CanonicalSet is empty
func (c *CanonicalSet) IsEmpty() bool {
return len(c.intervalSet) == 0
Expand Down
91 changes: 90 additions & 1 deletion pkg/netset/ipblock.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ const (
// CidrAll represents the CIDR for all addresses "0.0.0.0/0"
CidrAll = "0.0.0.0/0"

FirstIPAddressString = "0.0.0.0"
LastIPAddressString = "255.255.255.255"

// internal const below
ipBase = 10
ipMask = 0xffffffff
Expand Down Expand Up @@ -144,7 +147,12 @@ func (b *IPBlock) ipCount() int {
return int(b.ipRange.CalculateSize())
}

// Split returns a set of IpBlock objects, each with a single range of ips
// IsASingleIPAddress returns true if this ipblock is a single IP address
func (b *IPBlock) IsSingleIPAddress() bool {
return b.ipRange.IsSingleNumber()
}

// Split returns a set of IPBlock objects, each with a single range of ips
func (b *IPBlock) Split() []*IPBlock {
intervals := b.ipRange.Intervals()
res := make([]*IPBlock, len(intervals))
Expand All @@ -156,6 +164,18 @@ func (b *IPBlock) Split() []*IPBlock {
return res
}

// SplitToCidrs returns a slice of IPBlocks, each representing a single CIDR
func (b *IPBlock) SplitToCidrs() []*IPBlock {
cidrs := make([]*IPBlock, 0)
for _, ipRange := range b.ipRange.Intervals() {
for _, cidrString := range intervalToCidrList(ipRange) {
ipblock, _ := IPBlockFromCidr(cidrString)
cidrs = append(cidrs, ipblock)
}
}
return cidrs
}

// int64ToIP4 returns a string of an ip address from an input integer ip value
func int64ToIP4(ipInt int64) string {
if ipInt < 0 || ipInt > math.MaxUint32 {
Expand Down Expand Up @@ -244,6 +264,16 @@ func IPBlockFromCidrOrAddress(s string) (*IPBlock, error) {
return IPBlockFromIPAddress(s)
}

// IPBlockFromRange returns a new IPBlock object that contains startIP-endIP
func IPBlockFromRange(startIP, endIP *IPBlock) (*IPBlock, error) {
s := startIP.ToIPAddressString() + "-" + endIP.ToIPAddressString()
ipblock, err := IPBlockFromIPRangeStr(s)
if err != nil {
return nil, err
}
return ipblock, nil
}

// IPBlockFromCidrList returns IPBlock object from multiple CIDRs given as list of strings
func IPBlockFromCidrList(cidrsList []string) (*IPBlock, error) {
res := NewIPBlock()
Expand Down Expand Up @@ -338,6 +368,44 @@ func (b *IPBlock) FirstIPAddress() string {
return int64ToIP4(b.ipRange.Min())
}

// FirstIPAddresObject returns the first IP Address for this IPBlock
func (b *IPBlock) FirstIPAddressObject() *IPBlock {
res, _ := IPBlockFromIPAddress(b.FirstIPAddress())
return res
}

// LastIPAddress returns the last IP Address string for this IPBlock
func (b *IPBlock) LastIPAddress() string {
return int64ToIP4(b.ipRange.Max())
}

// LastIPAddresObject returns the last IP Address for this IPBlock
func (b *IPBlock) LastIPAddressObject() *IPBlock {
res, _ := IPBlockFromIPAddress(b.LastIPAddress())
return res
}

// NextIP returns the next ip address after this IPBlock
func (b *IPBlock) NextIP() (*IPBlock, error) {
if GetLastIPAddress().IsSubset(b) {
return nil, fmt.Errorf("%s is contained in ipblock", LastIPAddressString)
}
other := GetCidrAll().Subtract(b)
otherIPRanges := other.Split()
lastRange := otherIPRanges[len(otherIPRanges)-1]
return lastRange.FirstIPAddressObject(), nil
}

// PreviousIP returns the previous ip address before this IPBlock
func (b *IPBlock) PreviousIP() (*IPBlock, error) {
if GetFirstIPAddress().IsSubset(b) {
return nil, fmt.Errorf("%s is contained in IPBlock", FirstIPAddressString)
}
other := GetCidrAll().Subtract(b)
otherFirstRange := other.Split()[0]
return otherFirstRange.LastIPAddressObject(), nil
}

func intervalToCidrList(ipRange interval.Interval) []string {
start := ipRange.Start()
end := ipRange.End()
Expand Down Expand Up @@ -396,6 +464,18 @@ func GetCidrAll() *IPBlock {
return res
}

// GetFirstIPAddress returns IPBlock object of 0.0.0.0
func GetFirstIPAddress() *IPBlock {
res, _ := IPBlockFromIPAddress(FirstIPAddressString)
return res
}

// GetLastIPAddress returns IPBlock object of 255.255.255.255
func GetLastIPAddress() *IPBlock {
res, _ := IPBlockFromIPAddress(LastIPAddressString)
return res
}

// PrefixLength returns the cidr's prefix length, assuming the ipBlock is exactly one cidr.
// Prefix length specifies the number of bits in the IP address that are to be used as the subnet mask.
func (b *IPBlock) PrefixLength() (int64, error) {
Expand All @@ -415,3 +495,12 @@ func (b *IPBlock) String() string {
}
return b.ToCidrListString()
}

// TouchingIPRanges returns true if this and other ipblocks objects are touching.
// assumption: both IPBlocks are a single IP range
func (b *IPBlock) TouchingIPRanges(other *IPBlock) bool {
u := b.Union(other)
IPRanges := u.ToIPRanges()
ranges := strings.Split(IPRanges, commaSeparator)
return (len(ranges) == 1 && !b.Overlap(other))
}