package bridge import ( "fmt" "net" "strconv" "testing" "github.com/docker/docker/daemon/network" "github.com/docker/docker/daemon/networkdriver/portmapper" "github.com/docker/docker/nat" "github.com/docker/docker/pkg/iptables" ) func init() { // reset the new proxy command for mocking out the userland proxy in tests portmapper.NewProxy = portmapper.NewMockProxyCommand } func findFreePort(t *testing.T) string { l, err := net.Listen("tcp", ":0") if err != nil { t.Fatal("Failed to find a free port") } defer l.Close() result, err := net.ResolveTCPAddr("tcp", l.Addr().String()) if err != nil { t.Fatal("Failed to resolve address to identify free port") } return strconv.Itoa(result.Port) } func TestAllocatePortDetection(t *testing.T) { freePort := findFreePort(t) if err := InitDriver(new(Config)); err != nil { t.Fatal("Failed to initialize network driver") } // Allocate interface if _, err := Allocate("container_id", "", "", ""); err != nil { t.Fatal("Failed to allocate network interface") } port := nat.Port(freePort + "/tcp") binding := nat.PortBinding{HostIp: "127.0.0.1", HostPort: freePort} // Allocate same port twice, expect failure on second call if _, err := AllocatePort("container_id", port, binding); err != nil { t.Fatal("Failed to find a free port to allocate") } if _, err := AllocatePort("container_id", port, binding); err == nil { t.Fatal("Duplicate port allocation granted by AllocatePort") } } func TestHostnameFormatChecking(t *testing.T) { freePort := findFreePort(t) if err := InitDriver(new(Config)); err != nil { t.Fatal("Failed to initialize network driver") } // Allocate interface if _, err := Allocate("container_id", "", "", ""); err != nil { t.Fatal("Failed to allocate network interface") } port := nat.Port(freePort + "/tcp") binding := nat.PortBinding{HostIp: "localhost", HostPort: freePort} if _, err := AllocatePort("container_id", port, binding); err == nil { t.Fatal("Failed to check invalid HostIP") } } func newInterfaceAllocation(t *testing.T, globalIPv6 *net.IPNet, requestedMac, requestedIP, requestedIPv6 string, expectFail bool) *network.Settings { // set IPv6 global if given if globalIPv6 != nil { globalIPv6Network = globalIPv6 } networkSettings, err := Allocate("container_id", requestedMac, requestedIP, requestedIPv6) if err == nil && expectFail { t.Fatal("Doesn't fail to allocate network interface") } else if err != nil && !expectFail { t.Fatal("Failed to allocate network interface") } if globalIPv6 != nil { // check for bug #11427 if globalIPv6Network.IP.String() != globalIPv6.IP.String() { t.Fatal("globalIPv6Network was modified during allocation") } // clean up IPv6 global globalIPv6Network = nil } return networkSettings } func TestIPv6InterfaceAllocationAutoNetmaskGt80(t *testing.T) { _, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/81") networkSettings := newInterfaceAllocation(t, subnet, "", "", "", false) // ensure low manually assigend global ip ip := net.ParseIP(networkSettings.GlobalIPv6Address) _, subnet, _ = net.ParseCIDR(fmt.Sprintf("%s/%d", subnet.IP.String(), 120)) if !subnet.Contains(ip) { t.Fatalf("Error ip %s not in subnet %s", ip.String(), subnet.String()) } } func TestIPv6InterfaceAllocationAutoNetmaskLe80(t *testing.T) { _, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80") networkSettings := newInterfaceAllocation(t, subnet, "ab:cd:ab:cd:ab:cd", "", "", false) // ensure global ip with mac ip := net.ParseIP(networkSettings.GlobalIPv6Address) expectedIP := net.ParseIP("2001:db8:1234:1234:1234:abcd:abcd:abcd") if ip.String() != expectedIP.String() { t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String()) } // ensure link local format ip = net.ParseIP(networkSettings.LinkLocalIPv6Address) expectedIP = net.ParseIP("fe80::a9cd:abff:fecd:abcd") if ip.String() != expectedIP.String() { t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String()) } } func TestIPv6InterfaceAllocationRequest(t *testing.T) { _, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80") expectedIP := "2001:db8:1234:1234:1234::1328" networkSettings := newInterfaceAllocation(t, subnet, "", "", expectedIP, false) // ensure global ip with mac ip := net.ParseIP(networkSettings.GlobalIPv6Address) if ip.String() != expectedIP { t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP) } // retry -> fails for duplicated address _ = newInterfaceAllocation(t, subnet, "", "", expectedIP, true) } func TestMacAddrGeneration(t *testing.T) { ip := net.ParseIP("192.168.0.1") mac := generateMacAddr(ip).String() // Should be consistent. if generateMacAddr(ip).String() != mac { t.Fatal("Inconsistent MAC address") } // Should be unique. ip2 := net.ParseIP("192.168.0.2") if generateMacAddr(ip2).String() == mac { t.Fatal("Non-unique MAC address") } } func TestLinkContainers(t *testing.T) { // Init driver if err := InitDriver(new(Config)); err != nil { t.Fatal("Failed to initialize network driver") } // Allocate interface if _, err := Allocate("container_id", "", "", ""); err != nil { t.Fatal("Failed to allocate network interface") } bridgeIface = "lo" if _, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter, false); err != nil { t.Fatal(err) } if err := LinkContainers("-I", "172.17.0.1", "172.17.0.2", []nat.Port{nat.Port("1234")}, false); err != nil { t.Fatal("LinkContainers failed") } // flush rules if _, err := iptables.Raw([]string{"-F", "DOCKER"}...); err != nil { t.Fatal(err) } }