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", "type": "host-local",
"ranges": [ "ranges": [
[{"subnet": "10.1.2.0/24"}], [{"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") 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 the gateway is nil, claim .1
if r.Gateway == nil { if r.Gateway == nil {
r.Gateway = ip.NextIP(r.Subnet.IP) r.Gateway = ip.NextIP(r.Subnet.IP)

View File

@ -25,7 +25,7 @@ import (
) )
var _ = Describe("IP ranges", func() { 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" snstr := "192.0.2.0/24"
r := Range{Subnet: mustSubnet(snstr)} r := Range{Subnet: mustSubnet(snstr)}
@ -33,7 +33,7 @@ var _ = Describe("IP ranges", func() {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(r).To(Equal(Range{ Expect(r).To(Equal(Range{
Subnet: mustSubnet(snstr), Subnet: networkSubnet(snstr),
RangeStart: net.IP{192, 0, 2, 1}, RangeStart: net.IP{192, 0, 2, 1},
RangeEnd: net.IP{192, 0, 2, 254}, RangeEnd: net.IP{192, 0, 2, 254},
Gateway: net.IP{192, 0, 2, 1}, Gateway: net.IP{192, 0, 2, 1},
@ -47,13 +47,41 @@ var _ = Describe("IP ranges", func() {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(r).To(Equal(Range{ Expect(r).To(Equal(Range{
Subnet: mustSubnet(snstr), Subnet: networkSubnet(snstr),
RangeStart: net.IP{192, 0, 2, 1}, RangeStart: net.IP{192, 0, 2, 1},
RangeEnd: net.IP{192, 0, 2, 126}, RangeEnd: net.IP{192, 0, 2, 126},
Gateway: net.IP{192, 0, 2, 1}, 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" snstr := "2001:DB8:1::/64"
r := Range{Subnet: mustSubnet(snstr)} r := Range{Subnet: mustSubnet(snstr)}
@ -61,7 +89,7 @@ var _ = Describe("IP ranges", func() {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(r).To(Equal(Range{ Expect(r).To(Equal(Range{
Subnet: mustSubnet(snstr), Subnet: networkSubnet(snstr),
RangeStart: net.ParseIP("2001:DB8:1::1"), RangeStart: net.ParseIP("2001:DB8:1::1"),
RangeEnd: net.ParseIP("2001:DB8:1::ffff:ffff:ffff:ffff"), RangeEnd: net.ParseIP("2001:DB8:1::ffff:ffff:ffff:ffff"),
Gateway: net.ParseIP("2001:DB8:1::1"), 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() { 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() err := r.Canonicalize()
Expect(err).Should(MatchError("RangeStart 192.0.3.0 not in network 192.0.2.0/24")) 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() err = r.Canonicalize()
Expect(err).Should(MatchError("RangeEnd 192.0.4.0 not in network 192.0.2.0/24")) Expect(err).Should(MatchError("RangeEnd 192.0.4.0 not in network 192.0.2.0/24"))
r = Range{ r = Range{
Subnet: mustSubnet("192.0.2.0/24"), Subnet: networkSubnet(snstr),
RangeStart: net.ParseIP("192.0.2.50"), RangeStart: net.ParseIP("192.0.2.50"),
RangeEnd: net.ParseIP("192.0.2.40"), RangeEnd: net.ParseIP("192.0.2.40"),
} }
@ -99,8 +128,9 @@ var _ = Describe("IP ranges", func() {
}) })
It("should parse all fields correctly", func() { It("should parse all fields correctly", func() {
snstr := "192.0.2.0/24"
r := Range{ r := Range{
Subnet: mustSubnet("192.0.2.0/24"), Subnet: mustSubnet(snstr),
RangeStart: net.ParseIP("192.0.2.40"), RangeStart: net.ParseIP("192.0.2.40"),
RangeEnd: net.ParseIP("192.0.2.50"), RangeEnd: net.ParseIP("192.0.2.50"),
Gateway: net.ParseIP("192.0.2.254"), Gateway: net.ParseIP("192.0.2.254"),
@ -109,7 +139,7 @@ var _ = Describe("IP ranges", func() {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(r).To(Equal(Range{ Expect(r).To(Equal(Range{
Subnet: mustSubnet("192.0.2.0/24"), Subnet: networkSubnet(snstr),
RangeStart: net.IP{192, 0, 2, 40}, RangeStart: net.IP{192, 0, 2, 40},
RangeEnd: net.IP{192, 0, 2, 50}, RangeEnd: net.IP{192, 0, 2, 50},
Gateway: net.IP{192, 0, 2, 254}, Gateway: net.IP{192, 0, 2, 254},
@ -207,3 +237,9 @@ func mustSubnet(s string) types.IPNet {
canonicalizeIP(&n.IP) canonicalizeIP(&n.IP)
return types.IPNet(*n) 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", "dataDir": "%s",
"ranges": [ "ranges": [
[{"subnet":"172.16.1.0/24"}, { "subnet": "10.1.2.0/24" }], [{"subnet":"172.16.1.0/24"}, { "subnet": "10.1.2.0/24" }],
[{ "subnet": "2001:db8:1::/24" }] [{ "subnet": "2001:db8:1::/48" }]
] ]
}, },
"args": { "args": {