func Unmap(host net.Addr) error { lock.Lock() defer lock.Unlock() key := getKey(host) data, exists := currentMappings[key] if !exists { return ErrPortNotMapped } data.userlandProxy.Close() delete(currentMappings, key) containerIP, containerPort := getIPAndPort(data.container) hostIP, hostPort := getIPAndPort(data.host) if err := forward(iptables.Delete, data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil { return err } switch a := host.(type) { case *net.TCPAddr: if err := portallocator.ReleasePort(a.IP, "tcp", a.Port); err != nil { return err } case *net.UDPAddr: if err := portallocator.ReleasePort(a.IP, "udp", a.Port); err != nil { return err } } return nil }
func Map(container net.Addr, hostIP net.IP, hostPort int) (net.Addr, error) { lock.Lock() defer lock.Unlock() var ( m *mapping err error proto string allocatedHostPort int ) // release the port on any error during return. defer func() { if err != nil { portallocator.ReleasePort(hostIP, proto, allocatedHostPort) } }() switch container.(type) { case *net.TCPAddr: proto = "tcp" if allocatedHostPort, err = portallocator.RequestPort(hostIP, proto, hostPort); err != nil { return nil, err } m = &mapping{ proto: proto, host: &net.TCPAddr{IP: hostIP, Port: allocatedHostPort}, container: container, } case *net.UDPAddr: proto = "udp" if allocatedHostPort, err = portallocator.RequestPort(hostIP, proto, hostPort); err != nil { return nil, err } m = &mapping{ proto: proto, host: &net.UDPAddr{IP: hostIP, Port: allocatedHostPort}, container: container, } default: err = ErrUnknownBackendAddressType return nil, err } key := getKey(m.host) if _, exists := currentMappings[key]; exists { err = ErrPortMappedForIP return nil, err } containerIP, containerPort := getIPAndPort(m.container) if err := forward(iptables.Add, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil { return nil, err } p, err := newProxy(m.host, m.container) if err != nil { // need to undo the iptables rules before we return forward(iptables.Delete, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort) return nil, err } m.userlandProxy = p currentMappings[key] = m go p.Run() return m.host, nil }