Skip to content

Commit

Permalink
Merge pull request #365 from andreaskaris/nil-pointer-exclude-range
Browse files Browse the repository at this point in the history
IterateForAssignment: Properly handle invalid syntax for exclude range
  • Loading branch information
dougbtv committed Jul 21, 2023
2 parents a31fc99 + e29384d commit 23e6020
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
31 changes: 30 additions & 1 deletion pkg/allocate/allocate.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,14 @@ func IterateForAssignment(ipnet net.IPNet, rangeStart net.IP, rangeEnd net.IP, r
for _, r := range reserveList {
reserved[r.IP.String()] = true
}

// Build excluded list, "192.168.2.229/30", "192.168.1.229/30".
excluded := []*net.IPNet{}
for _, v := range excludeRanges {
_, subnet, _ := net.ParseCIDR(v)
subnet, err := parseExcludedRange(v)
if err != nil {
return net.IP{}, reserveList, fmt.Errorf("could not parse exclude range, err: %q", err)
}
excluded = append(excluded, subnet)
}

Expand Down Expand Up @@ -146,3 +150,28 @@ func skipExcludedSubnets(ip net.IP, excluded []*net.IPNet) net.IP {
}
return nil
}

// parseExcludedRange parses a provided string to a net.IPNet.
// If the provided string is a valid CIDR, return the net.IPNet for that CIDR.
// If the provided string is a valid IP address, add the /32 or /128 prefix to form the CIDR and return the net.IPNet.
// Otherwise, return the error.
func parseExcludedRange(s string) (*net.IPNet, error) {
// Try parsing CIDRs.
_, subnet, err := net.ParseCIDR(s)
if err == nil {
return subnet, nil
}
// The user might have given a single IP address, try parsing that - if it does not parse, return the error that
// we got earlier.
ip := net.ParseIP(s)
if ip == nil {
return nil, err
}
// If the address parses, check if it's IPv4 or IPv6 and add the correct prefix.
if ip.To4() != nil {
_, subnet, err = net.ParseCIDR(fmt.Sprintf("%s/32", s))
} else {
_, subnet, err = net.ParseCIDR(fmt.Sprintf("%s/128", s))
}
return subnet, err
}
53 changes: 53 additions & 0 deletions pkg/allocate/allocate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,33 @@ var _ = Describe("Allocation operations", func() {

})

It("can IterateForAssignment on an IPv4 address excluding a range which is a single IP", func() {
firstip, ipnet, err := net.ParseCIDR("192.168.0.0/29")
Expect(err).NotTo(HaveOccurred())

// figure out the range start.
calculatedrangestart := net.ParseIP(firstip.Mask(ipnet.Mask).String())

var ipres []types.IPReservation
exrange := []string{"192.168.0.1"}
newip, _, err := IterateForAssignment(*ipnet, calculatedrangestart, nil, ipres, exrange, "0xdeadbeef", "")
Expect(err).NotTo(HaveOccurred())
Expect(fmt.Sprint(newip)).To(Equal("192.168.0.2"))
})

It("correctly handles invalid syntax for an exclude range with IPv4", func() {
firstip, ipnet, err := net.ParseCIDR("192.168.0.0/29")
Expect(err).NotTo(HaveOccurred())

// figure out the range start.
calculatedrangestart := net.ParseIP(firstip.Mask(ipnet.Mask).String())

var ipres []types.IPReservation
exrange := []string{"192.168.0.1/123"}
_, _, err = IterateForAssignment(*ipnet, calculatedrangestart, nil, ipres, exrange, "0xdeadbeef", "")
Expect(err).To(MatchError(HavePrefix("could not parse exclude range")))
})

It("can IterateForAssignment on an IPv6 address excluding a range", func() {

firstip, ipnet, err := net.ParseCIDR("100::2:1/125")
Expand All @@ -128,6 +155,32 @@ var _ = Describe("Allocation operations", func() {

})

It("can IterateForAssignment on an IPv6 address excluding a range which is a single IP", func() {
firstip, ipnet, err := net.ParseCIDR("100::2:1/125")
Expect(err).NotTo(HaveOccurred())

// figure out the range start.
calculatedrangestart := net.ParseIP(firstip.Mask(ipnet.Mask).String())

var ipres []types.IPReservation
exrange := []string{"100::2:1"}
newip, _, _ := IterateForAssignment(*ipnet, calculatedrangestart, nil, ipres, exrange, "0xdeadbeef", "")
Expect(fmt.Sprint(newip)).To(Equal("100::2:2"))
})

It("correctly handles invalid syntax for an exclude range with IPv6", func() {
firstip, ipnet, err := net.ParseCIDR("100::2:1/125")
Expect(err).NotTo(HaveOccurred())

// figure out the range start.
calculatedrangestart := net.ParseIP(firstip.Mask(ipnet.Mask).String())

var ipres []types.IPReservation
exrange := []string{"100::2::1"}
_, _, err = IterateForAssignment(*ipnet, calculatedrangestart, nil, ipres, exrange, "0xdeadbeef", "")
Expect(err).To(MatchError(HavePrefix("could not parse exclude range")))
})

It("can IterateForAssignment on an IPv6 address excluding a very large range", func() {

firstip, ipnet, err := net.ParseCIDR("2001:db8::/30")
Expand Down

0 comments on commit 23e6020

Please sign in to comment.