From 88a68ef21c1a30e0f81b675f1ee08675d8cba709 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 7 Oct 2024 16:12:22 +0300 Subject: [PATCH 1/9] ipblock convenience functions --- pkg/interval/intervalset.go | 7 +++++++ pkg/netset/ipblock.go | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/pkg/interval/intervalset.go b/pkg/interval/intervalset.go index 7707d0a..d62e371 100644 --- a/pkg/interval/intervalset.go +++ b/pkg/interval/intervalset.go @@ -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 diff --git a/pkg/netset/ipblock.go b/pkg/netset/ipblock.go index 9536b91..5ac2902 100644 --- a/pkg/netset/ipblock.go +++ b/pkg/netset/ipblock.go @@ -144,7 +144,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) IsASingleIPAddress() 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)) @@ -156,6 +161,18 @@ func (b *IPBlock) Split() []*IPBlock { return res } +// SplitToCidrs returns a set of Cidrs +func (b *IPBlock) SplitToCidrs() []*IPBlock { + cidrs := make([]*IPBlock, 0) + for _, ipRange := range b.ipRange.Intervals() { + for _, cidrString := range intervalToCidrList(ipRange) { + ipblock, _ := IPBlockFromCidrOrAddress(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 { @@ -338,6 +355,23 @@ func (b *IPBlock) FirstIPAddress() string { return int64ToIP4(b.ipRange.Min()) } +// FirstIPAdddresObject returns the first IP Address for this IPBlock +func (b *IPBlock) FirstIPAdddresObject() *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()) +} + +// LastIPAdddresObject returns the last IP Address for this IPBlock +func (b *IPBlock) LastIPAdddresObject() *IPBlock { + res, _ := IPBlockFromIPAddress(b.LastIPAddress()) + return res +} + func intervalToCidrList(ipRange interval.Interval) []string { start := ipRange.Start() end := ipRange.End() From 9eea5e6ac2df2f794c2babf2ee44a007b2c79c65 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 7 Oct 2024 16:52:39 +0300 Subject: [PATCH 2/9] more functions --- pkg/netset/ipblock.go | 54 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/pkg/netset/ipblock.go b/pkg/netset/ipblock.go index 5ac2902..fc20ad0 100644 --- a/pkg/netset/ipblock.go +++ b/pkg/netset/ipblock.go @@ -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 @@ -261,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() @@ -355,8 +368,8 @@ func (b *IPBlock) FirstIPAddress() string { return int64ToIP4(b.ipRange.Min()) } -// FirstIPAdddresObject returns the first IP Address for this IPBlock -func (b *IPBlock) FirstIPAdddresObject() *IPBlock { +// FirstIPAddresObject returns the first IP Address for this IPBlock +func (b *IPBlock) FirstIPAddresObject() *IPBlock { res, _ := IPBlockFromIPAddress(b.FirstIPAddress()) return res } @@ -366,12 +379,33 @@ func (b *IPBlock) LastIPAddress() string { return int64ToIP4(b.ipRange.Max()) } -// LastIPAdddresObject returns the last IP Address for this IPBlock -func (b *IPBlock) LastIPAdddresObject() *IPBlock { +// LastIPAddresObject returns the last IP Address for this IPBlock +func (b *IPBlock) LastIPAddresObject() *IPBlock { res, _ := IPBlockFromIPAddress(b.LastIPAddress()) return res } +// NextIP returns the next ip address after this IPBlock +func (b *IPBlock) NextIP() (*IPBlock, error) { + if GetLastIPAdress().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.FirstIPAddresObject(), nil +} + +// PreviousIP returns the previous ip address before this IPBlock +func (b *IPBlock) PreviousIP() (*IPBlock, error) { + if GetFirstIPAdress().IsSubset(b) { + return nil, fmt.Errorf("%s is contained in IPBlock", FirstIPAddressString) + } + other := GetCidrAll().Subtract(b) + otherFirstRange := other.Split()[0] + return otherFirstRange.LastIPAddresObject(), nil +} + func intervalToCidrList(ipRange interval.Interval) []string { start := ipRange.Start() end := ipRange.End() @@ -430,6 +464,18 @@ func GetCidrAll() *IPBlock { return res } +// GetFirstIPAdress returns IPBlock object of 0.0.0.0 +func GetFirstIPAdress() *IPBlock { + res, _ := IPBlockFromIPAddress(FirstIPAddressString) + return res +} + +// GetLastIPAdress returns IPBlock object of 255.255.255.255 +func GetLastIPAdress() *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) { From bfce11b37605a79e8a59e585f91e6211df0c60ea Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 7 Oct 2024 16:57:08 +0300 Subject: [PATCH 3/9] touching --- pkg/netset/ipblock.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/netset/ipblock.go b/pkg/netset/ipblock.go index fc20ad0..4f0ad25 100644 --- a/pkg/netset/ipblock.go +++ b/pkg/netset/ipblock.go @@ -495,3 +495,11 @@ func (b *IPBlock) String() string { } return b.ToCidrListString() } + +// TouchingIPRanges returns true if this and other ipblocks objects are touching +func (b *IPBlock) TouchingIPRanges(other *IPBlock) bool { + u := b.Copy().Union(b) + IPRanges := u.ToIPRanges() + ranges := strings.Split(IPRanges, commaSeparator) + return (len(ranges) == 1 && !b.Overlap(other)) +} From b3b06f4fb8379d7cdd3269819785a0148cffae02 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 8 Oct 2024 12:40:52 +0300 Subject: [PATCH 4/9] review comments --- pkg/netset/ipblock.go | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/pkg/netset/ipblock.go b/pkg/netset/ipblock.go index 4f0ad25..fdae80d 100644 --- a/pkg/netset/ipblock.go +++ b/pkg/netset/ipblock.go @@ -148,7 +148,7 @@ func (b *IPBlock) ipCount() int { } // IsASingleIPAddress returns true if this ipblock is a single IP address -func (b *IPBlock) IsASingleIPAddress() bool { +func (b *IPBlock) IsSingleIPAddress() bool { return b.ipRange.IsSingleNumber() } @@ -164,12 +164,12 @@ func (b *IPBlock) Split() []*IPBlock { return res } -// SplitToCidrs returns a set of Cidrs +// 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, _ := IPBlockFromCidrOrAddress(cidrString) + ipblock, _ := IPBlockFromCidr(cidrString) cidrs = append(cidrs, ipblock) } } @@ -369,7 +369,7 @@ func (b *IPBlock) FirstIPAddress() string { } // FirstIPAddresObject returns the first IP Address for this IPBlock -func (b *IPBlock) FirstIPAddresObject() *IPBlock { +func (b *IPBlock) FirstIPAddressObject() *IPBlock { res, _ := IPBlockFromIPAddress(b.FirstIPAddress()) return res } @@ -380,30 +380,30 @@ func (b *IPBlock) LastIPAddress() string { } // LastIPAddresObject returns the last IP Address for this IPBlock -func (b *IPBlock) LastIPAddresObject() *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 GetLastIPAdress().IsSubset(b) { + 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.FirstIPAddresObject(), nil + return lastRange.FirstIPAddressObject(), nil } // PreviousIP returns the previous ip address before this IPBlock func (b *IPBlock) PreviousIP() (*IPBlock, error) { - if GetFirstIPAdress().IsSubset(b) { + if GetFirstIPAddress().IsSubset(b) { return nil, fmt.Errorf("%s is contained in IPBlock", FirstIPAddressString) } other := GetCidrAll().Subtract(b) otherFirstRange := other.Split()[0] - return otherFirstRange.LastIPAddresObject(), nil + return otherFirstRange.LastIPAddressObject(), nil } func intervalToCidrList(ipRange interval.Interval) []string { @@ -464,14 +464,14 @@ func GetCidrAll() *IPBlock { return res } -// GetFirstIPAdress returns IPBlock object of 0.0.0.0 -func GetFirstIPAdress() *IPBlock { +// GetFirstIPAddress returns IPBlock object of 0.0.0.0 +func GetFirstIPAddress() *IPBlock { res, _ := IPBlockFromIPAddress(FirstIPAddressString) return res } -// GetLastIPAdress returns IPBlock object of 255.255.255.255 -func GetLastIPAdress() *IPBlock { +// GetLastIPAddress returns IPBlock object of 255.255.255.255 +func GetLastIPAddress() *IPBlock { res, _ := IPBlockFromIPAddress(LastIPAddressString) return res } @@ -496,9 +496,10 @@ func (b *IPBlock) String() string { return b.ToCidrListString() } -// TouchingIPRanges returns true if this and other ipblocks objects are touching +// 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.Copy().Union(b) + u := b.Union(other) IPRanges := u.ToIPRanges() ranges := strings.Split(IPRanges, commaSeparator) return (len(ranges) == 1 && !b.Overlap(other)) From ea7d789fccdeb2a8d4c34d044d4af3a29170803c Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 8 Oct 2024 12:55:55 +0300 Subject: [PATCH 5/9] fix touching method --- pkg/netset/ipblock.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/netset/ipblock.go b/pkg/netset/ipblock.go index fdae80d..ec1edf0 100644 --- a/pkg/netset/ipblock.go +++ b/pkg/netset/ipblock.go @@ -498,9 +498,9 @@ func (b *IPBlock) String() string { // 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)) +func (b *IPBlock) TouchingIPRanges(other *IPBlock) (bool, error) { + if len(b.Split()) != 1 || len(other.Split()) != 1 { + return false, fmt.Errorf("both ipblocks should be a single IP range") + } + return (!b.Overlap(other) && len(b.Union(other).Split()) == 1), nil } From 0520d058c1204bdc35fe18d7390c7575f1d0bd13 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 8 Oct 2024 13:03:33 +0300 Subject: [PATCH 6/9] doc --- pkg/netset/ipblock.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/netset/ipblock.go b/pkg/netset/ipblock.go index ec1edf0..610d243 100644 --- a/pkg/netset/ipblock.go +++ b/pkg/netset/ipblock.go @@ -147,7 +147,7 @@ func (b *IPBlock) ipCount() int { return int(b.ipRange.CalculateSize()) } -// IsASingleIPAddress returns true if this ipblock is a single IP address +// IsSingleIPAddress returns true if this ipblock is a single IP address func (b *IPBlock) IsSingleIPAddress() bool { return b.ipRange.IsSingleNumber() } @@ -368,7 +368,7 @@ func (b *IPBlock) FirstIPAddress() string { return int64ToIP4(b.ipRange.Min()) } -// FirstIPAddresObject returns the first IP Address for this IPBlock +// FirstIPAddressObject returns the first IP Address for this IPBlock func (b *IPBlock) FirstIPAddressObject() *IPBlock { res, _ := IPBlockFromIPAddress(b.FirstIPAddress()) return res @@ -379,7 +379,7 @@ func (b *IPBlock) LastIPAddress() string { return int64ToIP4(b.ipRange.Max()) } -// LastIPAddresObject returns the last IP Address for this IPBlock +// LastIPAddressObject returns the last IP Address for this IPBlock func (b *IPBlock) LastIPAddressObject() *IPBlock { res, _ := IPBlockFromIPAddress(b.LastIPAddress()) return res From 0649c7e5d1b34bd5ee4595eba8ad10903e6cfb8b Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 8 Oct 2024 14:28:01 +0300 Subject: [PATCH 7/9] tests --- pkg/netset/ipblock.go | 37 ++++++++++++++++++++----------------- pkg/netset/ipblock_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 17 deletions(-) diff --git a/pkg/netset/ipblock.go b/pkg/netset/ipblock.go index 610d243..da738e0 100644 --- a/pkg/netset/ipblock.go +++ b/pkg/netset/ipblock.go @@ -264,14 +264,14 @@ 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 +// IPBlockFromIPRange returns a new IPBlock object that contains startIP-endIP +func IPBlockFromIPRange(startIP, endIP *IPBlock) (*IPBlock, error) { + if !startIP.IsSingleIPAddress() || !endIP.IsSingleIPAddress() { + return nil, fmt.Errorf("both startIP and endIP should be a single IP address") } - return ipblock, nil + return &IPBlock{ + ipRange: interval.New(startIP.ipRange.Min(), endIP.ipRange.Min()).ToSet(), + }, nil } // IPBlockFromCidrList returns IPBlock object from multiple CIDRs given as list of strings @@ -390,10 +390,11 @@ 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 + lastIP := b.LastIPAddressObject() + ipNum := lastIP.ipRange.Min() + return &IPBlock{ + ipRange: interval.New(ipNum+1, ipNum+1).ToSet(), + }, nil } // PreviousIP returns the previous ip address before this IPBlock @@ -401,9 +402,11 @@ 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 + firstIP := b.FirstIPAddressObject() + ipNum := firstIP.ipRange.Min() + return &IPBlock{ + ipRange: interval.New(ipNum-1, ipNum-1).ToSet(), + }, nil } func intervalToCidrList(ipRange interval.Interval) []string { @@ -497,10 +500,10 @@ func (b *IPBlock) String() string { } // TouchingIPRanges returns true if this and other ipblocks objects are touching. -// assumption: both IPBlocks are a single IP range +// assumption: both IPBlocks represent a single IP range func (b *IPBlock) TouchingIPRanges(other *IPBlock) (bool, error) { - if len(b.Split()) != 1 || len(other.Split()) != 1 { + if b.ipRange.NumIntervals() != 1 || other.ipRange.NumIntervals() != 1 { return false, fmt.Errorf("both ipblocks should be a single IP range") } - return (!b.Overlap(other) && len(b.Union(other).Split()) == 1), nil + return (!b.Overlap(other) && b.Union(other).ipRange.NumIntervals() == 1), nil } diff --git a/pkg/netset/ipblock_test.go b/pkg/netset/ipblock_test.go index ffbd05a..ca345a5 100644 --- a/pkg/netset/ipblock_test.go +++ b/pkg/netset/ipblock_test.go @@ -41,6 +41,42 @@ func TestOps(t *testing.T) { intersect2 := minus.Intersect(intersect) require.True(t, intersect2.IsEmpty()) + + ipb3, err := ipb2.NextIP() + ipb4, _ := netset.IPBlockFromCidrOrAddress("1.2.3.5") + require.Nil(t, err) + require.Equal(t, ipb3, ipb4) + + ipb5, err := ipb3.PreviousIP() + require.Nil(t, err) + require.Equal(t, ipb2, ipb5) + + ipb6, err := ipb1.NextIP() // ipb6 = 1.2.4.0 + ipb7, _ := netset.IPBlockFromCidrOrAddress("1.2.4.0") + require.Nil(t, err) + require.Equal(t, ipb6, ipb7) + + require.False(t, ipb1.IsSingleIPAddress()) + require.True(t, ipb2.IsSingleIPAddress()) + + ipb8, err := ipb7.PreviousIP() // ipb8 = 1.2.3.255 + require.Nil(t, err) + require.Equal(t, ipb8, ipb1.LastIPAddressObject()) + + ipb9, err := netset.IPBlockFromIPRange(ipb4, ipb6) + require.Nil(t, err) + // ipb9 = 1.2.3.5-1.2.4.0. Equal to the union of: + // 1.2.3.5/32, 1.2.3.6/31, 1.2.3.8/29, 1.2.3.16/28, + // 1.2.3.32/27, 1.2.3.64/26, 1.2.3.128/25, 1.2.4.0/32 + require.Len(t, ipb9.SplitToCidrs(), 8) + + t1, err := ipb9.TouchingIPRanges(ipb2) + require.Nil(t, err) + require.True(t, t1) + + t2, err := ipb9.TouchingIPRanges(ipb7) + require.Nil(t, err) + require.False(t, t2) } func TestConversions(t *testing.T) { From 3c6cad61fe5f49ff0c4b0b759bf98182bf77fe6f Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 8 Oct 2024 14:41:34 +0300 Subject: [PATCH 8/9] better implementation --- pkg/netset/ipblock.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/pkg/netset/ipblock.go b/pkg/netset/ipblock.go index da738e0..1dcb173 100644 --- a/pkg/netset/ipblock.go +++ b/pkg/netset/ipblock.go @@ -370,8 +370,10 @@ func (b *IPBlock) FirstIPAddress() string { // FirstIPAddressObject returns the first IP Address for this IPBlock func (b *IPBlock) FirstIPAddressObject() *IPBlock { - res, _ := IPBlockFromIPAddress(b.FirstIPAddress()) - return res + ipNum := b.ipRange.Min() + return &IPBlock{ + ipRange: interval.New(ipNum, ipNum).ToSet(), + } } // LastIPAddress returns the last IP Address string for this IPBlock @@ -381,8 +383,10 @@ func (b *IPBlock) LastIPAddress() string { // LastIPAddressObject returns the last IP Address for this IPBlock func (b *IPBlock) LastIPAddressObject() *IPBlock { - res, _ := IPBlockFromIPAddress(b.LastIPAddress()) - return res + ipNum := b.ipRange.Max() + return &IPBlock{ + ipRange: interval.New(ipNum, ipNum).ToSet(), + } } // NextIP returns the next ip address after this IPBlock @@ -391,9 +395,9 @@ func (b *IPBlock) NextIP() (*IPBlock, error) { return nil, fmt.Errorf("%s is contained in ipblock", LastIPAddressString) } lastIP := b.LastIPAddressObject() - ipNum := lastIP.ipRange.Min() + ipNum := lastIP.ipRange.Min() + 1 return &IPBlock{ - ipRange: interval.New(ipNum+1, ipNum+1).ToSet(), + ipRange: interval.New(ipNum, ipNum).ToSet(), }, nil } @@ -403,9 +407,9 @@ func (b *IPBlock) PreviousIP() (*IPBlock, error) { return nil, fmt.Errorf("%s is contained in IPBlock", FirstIPAddressString) } firstIP := b.FirstIPAddressObject() - ipNum := firstIP.ipRange.Min() + ipNum := firstIP.ipRange.Min() - 1 return &IPBlock{ - ipRange: interval.New(ipNum-1, ipNum-1).ToSet(), + ipRange: interval.New(ipNum, ipNum).ToSet(), }, nil } From 81bc391f86cacf48eaea4b380fe70840b609a6b1 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 8 Oct 2024 14:44:25 +0300 Subject: [PATCH 9/9] another test --- pkg/netset/ipblock_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/netset/ipblock_test.go b/pkg/netset/ipblock_test.go index ca345a5..83af0ce 100644 --- a/pkg/netset/ipblock_test.go +++ b/pkg/netset/ipblock_test.go @@ -77,6 +77,8 @@ func TestOps(t *testing.T) { t2, err := ipb9.TouchingIPRanges(ipb7) require.Nil(t, err) require.False(t, t2) + + require.Equal(t, ipb7, ipb7.FirstIPAddressObject()) } func TestConversions(t *testing.T) {