full diff: https://github.com/docker/libnetwork/compare/48f846327bbe6a0dce0c556e8dc9f5bb939d5c16...9ff9b57c344df5cd47443ad9e65702ec85c5aeb0
- docker/libnetwork#2368 (windows) Pick a random host port if the user does not specify a host port
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -3,7 +3,7 @@ |
| 3 | 3 |
# LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When |
| 4 | 4 |
# updating the binary version, consider updating github.com/docker/libnetwork |
| 5 | 5 |
# in vendor.conf accordingly |
| 6 |
-LIBNETWORK_COMMIT=48f846327bbe6a0dce0c556e8dc9f5bb939d5c16 |
|
| 6 |
+LIBNETWORK_COMMIT=9ff9b57c344df5cd47443ad9e65702ec85c5aeb0 |
|
| 7 | 7 |
|
| 8 | 8 |
install_proxy() {
|
| 9 | 9 |
case "$1" in |
| ... | ... |
@@ -39,7 +39,7 @@ github.com/gofrs/flock 7f43ea2e6a643ad441fc12d0ecc0 |
| 39 | 39 |
# libnetwork |
| 40 | 40 |
|
| 41 | 41 |
# When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy.installer accordingly |
| 42 |
-github.com/docker/libnetwork 48f846327bbe6a0dce0c556e8dc9f5bb939d5c16 |
|
| 42 |
+github.com/docker/libnetwork 9ff9b57c344df5cd47443ad9e65702ec85c5aeb0 |
|
| 43 | 43 |
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 |
| 44 | 44 |
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 45 | 45 |
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| ... | ... |
@@ -171,7 +171,19 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 171 | 171 |
return err |
| 172 | 172 |
} |
| 173 | 173 |
|
| 174 |
- pbPolicy, err := windows.ConvertPortBindings(epConnectivity.PortBindings) |
|
| 174 |
+ ep.portMapping = epConnectivity.PortBindings |
|
| 175 |
+ ep.portMapping, err = windows.AllocatePorts(n.portMapper, ep.portMapping, ep.addr.IP) |
|
| 176 |
+ if err != nil {
|
|
| 177 |
+ return err |
|
| 178 |
+ } |
|
| 179 |
+ |
|
| 180 |
+ defer func() {
|
|
| 181 |
+ if err != nil {
|
|
| 182 |
+ windows.ReleasePorts(n.portMapper, ep.portMapping) |
|
| 183 |
+ } |
|
| 184 |
+ }() |
|
| 185 |
+ |
|
| 186 |
+ pbPolicy, err := windows.ConvertPortBindings(ep.portMapping) |
|
| 175 | 187 |
if err != nil {
|
| 176 | 188 |
return err |
| 177 | 189 |
} |
| ... | ... |
@@ -229,6 +241,8 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
|
| 229 | 229 |
return fmt.Errorf("endpoint id %q not found", eid)
|
| 230 | 230 |
} |
| 231 | 231 |
|
| 232 |
+ windows.ReleasePorts(n.portMapper, ep.portMapping) |
|
| 233 |
+ |
|
| 232 | 234 |
n.deleteEndpoint(eid) |
| 233 | 235 |
|
| 234 | 236 |
_, err := endpointRequest("DELETE", ep.profileID, "")
|
| ... | ... |
@@ -11,6 +11,7 @@ import ( |
| 11 | 11 |
"github.com/Microsoft/hcsshim" |
| 12 | 12 |
"github.com/docker/libnetwork/driverapi" |
| 13 | 13 |
"github.com/docker/libnetwork/netlabel" |
| 14 |
+ "github.com/docker/libnetwork/portmapper" |
|
| 14 | 15 |
"github.com/docker/libnetwork/types" |
| 15 | 16 |
"github.com/sirupsen/logrus" |
| 16 | 17 |
) |
| ... | ... |
@@ -46,6 +47,7 @@ type network struct {
|
| 46 | 46 |
initErr error |
| 47 | 47 |
subnets []*subnet |
| 48 | 48 |
secure bool |
| 49 |
+ portMapper *portmapper.PortMapper |
|
| 49 | 50 |
sync.Mutex |
| 50 | 51 |
} |
| 51 | 52 |
|
| ... | ... |
@@ -89,10 +91,11 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
| 89 | 89 |
} |
| 90 | 90 |
|
| 91 | 91 |
n := &network{
|
| 92 |
- id: id, |
|
| 93 |
- driver: d, |
|
| 94 |
- endpoints: endpointTable{},
|
|
| 95 |
- subnets: []*subnet{},
|
|
| 92 |
+ id: id, |
|
| 93 |
+ driver: d, |
|
| 94 |
+ endpoints: endpointTable{},
|
|
| 95 |
+ subnets: []*subnet{},
|
|
| 96 |
+ portMapper: portmapper.New(""),
|
|
| 96 | 97 |
} |
| 97 | 98 |
|
| 98 | 99 |
genData, ok := option[netlabel.GenericData].(map[string]string) |
| 99 | 100 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,125 @@ |
| 0 |
+// +build windows |
|
| 1 |
+ |
|
| 2 |
+package windows |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "bytes" |
|
| 6 |
+ "errors" |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "net" |
|
| 9 |
+ |
|
| 10 |
+ "github.com/docker/libnetwork/portmapper" |
|
| 11 |
+ "github.com/docker/libnetwork/types" |
|
| 12 |
+ "github.com/ishidawataru/sctp" |
|
| 13 |
+ "github.com/sirupsen/logrus" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+const ( |
|
| 17 |
+ maxAllocatePortAttempts = 10 |
|
| 18 |
+) |
|
| 19 |
+ |
|
| 20 |
+// ErrUnsupportedAddressType is returned when the specified address type is not supported. |
|
| 21 |
+type ErrUnsupportedAddressType string |
|
| 22 |
+ |
|
| 23 |
+func (uat ErrUnsupportedAddressType) Error() string {
|
|
| 24 |
+ return fmt.Sprintf("unsupported address type: %s", string(uat))
|
|
| 25 |
+} |
|
| 26 |
+ |
|
| 27 |
+// AllocatePorts allocates ports specified in bindings from the portMapper |
|
| 28 |
+func AllocatePorts(portMapper *portmapper.PortMapper, bindings []types.PortBinding, containerIP net.IP) ([]types.PortBinding, error) {
|
|
| 29 |
+ bs := make([]types.PortBinding, 0, len(bindings)) |
|
| 30 |
+ for _, c := range bindings {
|
|
| 31 |
+ b := c.GetCopy() |
|
| 32 |
+ if err := allocatePort(portMapper, &b, containerIP); err != nil {
|
|
| 33 |
+ // On allocation failure, release previously allocated ports. On cleanup error, just log a warning message |
|
| 34 |
+ if cuErr := ReleasePorts(portMapper, bs); cuErr != nil {
|
|
| 35 |
+ logrus.Warnf("Upon allocation failure for %v, failed to clear previously allocated port bindings: %v", b, cuErr)
|
|
| 36 |
+ } |
|
| 37 |
+ return nil, err |
|
| 38 |
+ } |
|
| 39 |
+ bs = append(bs, b) |
|
| 40 |
+ } |
|
| 41 |
+ return bs, nil |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+func allocatePort(portMapper *portmapper.PortMapper, bnd *types.PortBinding, containerIP net.IP) error {
|
|
| 45 |
+ var ( |
|
| 46 |
+ host net.Addr |
|
| 47 |
+ err error |
|
| 48 |
+ ) |
|
| 49 |
+ |
|
| 50 |
+ // Store the container interface address in the operational binding |
|
| 51 |
+ bnd.IP = containerIP |
|
| 52 |
+ |
|
| 53 |
+ // Adjust HostPortEnd if this is not a range. |
|
| 54 |
+ if bnd.HostPortEnd == 0 {
|
|
| 55 |
+ bnd.HostPortEnd = bnd.HostPort |
|
| 56 |
+ } |
|
| 57 |
+ |
|
| 58 |
+ // Construct the container side transport address |
|
| 59 |
+ container, err := bnd.ContainerAddr() |
|
| 60 |
+ if err != nil {
|
|
| 61 |
+ return err |
|
| 62 |
+ } |
|
| 63 |
+ |
|
| 64 |
+ // Try up to maxAllocatePortAttempts times to get a port that's not already allocated. |
|
| 65 |
+ for i := 0; i < maxAllocatePortAttempts; i++ {
|
|
| 66 |
+ if host, err = portMapper.MapRange(container, bnd.HostIP, int(bnd.HostPort), int(bnd.HostPortEnd), false); err == nil {
|
|
| 67 |
+ break |
|
| 68 |
+ } |
|
| 69 |
+ // There is no point in immediately retrying to map an explicitly chosen port. |
|
| 70 |
+ if bnd.HostPort != 0 {
|
|
| 71 |
+ logrus.Warnf("Failed to allocate and map port %d-%d: %s", bnd.HostPort, bnd.HostPortEnd, err)
|
|
| 72 |
+ break |
|
| 73 |
+ } |
|
| 74 |
+ logrus.Warnf("Failed to allocate and map port: %s, retry: %d", err, i+1)
|
|
| 75 |
+ } |
|
| 76 |
+ if err != nil {
|
|
| 77 |
+ return err |
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ // Save the host port (regardless it was or not specified in the binding) |
|
| 81 |
+ switch netAddr := host.(type) {
|
|
| 82 |
+ case *net.TCPAddr: |
|
| 83 |
+ bnd.HostPort = uint16(host.(*net.TCPAddr).Port) |
|
| 84 |
+ break |
|
| 85 |
+ case *net.UDPAddr: |
|
| 86 |
+ bnd.HostPort = uint16(host.(*net.UDPAddr).Port) |
|
| 87 |
+ break |
|
| 88 |
+ case *sctp.SCTPAddr: |
|
| 89 |
+ bnd.HostPort = uint16(host.(*sctp.SCTPAddr).Port) |
|
| 90 |
+ break |
|
| 91 |
+ default: |
|
| 92 |
+ // For completeness |
|
| 93 |
+ return ErrUnsupportedAddressType(fmt.Sprintf("%T", netAddr))
|
|
| 94 |
+ } |
|
| 95 |
+ //Windows does not support host port ranges. |
|
| 96 |
+ bnd.HostPortEnd = bnd.HostPort |
|
| 97 |
+ return nil |
|
| 98 |
+} |
|
| 99 |
+ |
|
| 100 |
+// ReleasePorts releases ports specified in bindings from the portMapper |
|
| 101 |
+func ReleasePorts(portMapper *portmapper.PortMapper, bindings []types.PortBinding) error {
|
|
| 102 |
+ var errorBuf bytes.Buffer |
|
| 103 |
+ |
|
| 104 |
+ // Attempt to release all port bindings, do not stop on failure |
|
| 105 |
+ for _, m := range bindings {
|
|
| 106 |
+ if err := releasePort(portMapper, m); err != nil {
|
|
| 107 |
+ errorBuf.WriteString(fmt.Sprintf("\ncould not release %v because of %v", m, err))
|
|
| 108 |
+ } |
|
| 109 |
+ } |
|
| 110 |
+ |
|
| 111 |
+ if errorBuf.Len() != 0 {
|
|
| 112 |
+ return errors.New(errorBuf.String()) |
|
| 113 |
+ } |
|
| 114 |
+ return nil |
|
| 115 |
+} |
|
| 116 |
+ |
|
| 117 |
+func releasePort(portMapper *portmapper.PortMapper, bnd types.PortBinding) error {
|
|
| 118 |
+ // Construct the host side transport address |
|
| 119 |
+ host, err := bnd.HostAddr() |
|
| 120 |
+ if err != nil {
|
|
| 121 |
+ return err |
|
| 122 |
+ } |
|
| 123 |
+ return portMapper.Unmap(host) |
|
| 124 |
+} |
| ... | ... |
@@ -25,6 +25,7 @@ import ( |
| 25 | 25 |
"github.com/docker/libnetwork/discoverapi" |
| 26 | 26 |
"github.com/docker/libnetwork/driverapi" |
| 27 | 27 |
"github.com/docker/libnetwork/netlabel" |
| 28 |
+ "github.com/docker/libnetwork/portmapper" |
|
| 28 | 29 |
"github.com/docker/libnetwork/types" |
| 29 | 30 |
"github.com/sirupsen/logrus" |
| 30 | 31 |
) |
| ... | ... |
@@ -88,11 +89,12 @@ type hnsEndpoint struct {
|
| 88 | 88 |
} |
| 89 | 89 |
|
| 90 | 90 |
type hnsNetwork struct {
|
| 91 |
- id string |
|
| 92 |
- created bool |
|
| 93 |
- config *networkConfiguration |
|
| 94 |
- endpoints map[string]*hnsEndpoint // key: endpoint id |
|
| 95 |
- driver *driver // The network's driver |
|
| 91 |
+ id string |
|
| 92 |
+ created bool |
|
| 93 |
+ config *networkConfiguration |
|
| 94 |
+ endpoints map[string]*hnsEndpoint // key: endpoint id |
|
| 95 |
+ driver *driver // The network's driver |
|
| 96 |
+ portMapper *portmapper.PortMapper |
|
| 96 | 97 |
sync.Mutex |
| 97 | 98 |
} |
| 98 | 99 |
|
| ... | ... |
@@ -252,10 +254,11 @@ func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (s |
| 252 | 252 |
|
| 253 | 253 |
func (d *driver) createNetwork(config *networkConfiguration) error {
|
| 254 | 254 |
network := &hnsNetwork{
|
| 255 |
- id: config.ID, |
|
| 256 |
- endpoints: make(map[string]*hnsEndpoint), |
|
| 257 |
- config: config, |
|
| 258 |
- driver: d, |
|
| 255 |
+ id: config.ID, |
|
| 256 |
+ endpoints: make(map[string]*hnsEndpoint), |
|
| 257 |
+ config: config, |
|
| 258 |
+ driver: d, |
|
| 259 |
+ portMapper: portmapper.New(""),
|
|
| 259 | 260 |
} |
| 260 | 261 |
|
| 261 | 262 |
d.Lock() |
| ... | ... |
@@ -610,7 +613,27 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 610 | 610 |
endpointStruct.MacAddress = strings.Replace(macAddress.String(), ":", "-", -1) |
| 611 | 611 |
} |
| 612 | 612 |
|
| 613 |
- endpointStruct.Policies, err = ConvertPortBindings(epConnectivity.PortBindings) |
|
| 613 |
+ portMapping := epConnectivity.PortBindings |
|
| 614 |
+ |
|
| 615 |
+ if n.config.Type == "l2bridge" || n.config.Type == "l2tunnel" {
|
|
| 616 |
+ ip := net.IPv4(0, 0, 0, 0) |
|
| 617 |
+ if ifInfo.Address() != nil {
|
|
| 618 |
+ ip = ifInfo.Address().IP |
|
| 619 |
+ } |
|
| 620 |
+ |
|
| 621 |
+ portMapping, err = AllocatePorts(n.portMapper, portMapping, ip) |
|
| 622 |
+ if err != nil {
|
|
| 623 |
+ return err |
|
| 624 |
+ } |
|
| 625 |
+ |
|
| 626 |
+ defer func() {
|
|
| 627 |
+ if err != nil {
|
|
| 628 |
+ ReleasePorts(n.portMapper, portMapping) |
|
| 629 |
+ } |
|
| 630 |
+ }() |
|
| 631 |
+ } |
|
| 632 |
+ |
|
| 633 |
+ endpointStruct.Policies, err = ConvertPortBindings(portMapping) |
|
| 614 | 634 |
if err != nil {
|
| 615 | 635 |
return err |
| 616 | 636 |
} |
| ... | ... |
@@ -721,6 +744,10 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
|
| 721 | 721 |
return err |
| 722 | 722 |
} |
| 723 | 723 |
|
| 724 |
+ if n.config.Type == "l2bridge" || n.config.Type == "l2tunnel" {
|
|
| 725 |
+ ReleasePorts(n.portMapper, ep.portMapping) |
|
| 726 |
+ } |
|
| 727 |
+ |
|
| 724 | 728 |
n.Lock() |
| 725 | 729 |
delete(n.endpoints, eid) |
| 726 | 730 |
n.Unlock() |
| ... | ... |
@@ -4,9 +4,7 @@ import ( |
| 4 | 4 |
"errors" |
| 5 | 5 |
"fmt" |
| 6 | 6 |
"net" |
| 7 |
- "sync" |
|
| 8 | 7 |
|
| 9 |
- "github.com/docker/libnetwork/iptables" |
|
| 10 | 8 |
"github.com/docker/libnetwork/portallocator" |
| 11 | 9 |
"github.com/ishidawataru/sctp" |
| 12 | 10 |
"github.com/sirupsen/logrus" |
| ... | ... |
@@ -32,20 +30,6 @@ var ( |
| 32 | 32 |
ErrSCTPAddrNoIP = errors.New("sctp address does not contain any IP address")
|
| 33 | 33 |
) |
| 34 | 34 |
|
| 35 |
-// PortMapper manages the network address translation |
|
| 36 |
-type PortMapper struct {
|
|
| 37 |
- chain *iptables.ChainInfo |
|
| 38 |
- bridgeName string |
|
| 39 |
- |
|
| 40 |
- // udp:ip:port |
|
| 41 |
- currentMappings map[string]*mapping |
|
| 42 |
- lock sync.Mutex |
|
| 43 |
- |
|
| 44 |
- proxyPath string |
|
| 45 |
- |
|
| 46 |
- Allocator *portallocator.PortAllocator |
|
| 47 |
-} |
|
| 48 |
- |
|
| 49 | 35 |
// New returns a new instance of PortMapper |
| 50 | 36 |
func New(proxyPath string) *PortMapper {
|
| 51 | 37 |
return NewWithPortAllocator(portallocator.Get(), proxyPath) |
| ... | ... |
@@ -60,12 +44,6 @@ func NewWithPortAllocator(allocator *portallocator.PortAllocator, proxyPath stri |
| 60 | 60 |
} |
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 |
-// SetIptablesChain sets the specified chain into portmapper |
|
| 64 |
-func (pm *PortMapper) SetIptablesChain(c *iptables.ChainInfo, bridgeName string) {
|
|
| 65 |
- pm.chain = c |
|
| 66 |
- pm.bridgeName = bridgeName |
|
| 67 |
-} |
|
| 68 |
- |
|
| 69 | 63 |
// Map maps the specified container transport address to the host's network address and transport port |
| 70 | 64 |
func (pm *PortMapper) Map(container net.Addr, hostIP net.IP, hostPort int, useProxy bool) (host net.Addr, err error) {
|
| 71 | 65 |
return pm.MapRange(container, hostIP, hostPort, hostPort, useProxy) |
| ... | ... |
@@ -174,7 +152,7 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, |
| 174 | 174 |
|
| 175 | 175 |
containerIP, containerPort := getIPAndPort(m.container) |
| 176 | 176 |
if hostIP.To4() != nil {
|
| 177 |
- if err := pm.forward(iptables.Append, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil {
|
|
| 177 |
+ if err := pm.AppendForwardingTableEntry(m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil {
|
|
| 178 | 178 |
return nil, err |
| 179 | 179 |
} |
| 180 | 180 |
} |
| ... | ... |
@@ -183,7 +161,7 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, |
| 183 | 183 |
// need to undo the iptables rules before we return |
| 184 | 184 |
m.userlandProxy.Stop() |
| 185 | 185 |
if hostIP.To4() != nil {
|
| 186 |
- pm.forward(iptables.Delete, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort) |
|
| 186 |
+ pm.DeleteForwardingTableEntry(m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort) |
|
| 187 | 187 |
if err := pm.Allocator.ReleasePort(hostIP, m.proto, allocatedHostPort); err != nil {
|
| 188 | 188 |
return err |
| 189 | 189 |
} |
| ... | ... |
@@ -222,7 +200,7 @@ func (pm *PortMapper) Unmap(host net.Addr) error {
|
| 222 | 222 |
|
| 223 | 223 |
containerIP, containerPort := getIPAndPort(data.container) |
| 224 | 224 |
hostIP, hostPort := getIPAndPort(data.host) |
| 225 |
- if err := pm.forward(iptables.Delete, data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil {
|
|
| 225 |
+ if err := pm.DeleteForwardingTableEntry(data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil {
|
|
| 226 | 226 |
logrus.Errorf("Error on iptables delete: %s", err)
|
| 227 | 227 |
} |
| 228 | 228 |
|
| ... | ... |
@@ -248,7 +226,7 @@ func (pm *PortMapper) ReMapAll() {
|
| 248 | 248 |
for _, data := range pm.currentMappings {
|
| 249 | 249 |
containerIP, containerPort := getIPAndPort(data.container) |
| 250 | 250 |
hostIP, hostPort := getIPAndPort(data.host) |
| 251 |
- if err := pm.forward(iptables.Append, data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil {
|
|
| 251 |
+ if err := pm.AppendForwardingTableEntry(data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil {
|
|
| 252 | 252 |
logrus.Errorf("Error on iptables add: %s", err)
|
| 253 | 253 |
} |
| 254 | 254 |
} |
| ... | ... |
@@ -285,10 +263,3 @@ func getIPAndPort(a net.Addr) (net.IP, int) {
|
| 285 | 285 |
} |
| 286 | 286 |
return nil, 0 |
| 287 | 287 |
} |
| 288 |
- |
|
| 289 |
-func (pm *PortMapper) forward(action iptables.Action, proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
|
|
| 290 |
- if pm.chain == nil {
|
|
| 291 |
- return nil |
|
| 292 |
- } |
|
| 293 |
- return pm.chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort, pm.bridgeName) |
|
| 294 |
-} |
| 295 | 288 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,46 @@ |
| 0 |
+package portmapper |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "net" |
|
| 4 |
+ "sync" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/docker/libnetwork/iptables" |
|
| 7 |
+ "github.com/docker/libnetwork/portallocator" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// PortMapper manages the network address translation |
|
| 11 |
+type PortMapper struct {
|
|
| 12 |
+ bridgeName string |
|
| 13 |
+ |
|
| 14 |
+ // udp:ip:port |
|
| 15 |
+ currentMappings map[string]*mapping |
|
| 16 |
+ lock sync.Mutex |
|
| 17 |
+ |
|
| 18 |
+ proxyPath string |
|
| 19 |
+ |
|
| 20 |
+ Allocator *portallocator.PortAllocator |
|
| 21 |
+ chain *iptables.ChainInfo |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+// SetIptablesChain sets the specified chain into portmapper |
|
| 25 |
+func (pm *PortMapper) SetIptablesChain(c *iptables.ChainInfo, bridgeName string) {
|
|
| 26 |
+ pm.chain = c |
|
| 27 |
+ pm.bridgeName = bridgeName |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+// AppendForwardingTableEntry adds a port mapping to the forwarding table |
|
| 31 |
+func (pm *PortMapper) AppendForwardingTableEntry(proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
|
|
| 32 |
+ return pm.forward(iptables.Append, proto, sourceIP, sourcePort, containerIP, containerPort) |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+// DeleteForwardingTableEntry removes a port mapping from the forwarding table |
|
| 36 |
+func (pm *PortMapper) DeleteForwardingTableEntry(proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
|
|
| 37 |
+ return pm.forward(iptables.Delete, proto, sourceIP, sourcePort, containerIP, containerPort) |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+func (pm *PortMapper) forward(action iptables.Action, proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
|
|
| 41 |
+ if pm.chain == nil {
|
|
| 42 |
+ return nil |
|
| 43 |
+ } |
|
| 44 |
+ return pm.chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort, pm.bridgeName) |
|
| 45 |
+} |
| 0 | 46 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,31 @@ |
| 0 |
+package portmapper |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "net" |
|
| 4 |
+ "sync" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/docker/libnetwork/portallocator" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+// PortMapper manages the network address translation |
|
| 10 |
+type PortMapper struct {
|
|
| 11 |
+ bridgeName string |
|
| 12 |
+ |
|
| 13 |
+ // udp:ip:port |
|
| 14 |
+ currentMappings map[string]*mapping |
|
| 15 |
+ lock sync.Mutex |
|
| 16 |
+ |
|
| 17 |
+ proxyPath string |
|
| 18 |
+ |
|
| 19 |
+ Allocator *portallocator.PortAllocator |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+// AppendForwardingTableEntry adds a port mapping to the forwarding table |
|
| 23 |
+func (pm *PortMapper) AppendForwardingTableEntry(proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
|
|
| 24 |
+ return nil |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 27 |
+// DeleteForwardingTableEntry removes a port mapping from the forwarding table |
|
| 28 |
+func (pm *PortMapper) DeleteForwardingTableEntry(proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
|
|
| 29 |
+ return nil |
|
| 30 |
+} |
| 0 | 31 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,10 @@ |
| 0 |
+package portmapper |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "errors" |
|
| 4 |
+ "net" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+func newProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int, proxyPath string) (userlandProxy, error) {
|
|
| 8 |
+ return nil, errors.New("proxy is unsupported on windows")
|
|
| 9 |
+} |