From f7b6fbbd7664634481c8519e58844d572423f3e1 Mon Sep 17 00:00:00 2001 From: Andy Kipp Date: Wed, 12 Mar 2014 17:22:57 -0400 Subject: [PATCH 1/4] Prevent dynamic allocation of previously allocated ports Docker-DCO-1.1-Signed-off-by: Andy Kipp (github: kippandrew) --- .../portallocator/portallocator.go | 32 +++++++++++++++---- .../portallocator/portallocator_test.go | 7 ++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/runtime/networkdriver/portallocator/portallocator.go b/runtime/networkdriver/portallocator/portallocator.go index 71cac82703..18ae9469e5 100644 --- a/runtime/networkdriver/portallocator/portallocator.go +++ b/runtime/networkdriver/portallocator/portallocator.go @@ -100,22 +100,30 @@ func ReleaseAll() error { } func registerDynamicPort(ip net.IP, proto string) (int, error) { - allocated := defaultAllocatedPorts[proto] - - port := nextPort(proto) - if port > EndPortRange { - return 0, ErrPortExceedsRange - } if !equalsDefault(ip) { registerIP(ip) ipAllocated := otherAllocatedPorts[ip.String()][proto] + + port, err := findNextPort(proto, ipAllocated) + if err != nil { + return 0, err + } ipAllocated.Push(port) + return port, nil + } else { + + allocated := defaultAllocatedPorts[proto] + + port, err := findNextPort(proto, allocated) + if err != nil { + return 0, err + } allocated.Push(port) + return port, nil } - return port, nil } func registerSetPort(ip net.IP, proto string, port int) error { @@ -142,6 +150,16 @@ func equalsDefault(ip net.IP) bool { return ip == nil || ip.Equal(defaultIP) } +func findNextPort(proto string, allocated *collections.OrderedIntSet) (int, error) { + port := 0 + for port = nextPort(proto); allocated.Exists(port); port = nextPort(proto) { + } + if port > EndPortRange { + return 0, ErrPortExceedsRange + } + return port, nil +} + func nextPort(proto string) int { c := currentDynamicPort[proto] + 1 currentDynamicPort[proto] = c diff --git a/runtime/networkdriver/portallocator/portallocator_test.go b/runtime/networkdriver/portallocator/portallocator_test.go index 603bd03bd7..3f3afa657b 100644 --- a/runtime/networkdriver/portallocator/portallocator_test.go +++ b/runtime/networkdriver/portallocator/portallocator_test.go @@ -181,4 +181,11 @@ func TestPortAllocation(t *testing.T) { if _, err := RequestPort(ip, "tcp", 80); err != nil { t.Fatal(err) } + + port, err = RequestPort(ip, "tcp", 0) + port2, err := RequestPort(ip, "tcp", port+1) + port3, err := RequestPort(ip, "tcp", 0) + if port3 == port2 { + t.Fatal("A dynamic port should never allocate a used port") + } } From 7a1db291fcedd50ce99649e95109187c76da255c Mon Sep 17 00:00:00 2001 From: Andy Kipp Date: Wed, 12 Mar 2014 17:26:17 -0400 Subject: [PATCH 2/4] Better test error message Docker-DCO-1.1-Signed-off-by: Andy Kipp (github: kippandrew) --- runtime/networkdriver/portallocator/portallocator_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/networkdriver/portallocator/portallocator_test.go b/runtime/networkdriver/portallocator/portallocator_test.go index 3f3afa657b..356da855b6 100644 --- a/runtime/networkdriver/portallocator/portallocator_test.go +++ b/runtime/networkdriver/portallocator/portallocator_test.go @@ -186,6 +186,6 @@ func TestPortAllocation(t *testing.T) { port2, err := RequestPort(ip, "tcp", port+1) port3, err := RequestPort(ip, "tcp", 0) if port3 == port2 { - t.Fatal("A dynamic port should never allocate a used port") + t.Fatal("Requesting a dynamic port should never allocate a used port") } } From 73c416a20db8fe48302a6cf0db4c1c0585ed0739 Mon Sep 17 00:00:00 2001 From: Andy Kipp Date: Thu, 13 Mar 2014 13:30:07 -0400 Subject: [PATCH 3/4] Be more explicit in finding next port to allocate Docker-DCO-1.1-Signed-off-by: Andy Kipp (github: kippandrew) --- runtime/networkdriver/portallocator/portallocator.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/runtime/networkdriver/portallocator/portallocator.go b/runtime/networkdriver/portallocator/portallocator.go index 18ae9469e5..4d698f2de2 100644 --- a/runtime/networkdriver/portallocator/portallocator.go +++ b/runtime/networkdriver/portallocator/portallocator.go @@ -151,8 +151,9 @@ func equalsDefault(ip net.IP) bool { } func findNextPort(proto string, allocated *collections.OrderedIntSet) (int, error) { - port := 0 - for port = nextPort(proto); allocated.Exists(port); port = nextPort(proto) { + port := nextPort(proto) + for allocated.Exists(port) { + port = nextPort(proto) } if port > EndPortRange { return 0, ErrPortExceedsRange From 555416fd02b9e062385dcdaf0c4b9f5de61df388 Mon Sep 17 00:00:00 2001 From: Andy Kipp Date: Tue, 18 Mar 2014 13:29:24 -0400 Subject: [PATCH 4/4] Add err checks for port allocator tests Docker-DCO-1.1-Signed-off-by: Andy Kipp (github: kippandrew) --- .../networkdriver/portallocator/portallocator_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/runtime/networkdriver/portallocator/portallocator_test.go b/runtime/networkdriver/portallocator/portallocator_test.go index 356da855b6..f01bcfc99e 100644 --- a/runtime/networkdriver/portallocator/portallocator_test.go +++ b/runtime/networkdriver/portallocator/portallocator_test.go @@ -183,8 +183,17 @@ func TestPortAllocation(t *testing.T) { } port, err = RequestPort(ip, "tcp", 0) + if err != nil { + t.Fatal(err) + } port2, err := RequestPort(ip, "tcp", port+1) + if err != nil { + t.Fatal(err) + } port3, err := RequestPort(ip, "tcp", 0) + if err != nil { + t.Fatal(err) + } if port3 == port2 { t.Fatal("Requesting a dynamic port should never allocate a used port") }