diff --git a/networking/libsnnet/dnsmasq.go b/networking/libsnnet/dnsmasq.go index eace472ad..b80351e60 100644 --- a/networking/libsnnet/dnsmasq.go +++ b/networking/libsnnet/dnsmasq.go @@ -270,8 +270,8 @@ func (d *Dnsmasq) getSubnetConfiguration() error { return fmt.Errorf("invalid subnet") } - d.gateway.IP = d.TenantNet.IP.To4().Mask(d.TenantNet.Mask) - d.gateway.Mask = d.TenantNet.Mask + tenantNetCopy := IPNetDeepCopy(d.TenantNet) + d.gateway = *tenantNetCopy d.startIP = d.TenantNet.IP.To4().Mask(d.TenantNet.Mask) d.endIP = d.TenantNet.IP.To4().Mask(d.TenantNet.Mask) //End Hack diff --git a/networking/libsnnet/utils.go b/networking/libsnnet/utils.go index da285fb59..6fdbc09bb 100644 --- a/networking/libsnnet/utils.go +++ b/networking/libsnnet/utils.go @@ -68,6 +68,21 @@ func init() { ifaceRsrc = rand.New(ifaceRseed) } +// IPNetDeepCopy returns a full copy of a net.IPNet struct +func IPNetDeepCopy(IPNetToCopy net.IPNet) *net.IPNet { + var newIPNet net.IPNet + + // create a copy of the net.IP slice + newIPNet.IP = make(net.IP, len(IPNetToCopy.IP)) + copy(newIPNet.IP, IPNetToCopy.IP) + + // create a copy of the net.IPMask slice + newIPNet.Mask = make(net.IPMask, len(IPNetToCopy.Mask)) + copy(newIPNet.Mask, IPNetToCopy.Mask) + + return &newIPNet +} + func validSnPrefix(s string) bool { switch { case strings.HasPrefix(s, prefixBridge): diff --git a/networking/libsnnet/utils_test.go b/networking/libsnnet/utils_test.go index b813f39bb..7f371da39 100644 --- a/networking/libsnnet/utils_test.go +++ b/networking/libsnnet/utils_test.go @@ -17,9 +17,15 @@ package libsnnet import ( + "net" "testing" ) +const ( + testCIDRIPv4 = "198.51.100.0/24" + testCIDRIPv6 = "2001:db8::/32" +) + func TestEqualNetSlice(t *testing.T) { netSlice1 := []string{"192.168.0.0/24", "192.168.5.0/24", "192.168.42.0/24"} netSlice2 := []string{"192.168.0.0/24", "192.168.5.0/24", "192.168.42.0/24"} @@ -29,3 +35,43 @@ func TestEqualNetSlice(t *testing.T) { t.Fatalf("Expected true, got %v", equalSlices) } } + +// TestIPNetDeepCopyIPv4 tests that given an *IPNet (ip1) +// creates a full copy of that struct (ip2), so if we +// modify the copy, original struct should not change +// this test is expected to pass +func TestIPNetDeepCopyIPv4(t *testing.T) { + _, ip1, _ := net.ParseCIDR(testCIDRIPv4) + ip2 := IPNetDeepCopy(*ip1) + + // check address of structs are different + if ip1 == ip2 { + t.Fatalf("expected a copy of %v, got a reference", ip1) + } + + // change values of copy to verify original is not changed + ip2.IP = []byte{42, 42, 42, 42} + if ip1.String() != testCIDRIPv4 { + t.Fatalf("expected %v, got %v", testCIDRIPv4, ip1.String()) + } +} + +// TestIPNetDeepCopyIPv6 perform a test similar to +// TestIPNetDeepCopyIPv4 but using an IPv6 CIDR as input +// this test is expected to pass +func TestIPNetDeepCopyIPv6(t *testing.T) { + _, ip1, _ := net.ParseCIDR(testCIDRIPv6) + ip2 := IPNetDeepCopy(*ip1) + + // check address of structs are different + if ip1 == ip2 { + t.Fatalf("expected a copy of %v, got a reference", ip1) + } + + // change values of copy to verify original is not changed + // new value "2001:db8:2001:db8:2001:db8:2001:db8" + ip2.IP = []byte{32, 01, 13, 184, 32, 01, 13, 184, 32, 01, 13, 184, 32, 01, 13, 184} + if ip1.String() != testCIDRIPv6 { + t.Fatalf("expected %v, got %v", testCIDRIPv6, ip1.String()) + } +}