aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpod/oci.go58
-rw-r--r--test/e2e/run_networking_test.go4
2 files changed, 62 insertions, 0 deletions
diff --git a/libpod/oci.go b/libpod/oci.go
index 3eaf159e7..0483c0d53 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
+ "net"
"os"
"os/exec"
"path/filepath"
@@ -15,6 +16,7 @@ import (
"time"
"github.com/coreos/go-systemd/activation"
+ "github.com/cri-o/ocicni/pkg/ocicni"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
"github.com/opencontainers/selinux/go-selinux/label"
@@ -177,6 +179,51 @@ func waitPidsStop(pids []int, timeout time.Duration) error {
}
}
+func bindPorts(ports []ocicni.PortMapping) ([]*os.File, error) {
+ var files []*os.File
+ for _, i := range ports {
+ switch i.Protocol {
+ case "udp":
+ addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", i.HostIP, i.HostPort))
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot resolve the UDP address")
+ }
+
+ server, err := net.ListenUDP("udp", addr)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot listen on the UDP port")
+ }
+ f, err := server.File()
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot get file for UDP socket")
+ }
+ files = append(files, f)
+ break
+
+ case "tcp":
+ addr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", i.HostIP, i.HostPort))
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot resolve the TCP address")
+ }
+
+ server, err := net.ListenTCP("tcp4", addr)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot listen on the TCP port")
+ }
+ f, err := server.File()
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot get file for TCP socket")
+ }
+ files = append(files, f)
+ break
+ default:
+ return nil, fmt.Errorf("unknown protocol %s", i.Protocol)
+
+ }
+ }
+ return files, nil
+}
+
func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string) (err error) {
var stderrBuf bytes.Buffer
@@ -259,6 +306,17 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string) (er
cmd.Env = append(r.conmonEnv, fmt.Sprintf("_OCI_SYNCPIPE=%d", 3))
cmd.Env = append(cmd.Env, fmt.Sprintf("_OCI_STARTPIPE=%d", 4))
cmd.Env = append(cmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir))
+
+ ports, err := bindPorts(ctr.config.PortMappings)
+ if err != nil {
+ return err
+ }
+
+ // Leak the port we bound in the conmon process. These fd's won't be used
+ // by the container and conmon will keep the ports busy so that another
+ // process cannot use them.
+ cmd.ExtraFiles = append(cmd.ExtraFiles, ports...)
+
if notify, ok := os.LookupEnv("NOTIFY_SOCKET"); ok {
cmd.Env = append(cmd.Env, fmt.Sprintf("NOTIFY_SOCKET=%s", notify))
}
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index 9a2858ca1..e1c1608b9 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -65,6 +65,10 @@ var _ = Describe("Podman rmi", func() {
results.Wait(30)
Expect(results.ExitCode()).To(Equal(0))
Expect(results.OutputToString()).To(ContainSubstring("8000"))
+
+ ncBusy := podmanTest.SystemExec("nc", []string{"-l", "-p", "80"})
+ ncBusy.Wait(10)
+ Expect(ncBusy.ExitCode()).ToNot(Equal(0))
})
It("podman run network expose ports in image metadata", func() {