Merge pull request #166 from NeilW/host-loca

plugins/host-local: ensure subnet is a network address
This commit is contained in:
Casey Callendrello 2018-06-20 17:49:42 +02:00 committed by GitHub
commit 696b1f9ab1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 12 deletions

View File

@ -372,7 +372,7 @@ var _ = Describe("IPAM config", func() {
"type": "host-local",
"ranges": [
[{"subnet": "10.1.2.0/24"}],
[{"subnet": "2001:db8:1::/24"}]
[{"subnet": "2001:db8:1::/48"}]
]
}
}`

View File

@ -40,6 +40,12 @@ func (r *Range) Canonicalize() error {
return fmt.Errorf("IPNet IP and Mask version mismatch")
}
// Ensure Subnet IP is the network address, not some other address
networkIP := r.Subnet.IP.Mask(r.Subnet.Mask)
if !r.Subnet.IP.Equal(networkIP) {
return fmt.Errorf("Network has host bits set. For a subnet mask of length %d the network address is %s", ones, networkIP.String())
}
// If the gateway is nil, claim .1
if r.Gateway == nil {
r.Gateway = ip.NextIP(r.Subnet.IP)

View File

@ -25,7 +25,7 @@ import (
)
var _ = Describe("IP ranges", func() {
It("should generate sane defaults for ipv4", func() {
It("should generate sane defaults for ipv4 with a clean prefix", func() {
snstr := "192.0.2.0/24"
r := Range{Subnet: mustSubnet(snstr)}
@ -33,7 +33,7 @@ var _ = Describe("IP ranges", func() {
Expect(err).NotTo(HaveOccurred())
Expect(r).To(Equal(Range{
Subnet: mustSubnet(snstr),
Subnet: networkSubnet(snstr),
RangeStart: net.IP{192, 0, 2, 1},
RangeEnd: net.IP{192, 0, 2, 254},
Gateway: net.IP{192, 0, 2, 1},
@ -47,13 +47,41 @@ var _ = Describe("IP ranges", func() {
Expect(err).NotTo(HaveOccurred())
Expect(r).To(Equal(Range{
Subnet: mustSubnet(snstr),
Subnet: networkSubnet(snstr),
RangeStart: net.IP{192, 0, 2, 1},
RangeEnd: net.IP{192, 0, 2, 126},
Gateway: net.IP{192, 0, 2, 1},
}))
})
It("should generate sane defaults for ipv6", func() {
It("should reject ipv4 subnet using a masked address", func() {
snstr := "192.0.2.12/24"
r := Range{Subnet: mustSubnet(snstr)}
err := r.Canonicalize()
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 24 the network address is 192.0.2.0"))
})
It("should reject ipv6 subnet using a masked address", func() {
snstr := "2001:DB8:1::24:19ff:fee1:c44a/64"
r := Range{Subnet: mustSubnet(snstr)}
err := r.Canonicalize()
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 64 the network address is 2001:db8:1::"))
})
It("should reject ipv6 prefix with host bit set", func() {
snstr := "2001:DB8:24:19ff::/63"
r := Range{Subnet: mustSubnet(snstr)}
err := r.Canonicalize()
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 63 the network address is 2001:db8:24:19fe::"))
})
It("should reject ipv4 network with host bit set", func() {
snstr := "192.168.127.0/23"
r := Range{Subnet: mustSubnet(snstr)}
err := r.Canonicalize()
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 23 the network address is 192.168.126.0"))
})
It("should generate sane defaults for ipv6 with a clean prefix", func() {
snstr := "2001:DB8:1::/64"
r := Range{Subnet: mustSubnet(snstr)}
@ -61,7 +89,7 @@ var _ = Describe("IP ranges", func() {
Expect(err).NotTo(HaveOccurred())
Expect(r).To(Equal(Range{
Subnet: mustSubnet(snstr),
Subnet: networkSubnet(snstr),
RangeStart: net.ParseIP("2001:DB8:1::1"),
RangeEnd: net.ParseIP("2001:DB8:1::ffff:ffff:ffff:ffff"),
Gateway: net.ParseIP("2001:DB8:1::1"),
@ -75,16 +103,17 @@ var _ = Describe("IP ranges", func() {
})
It("should reject invalid RangeStart and RangeEnd specifications", func() {
r := Range{Subnet: mustSubnet("192.0.2.0/24"), RangeStart: net.ParseIP("192.0.3.0")}
snstr := "192.0.2.0/24"
r := Range{Subnet: mustSubnet(snstr), RangeStart: net.ParseIP("192.0.3.0")}
err := r.Canonicalize()
Expect(err).Should(MatchError("RangeStart 192.0.3.0 not in network 192.0.2.0/24"))
r = Range{Subnet: mustSubnet("192.0.2.0/24"), RangeEnd: net.ParseIP("192.0.4.0")}
r = Range{Subnet: mustSubnet(snstr), RangeEnd: net.ParseIP("192.0.4.0")}
err = r.Canonicalize()
Expect(err).Should(MatchError("RangeEnd 192.0.4.0 not in network 192.0.2.0/24"))
r = Range{
Subnet: mustSubnet("192.0.2.0/24"),
Subnet: networkSubnet(snstr),
RangeStart: net.ParseIP("192.0.2.50"),
RangeEnd: net.ParseIP("192.0.2.40"),
}
@ -99,8 +128,9 @@ var _ = Describe("IP ranges", func() {
})
It("should parse all fields correctly", func() {
snstr := "192.0.2.0/24"
r := Range{
Subnet: mustSubnet("192.0.2.0/24"),
Subnet: mustSubnet(snstr),
RangeStart: net.ParseIP("192.0.2.40"),
RangeEnd: net.ParseIP("192.0.2.50"),
Gateway: net.ParseIP("192.0.2.254"),
@ -109,7 +139,7 @@ var _ = Describe("IP ranges", func() {
Expect(err).NotTo(HaveOccurred())
Expect(r).To(Equal(Range{
Subnet: mustSubnet("192.0.2.0/24"),
Subnet: networkSubnet(snstr),
RangeStart: net.IP{192, 0, 2, 40},
RangeEnd: net.IP{192, 0, 2, 50},
Gateway: net.IP{192, 0, 2, 254},
@ -207,3 +237,9 @@ func mustSubnet(s string) types.IPNet {
canonicalizeIP(&n.IP)
return types.IPNet(*n)
}
func networkSubnet(s string) types.IPNet {
net := mustSubnet(s)
net.IP = net.IP.Mask(net.Mask)
return net
}

View File

@ -444,7 +444,7 @@ var _ = Describe("host-local Operations", func() {
"dataDir": "%s",
"ranges": [
[{"subnet":"172.16.1.0/24"}, { "subnet": "10.1.2.0/24" }],
[{ "subnet": "2001:db8:1::/24" }]
[{ "subnet": "2001:db8:1::/48" }]
]
},
"args": {