Skip to content

Commit

Permalink
Pass container hostname to netavark
Browse files Browse the repository at this point in the history
Passing the hostname allows netavark to include it in DHCP lease
requests which, in an environment where DDNS is used, can cause
DNS entries to be created automatically.

* The current Hostname() function in container.go was updated to
check the new `use_container_name_as_hostname` option in the
CONTAINERS table of containers.conf.  If set and no hostname
was configured for the container, it causes the hostname to be
set to a version of the container's name with the characters not
valid for a hostname removed.  If not set (the default), the original
behavior of setting the hostname to the short container ID is
preserved.

* Because the Hostname() function can return the host's hostname
if the container isn't running in a private UTS namespace, and we'd
NEVER want to send _that_ in a DHCP request for a container, a new
function NetworkHostname() was added which functions like Hostname()
except that it will return an empty string instead of the host's
hostname if the container is not running in a private UTS namespace.

* networking_common.getNetworkOptions() now uses NetworkHostname()
to set the ContainerHostname member of the NetworkOptions structure.
That member was added to the structure in a corresponding commit in
common/libnetwork/types/network.go.

Signed-off-by: George Joseph <[email protected]>
  • Loading branch information
gtjoseph committed Nov 25, 2024
1 parent 84dc031 commit aa649e7
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 4 deletions.
60 changes: 59 additions & 1 deletion libpod/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/containers/podman/v5/libpod/define"
"github.com/containers/podman/v5/libpod/lock"
"github.com/containers/storage"
"github.com/containers/storage/pkg/regexp"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
Expand Down Expand Up @@ -667,7 +668,7 @@ func (c *Container) RuntimeName() string {
// Unlocked

// Hostname gets the container's hostname
func (c *Container) Hostname() string {
func (c *Container) ConfiguredHostname() string {
if c.config.UTSNsCtr != "" {
utsNsCtr, err := c.runtime.GetContainer(c.config.UTSNsCtr)
if err != nil {
Expand All @@ -680,6 +681,18 @@ func (c *Container) Hostname() string {
if c.config.Spec.Hostname != "" {
return c.config.Spec.Hostname
}
return ""
}

// Characters valid in a hostname are in the set [0-9a-zA-Z.-]
var invalidHostnameCharacters = regexp.Delayed("[^0-9a-zA-Z.-]")

// Hostname gets the container's hostname
func (c *Container) Hostname() string {
hostname := c.ConfiguredHostname()
if hostname != "" {
return hostname
}

// if the container is not running in a private UTS namespace,
// return the host's hostname.
Expand All @@ -690,6 +703,51 @@ func (c *Container) Hostname() string {
return hostname
}
}

// If use_container_name_as_hostname is set in the CONTAINERS table in containers.conf
// use a sanitized version of the container's name as the hostname.
if c.runtime.config.Containers.UseContainerNameAsHostName {
sanitizedHostname := invalidHostnameCharacters.ReplaceAllString(c.Name(), "")
return sanitizedHostname
}

// Otherwise use the container's short ID as the hostname.
if len(c.ID()) < 11 {
return c.ID()
}
return c.ID()[:12]
}

// If the container isn't running in a private UTS namespace, Hostname()
// will return the host's hostname as the container's hostname. If netavark
// were to try and obtain a DHCP lease with the host's hostname in an environment
// where DDNS was active, bad things could happen. NetworkHostname() on the
// other hand, will return an empty string if the container isn't running
// in a private UTS namespace.
//
// This function should only be used to populate the ContainerHostname member
// of the common.libnetwork.types.NetworkOptions struct.
func (c *Container) NetworkHostname() string {
hostname := c.ConfiguredHostname()
if hostname != "" {
return hostname
}

// if the container is not running in a private UTS namespace,
// return an empty string.
privateUTS := c.hasPrivateUTS()
if !privateUTS {
return ""
}

// If use_container_name_as_hostname is set in the CONTAINERS table in containers.conf
// use a sanitized version of the container's name as the hostname.
if c.runtime.config.Containers.UseContainerNameAsHostName {
sanitizedHostname := invalidHostnameCharacters.ReplaceAllString(c.Name(), "")
return sanitizedHostname
}

// Otherwise use the container's short ID as the hostname.
if len(c.ID()) < 11 {
return c.ID()
}
Expand Down
7 changes: 4 additions & 3 deletions libpod/networking_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ func (c *Container) getNetworkOptions(networkOpts map[string]types.PerNetworkOpt
nameservers = append(nameservers, ip.String())
}
opts := types.NetworkOptions{
ContainerID: c.config.ID,
ContainerName: getNetworkPodName(c),
DNSServers: nameservers,
ContainerID: c.config.ID,
ContainerName: getNetworkPodName(c),
DNSServers: nameservers,
ContainerHostname: c.NetworkHostname(),
}
opts.PortMappings = c.convertPortMappings()

Expand Down

0 comments on commit aa649e7

Please sign in to comment.