summaryrefslogtreecommitdiff
path: root/libpod/networking_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/networking_linux.go')
-rw-r--r--libpod/networking_linux.go100
1 files changed, 57 insertions, 43 deletions
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index fc91155fa..314a74427 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -4,6 +4,7 @@ package libpod
import (
"crypto/rand"
+ "crypto/sha1"
"fmt"
"io/ioutil"
"net"
@@ -87,12 +88,28 @@ func (c *Container) GetNetworkAliases(netName string) ([]string, error) {
return aliases, nil
}
+// convertPortMappings will remove the HostIP part from the ports when running inside podman machine.
+// This is need because a HostIP of 127.0.0.1 would now allow the gvproxy forwarder to reach to open ports.
+// For machine the HostIP must only be used by gvproxy and never in the VM.
+func (c *Container) convertPortMappings() []types.PortMapping {
+ if !c.runtime.config.Engine.MachineEnabled || len(c.config.PortMappings) == 0 {
+ return c.config.PortMappings
+ }
+ // if we run in a machine VM we have to ignore the host IP part
+ newPorts := make([]types.PortMapping, 0, len(c.config.PortMappings))
+ for _, port := range c.config.PortMappings {
+ port.HostIP = ""
+ newPorts = append(newPorts, port)
+ }
+ return newPorts
+}
+
func (c *Container) getNetworkOptions() (types.NetworkOptions, error) {
opts := types.NetworkOptions{
ContainerID: c.config.ID,
ContainerName: getCNIPodName(c),
}
- opts.PortMappings = c.config.PortMappings
+ opts.PortMappings = c.convertPortMappings()
networks, _, err := c.networks()
if err != nil {
return opts, err
@@ -384,10 +401,7 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) {
return nil, nil
}
var rootlessNetNS *RootlessNetNS
- runDir, err := util.GetRuntimeDir()
- if err != nil {
- return nil, err
- }
+ runDir := r.config.Engine.TmpDir
lfile := filepath.Join(runDir, "rootless-netns.lock")
lock, err := lockfile.GetLockfile(lfile)
@@ -413,7 +427,15 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) {
if err != nil {
return nil, err
}
- path := filepath.Join(nsDir, rootlessNetNsName)
+
+ // create a hash from the static dir
+ // the cleanup will check if there are running containers
+ // if you run a several libpod instances with different root/runroot directories this check will fail
+ // we want one netns for each libpod static dir so we use the hash to prevent name collisions
+ hash := sha1.Sum([]byte(r.config.Engine.StaticDir))
+ netnsName := fmt.Sprintf("%s-%x", rootlessNetNsName, hash[:10])
+
+ path := filepath.Join(nsDir, netnsName)
ns, err := ns.GetNS(path)
if err != nil {
if !new {
@@ -421,8 +443,8 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) {
return nil, errors.Wrap(err, "error getting rootless network namespace")
}
// create a new namespace
- logrus.Debug("creating rootless network namespace")
- ns, err = netns.NewNSWithName(rootlessNetNsName)
+ logrus.Debugf("creating rootless network namespace with name %q", netnsName)
+ ns, err = netns.NewNSWithName(netnsName)
if err != nil {
return nil, errors.Wrap(err, "error creating rootless network namespace")
}
@@ -591,32 +613,9 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) {
return rootlessNetNS, nil
}
-// setPrimaryMachineIP is used for podman-machine and it sets
-// and environment variable with the IP address of the podman-machine
-// host.
-func setPrimaryMachineIP() error {
- // no connection is actually made here
- conn, err := net.Dial("udp", "8.8.8.8:80")
- if err != nil {
- return err
- }
- defer func() {
- if err := conn.Close(); err != nil {
- logrus.Error(err)
- }
- }()
- addr := conn.LocalAddr().(*net.UDPAddr)
- return os.Setenv("PODMAN_MACHINE_HOST", addr.IP.String())
-}
-
// setUpNetwork will set up the the networks, on error it will also tear down the cni
// networks. If rootless it will join/create the rootless network namespace.
func (r *Runtime) setUpNetwork(ns string, opts types.NetworkOptions) (map[string]types.StatusBlock, error) {
- if r.config.MachineEnabled() {
- if err := setPrimaryMachineIP(); err != nil {
- return nil, err
- }
- }
rootlessNetNS, err := r.GetRootlessNetNs(true)
if err != nil {
return nil, err
@@ -650,7 +649,18 @@ func getCNIPodName(c *Container) string {
}
// Create and configure a new network namespace for a container
-func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (map[string]types.StatusBlock, error) {
+func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (status map[string]types.StatusBlock, rerr error) {
+ if err := r.exposeMachinePorts(ctr.config.PortMappings); err != nil {
+ return nil, err
+ }
+ defer func() {
+ // make sure to unexpose the gvproxy ports when an error happens
+ if rerr != nil {
+ if err := r.unexposeMachinePorts(ctr.config.PortMappings); err != nil {
+ logrus.Errorf("failed to free gvproxy machine ports: %v", err)
+ }
+ }
+ }()
if ctr.config.NetMode.IsSlirp4netns() {
return nil, r.setupSlirp4netns(ctr, ctrNS)
}
@@ -836,6 +846,10 @@ func (r *Runtime) teardownCNI(ctr *Container) error {
// Tear down a network namespace, undoing all state associated with it.
func (r *Runtime) teardownNetNS(ctr *Container) error {
+ if err := r.unexposeMachinePorts(ctr.config.PortMappings); err != nil {
+ // do not return an error otherwise we would prevent network cleanup
+ logrus.Errorf("failed to free gvproxy machine ports: %v", err)
+ }
if err := r.teardownCNI(ctr); err != nil {
return err
}
@@ -929,8 +943,8 @@ func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.Statu
Aliases: aliases[network],
StaticMAC: netInt.MacAddress,
}
- for _, netAddress := range netInt.Networks {
- perNetOpts.StaticIPs = append(perNetOpts.StaticIPs, netAddress.Subnet.IP)
+ for _, netAddress := range netInt.Subnets {
+ perNetOpts.StaticIPs = append(perNetOpts.StaticIPs, netAddress.IPNet.IP)
}
// Normally interfaces have a length of 1, only for some special cni configs we could get more.
// For now just use the first interface to get the ips this should be good enough for most cases.
@@ -1116,25 +1130,25 @@ func (c *Container) setupNetworkDescriptions(networks []string) error {
func resultToBasicNetworkConfig(result types.StatusBlock) (define.InspectBasicNetworkConfig, error) {
config := define.InspectBasicNetworkConfig{}
for _, netInt := range result.Interfaces {
- for _, netAddress := range netInt.Networks {
- size, _ := netAddress.Subnet.Mask.Size()
- if netAddress.Subnet.IP.To4() != nil {
+ for _, netAddress := range netInt.Subnets {
+ size, _ := netAddress.IPNet.Mask.Size()
+ if netAddress.IPNet.IP.To4() != nil {
//ipv4
if config.IPAddress == "" {
- config.IPAddress = netAddress.Subnet.IP.String()
+ config.IPAddress = netAddress.IPNet.IP.String()
config.IPPrefixLen = size
config.Gateway = netAddress.Gateway.String()
} else {
- config.SecondaryIPAddresses = append(config.SecondaryIPAddresses, netAddress.Subnet.IP.String())
+ config.SecondaryIPAddresses = append(config.SecondaryIPAddresses, netAddress.IPNet.IP.String())
}
} else {
//ipv6
if config.GlobalIPv6Address == "" {
- config.GlobalIPv6Address = netAddress.Subnet.IP.String()
+ config.GlobalIPv6Address = netAddress.IPNet.IP.String()
config.GlobalIPv6PrefixLen = size
config.IPv6Gateway = netAddress.Gateway.String()
} else {
- config.SecondaryIPv6Addresses = append(config.SecondaryIPv6Addresses, netAddress.Subnet.IP.String())
+ config.SecondaryIPv6Addresses = append(config.SecondaryIPv6Addresses, netAddress.IPNet.IP.String())
}
}
}
@@ -1206,7 +1220,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro
ContainerID: c.config.ID,
ContainerName: getCNIPodName(c),
}
- opts.PortMappings = c.config.PortMappings
+ opts.PortMappings = c.convertPortMappings()
eth, exists := c.state.NetInterfaceDescriptions.getInterfaceByName(netName)
if !exists {
return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName)
@@ -1298,7 +1312,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
ContainerID: c.config.ID,
ContainerName: getCNIPodName(c),
}
- opts.PortMappings = c.config.PortMappings
+ opts.PortMappings = c.convertPortMappings()
eth, exists := c.state.NetInterfaceDescriptions.getInterfaceByName(netName)
if !exists {
return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName)