// Release: Network cleanup - release all resources func (iface *NetworkInterface) Release() { if iface.disabled { return } for _, nat := range iface.extPorts { hostPort, err := parsePort(nat.Binding.HostPort) if err != nil { log.Printf("Unable to get host port: %s", err) continue } ip := net.ParseIP(nat.Binding.HostIp) utils.Debugf("Unmaping %s/%s:%s", nat.Port.Proto, ip.String(), nat.Binding.HostPort) var host net.Addr if nat.Port.Proto() == "tcp" { host = &net.TCPAddr{IP: ip, Port: hostPort} } else { host = &net.UDPAddr{IP: ip, Port: hostPort} } if err := portmapper.Unmap(host); err != nil { log.Printf("Unable to unmap port %s: %s", nat, err) } if err := portallocator.ReleasePort(ip, nat.Port.Proto(), hostPort); err != nil { log.Printf("Unable to release port %s", nat) } } if err := ipallocator.ReleaseIP(iface.manager.bridgeNetwork, &iface.IPNet.IP); err != nil { log.Printf("Unable to release ip %s\n", err) } }
// Allocate an external port and map it to the interface func AllocatePort(job *engine.Job) engine.Status { var ( err error ip = defaultBindingIP id = job.Args[0] hostIP = job.Getenv("HostIP") hostPort = job.GetenvInt("HostPort") containerPort = job.GetenvInt("ContainerPort") proto = job.Getenv("Proto") network = currentInterfaces[id] ) if hostIP != "" { ip = net.ParseIP(hostIP) } // host ip, proto, and host port hostPort, err = portallocator.RequestPort(ip, proto, hostPort) if err != nil { job.Error(err) return engine.StatusErr } var ( container net.Addr host net.Addr ) if proto == "tcp" { host = &net.TCPAddr{IP: ip, Port: hostPort} container = &net.TCPAddr{IP: network.IP, Port: containerPort} } else { host = &net.UDPAddr{IP: ip, Port: hostPort} container = &net.UDPAddr{IP: network.IP, Port: containerPort} } if err := portmapper.Map(container, ip, hostPort); err != nil { portallocator.ReleasePort(ip, proto, hostPort) job.Error(err) return engine.StatusErr } network.PortMappings = append(network.PortMappings, host) out := engine.Env{} out.Set("HostIP", ip.String()) out.SetInt("HostPort", hostPort) if _, err := out.WriteTo(job.Stdout); err != nil { job.Error(err) return engine.StatusErr } return engine.StatusOK }
// Allocate an external port and map it to the interface func (iface *NetworkInterface) AllocatePort(port Port, binding PortBinding) (*Nat, error) { if iface.disabled { return nil, fmt.Errorf("Trying to allocate port for interface %v, which is disabled", iface) // FIXME } ip := iface.manager.defaultBindingIP if binding.HostIp != "" { ip = net.ParseIP(binding.HostIp) } else { binding.HostIp = ip.String() } nat := &Nat{ Port: port, Binding: binding, } containerPort, err := parsePort(port.Port()) if err != nil { return nil, err } hostPort, _ := parsePort(nat.Binding.HostPort) extPort, err := portallocator.RequestPort(ip, nat.Port.Proto(), hostPort) if err != nil { return nil, err } var backend net.Addr if nat.Port.Proto() == "tcp" { backend = &net.TCPAddr{IP: iface.IPNet.IP, Port: containerPort} } else { backend = &net.UDPAddr{IP: iface.IPNet.IP, Port: containerPort} } if err := portmapper.Map(backend, ip, extPort); err != nil { portallocator.ReleasePort(ip, nat.Port.Proto(), extPort) return nil, err } nat.Binding.HostPort = strconv.Itoa(extPort) iface.extPorts = append(iface.extPorts, nat) return nat, nil }
// release an interface for a select ip func Release(job *engine.Job) engine.Status { var ( id = job.Args[0] containerInterface = currentInterfaces[id] ip net.IP port int proto string ) if containerInterface == nil { return job.Errorf("No network information to release for %s", id) } for _, nat := range containerInterface.PortMappings { if err := portmapper.Unmap(nat); err != nil { log.Printf("Unable to unmap port %s: %s", nat, err) } // this is host mappings switch a := nat.(type) { case *net.TCPAddr: proto = "tcp" ip = a.IP port = a.Port case *net.UDPAddr: proto = "udp" ip = a.IP port = a.Port } if err := portallocator.ReleasePort(ip, proto, port); err != nil { log.Printf("Unable to release port %s", nat) } } if err := ipallocator.ReleaseIP(bridgeNetwork, &containerInterface.IP); err != nil { log.Printf("Unable to release ip %s\n", err) } return engine.StatusOK }