diff --git a/network.go b/network.go index 690d252ec2..ea5e5c8586 100644 --- a/network.go +++ b/network.go @@ -485,20 +485,38 @@ type Nat struct { func parseNat(spec string) (*Nat, error) { var nat Nat - // If spec starts with ':', external and internal ports must be the same. - // This might fail if the requested external port is not available. - var sameFrontend bool - if spec[0] == ':' { - sameFrontend = true - spec = spec[1:] - } - port, err := strconv.ParseUint(spec, 10, 16) - if err != nil { - return nil, err - } - nat.Backend = int(port) - if sameFrontend { - nat.Frontend = nat.Backend + + if strings.Contains(spec, ":") { + specParts := strings.Split(spec, ":") + if len(specParts) != 2 { + return nil, fmt.Errorf("Invalid port format.") + } + // If spec starts with ':', external and internal ports must be the same. + // This might fail if the requested external port is not available. + var sameFrontend bool + if len(specParts[0]) == 0 { + sameFrontend = true + } else { + front, err := strconv.ParseUint(specParts[0], 10, 16) + if err != nil { + return nil, err + } + nat.Frontend = int(front) + } + back, err := strconv.ParseUint(specParts[1], 10, 16) + if err != nil { + return nil, err + } + nat.Backend = int(back) + if sameFrontend { + nat.Frontend = nat.Backend + } + } else { + port, err := strconv.ParseUint(spec, 10, 16) + if err != nil { + return nil, err + } + nat.Backend = int(port) } nat.Proto = "tcp" return &nat, nil diff --git a/network_test.go b/network_test.go index df19a73d74..8e56c04ac2 100644 --- a/network_test.go +++ b/network_test.go @@ -18,6 +18,32 @@ func TestIptables(t *testing.T) { } } +func TestParseNat(t *testing.T) { + if nat, err := parseNat("4500"); err == nil { + if nat.Frontend != 0 || nat.Backend != 4500 { + t.Errorf("-p 4500 should produce 0->4500, got %d->%d", nat.Frontend, nat.Backend) + } + } else { + t.Fatal(err) + } + + if nat, err := parseNat(":4501"); err == nil { + if nat.Frontend != 4501 || nat.Backend != 4501 { + t.Errorf("-p :4501 should produce 4501->4501, got %d->%d", nat.Frontend, nat.Backend) + } + } else { + t.Fatal(err) + } + + if nat, err := parseNat("4502:4503"); err == nil { + if nat.Frontend != 4502 || nat.Backend != 4503 { + t.Errorf("-p 4502:4503 should produce 4502->4503, got %d->%d", nat.Frontend, nat.Backend) + } + } else { + t.Fatal(err) + } +} + func TestPortAllocation(t *testing.T) { allocator, err := newPortAllocator() if err != nil {