diff options
author | Paul Holzinger <pholzing@redhat.com> | 2022-03-24 15:35:16 +0100 |
---|---|---|
committer | Paul Holzinger <pholzing@redhat.com> | 2022-03-29 19:18:40 +0200 |
commit | eedaaf33cdbfd6adced57ac8493d679b3f729493 (patch) | |
tree | b550b0cf05d0c8a0d0fadbbd814aa91b46d8a3b2 /libpod | |
parent | 83d0729146dc4616e180c8d36ffd90de093b8617 (diff) | |
download | podman-eedaaf33cdbfd6adced57ac8493d679b3f729493.tar.gz podman-eedaaf33cdbfd6adced57ac8493d679b3f729493.tar.bz2 podman-eedaaf33cdbfd6adced57ac8493d679b3f729493.zip |
fix slirp4netns port forwarding with ranges
The slirp4netns port forwarder was not updated to make use of the new
port format. This results in a problem when port ranges are used since
it does not read the range field from the port.
Update the logic to iterate through all ports with the range and
protocols. Also added a system test for port ranges with slirp4netns,
rootlesskit and the bridge network mode.
Fixes #13643
Signed-off-by: Paul Holzinger <pholzing@redhat.com>
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/networking_slirp4netns.go | 107 |
1 files changed, 60 insertions, 47 deletions
diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go index 3f6c4bef2..3f2842d4c 100644 --- a/libpod/networking_slirp4netns.go +++ b/libpod/networking_slirp4netns.go @@ -614,60 +614,73 @@ func (r *Runtime) setupRootlessPortMappingViaSlirp(ctr *Container, cmd *exec.Cmd // for each port we want to add we need to open a connection to the slirp4netns control socket // and send the add_hostfwd command. - for _, i := range ctr.convertPortMappings() { - conn, err := net.Dial("unix", apiSocket) - if err != nil { - return errors.Wrapf(err, "cannot open connection to %s", apiSocket) - } - defer func() { - if err := conn.Close(); err != nil { - logrus.Errorf("Unable to close connection: %q", err) + for _, port := range ctr.convertPortMappings() { + protocols := strings.Split(port.Protocol, ",") + for _, protocol := range protocols { + hostIP := port.HostIP + if hostIP == "" { + hostIP = "0.0.0.0" + } + for i := uint16(0); i < port.Range; i++ { + if err := openSlirp4netnsPort(apiSocket, protocol, hostIP, port.HostPort+i, port.ContainerPort+i); err != nil { + return err + } } - }() - hostIP := i.HostIP - if hostIP == "" { - hostIP = "0.0.0.0" - } - apiCmd := slirp4netnsCmd{ - Execute: "add_hostfwd", - Args: slirp4netnsCmdArg{ - Proto: i.Protocol, - HostAddr: hostIP, - HostPort: i.HostPort, - GuestPort: i.ContainerPort, - }, - } - // create the JSON payload and send it. Mark the end of request shutting down writes - // to the socket, as requested by slirp4netns. - data, err := json.Marshal(&apiCmd) - if err != nil { - return errors.Wrapf(err, "cannot marshal JSON for slirp4netns") - } - if _, err := conn.Write([]byte(fmt.Sprintf("%s\n", data))); err != nil { - return errors.Wrapf(err, "cannot write to control socket %s", apiSocket) - } - if err := conn.(*net.UnixConn).CloseWrite(); err != nil { - return errors.Wrapf(err, "cannot shutdown the socket %s", apiSocket) - } - buf := make([]byte, 2048) - readLength, err := conn.Read(buf) - if err != nil { - return errors.Wrapf(err, "cannot read from control socket %s", apiSocket) - } - // if there is no 'error' key in the received JSON data, then the operation was - // successful. - var y map[string]interface{} - if err := json.Unmarshal(buf[0:readLength], &y); err != nil { - return errors.Wrapf(err, "error parsing error status from slirp4netns") - } - if e, found := y["error"]; found { - return errors.Errorf("from slirp4netns while setting up port redirection: %v", e) } } logrus.Debug("slirp4netns port-forwarding setup via add_hostfwd is ready") return nil } +// openSlirp4netnsPort sends the slirp4netns pai quey to the given socket +func openSlirp4netnsPort(apiSocket, proto, hostip string, hostport, guestport uint16) error { + conn, err := net.Dial("unix", apiSocket) + if err != nil { + return errors.Wrapf(err, "cannot open connection to %s", apiSocket) + } + defer func() { + if err := conn.Close(); err != nil { + logrus.Errorf("Unable to close slirp4netns connection: %q", err) + } + }() + apiCmd := slirp4netnsCmd{ + Execute: "add_hostfwd", + Args: slirp4netnsCmdArg{ + Proto: proto, + HostAddr: hostip, + HostPort: hostport, + GuestPort: guestport, + }, + } + // create the JSON payload and send it. Mark the end of request shutting down writes + // to the socket, as requested by slirp4netns. + data, err := json.Marshal(&apiCmd) + if err != nil { + return errors.Wrapf(err, "cannot marshal JSON for slirp4netns") + } + if _, err := conn.Write([]byte(fmt.Sprintf("%s\n", data))); err != nil { + return errors.Wrapf(err, "cannot write to control socket %s", apiSocket) + } + if err := conn.(*net.UnixConn).CloseWrite(); err != nil { + return errors.Wrapf(err, "cannot shutdown the socket %s", apiSocket) + } + buf := make([]byte, 2048) + readLength, err := conn.Read(buf) + if err != nil { + return errors.Wrapf(err, "cannot read from control socket %s", apiSocket) + } + // if there is no 'error' key in the received JSON data, then the operation was + // successful. + var y map[string]interface{} + if err := json.Unmarshal(buf[0:readLength], &y); err != nil { + return errors.Wrapf(err, "error parsing error status from slirp4netns") + } + if e, found := y["error"]; found { + return errors.Errorf("from slirp4netns while setting up port redirection: %v", e) + } + return nil +} + func getRootlessPortChildIP(c *Container, netStatus map[string]types.StatusBlock) string { if c.config.NetMode.IsSlirp4netns() { slirp4netnsIP, err := GetSlirp4netnsIP(c.slirp4netnsSubnet) |