From f62c6bf6ecd1737afab66e2e79064bf14719d36f Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 2 Jun 2021 21:00:26 +0200 Subject: add ipv6 nameservers only when the container has ipv6 enabled The containers /etc/resolv.conf allways preserved the ipv6 nameserves from the host even when the container did not supported ipv6. Check if the cni result contains an ipv6 address or slirp4netns has ipv6 support enabled and only add the ipv6 nameservers when this is the case. The test needs to have an ipv6 nameserver in the hosts /etc/hosts but we should never mess with this file on the host. Therefore the test is skipped when no ipv6 is detected. Fixes #10158 Signed-off-by: Paul Holzinger --- test/system/500-networking.bats | 58 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'test') diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index 63b9a7c14..55ec80bb2 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -329,4 +329,62 @@ load helpers run_podman network rm -f $mynetname } +@test "podman ipv6 in /etc/resolv.conf" { + ipv6_regex='([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{0,4})(%\w+)?' + + # Make sure to read the correct /etc/resolv.conf file in case of systemd-resolved. + resolve_file=$(readlink -f /etc/resolv.conf) + if [[ "$resolve_file" == "/run/systemd/resolve/stub-resolv.conf" ]]; then + resolve_file="/run/systemd/resolve/resolv.conf" + fi + + # If the host doesn't have an ipv6 in resolv.conf skip this test. + # We should never modify resolv.conf on the host. + if ! grep -E "$ipv6_regex" "$resolve_file"; then + skip "This test needs an ipv6 nameserver in $resolve_file" + fi + + # ipv4 slirp + run_podman run --rm --network slirp4netns:enable_ipv6=false $IMAGE cat /etc/resolv.conf + if grep -E "$ipv6_regex" <<< $output; then + die "resolv.conf contains a ipv6 nameserver" + fi + + # ipv6 slirp + run_podman run --rm --network slirp4netns:enable_ipv6=true $IMAGE cat /etc/resolv.conf + # "is" does not like the ipv6 regex + if ! grep -E "$ipv6_regex" <<< $output; then + die "resolv.conf does not contain a ipv6 nameserver" + fi + + # ipv4 cni + local mysubnet=$(random_rfc1918_subnet) + local netname=testnet-$(random_string 10) + + run_podman network create --subnet $mysubnet.0/24 $netname + is "$output" ".*/cni/net.d/$netname.conflist" "output of 'network create'" + + run_podman run --rm --network $netname $IMAGE cat /etc/resolv.conf + if grep -E "$ipv6_regex" <<< $output; then + die "resolv.conf contains a ipv6 nameserver" + fi + + run_podman network rm -f $netname + + # ipv6 cni + mysubnet=fd00:4:4:4:4::/64 + netname=testnet-$(random_string 10) + + run_podman network create --subnet $mysubnet $netname + is "$output" ".*/cni/net.d/$netname.conflist" "output of 'network create'" + + run_podman run --rm --network $netname $IMAGE cat /etc/resolv.conf + # "is" does not like the ipv6 regex + if ! grep -E "$ipv6_regex" <<< $output; then + die "resolv.conf does not contain a ipv6 nameserver" + fi + + run_podman network rm -f $netname +} + # vim: filetype=sh -- cgit v1.2.3-54-g00ecf From cff73766fc4421774ad3b9a3cefa12abde2c5c03 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Thu, 20 May 2021 11:23:03 +0200 Subject: Fix network create macvlan with subnet option Creating a macvlan network with the subnet or ipRange option should set the ipam plugin type to `host-local`. We also have to insert the default route. Fixes #10283 Signed-off-by: Paul Holzinger --- libpod/network/config.go | 43 ++++++++++++++++++------------------------- libpod/network/netconflist.go | 18 +++++++++++++----- test/e2e/network_test.go | 26 +++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 33 deletions(-) (limited to 'test') diff --git a/libpod/network/config.go b/libpod/network/config.go index ac4478602..9a3bc4763 100644 --- a/libpod/network/config.go +++ b/libpod/network/config.go @@ -44,17 +44,17 @@ type CNIPlugins interface { // HostLocalBridge describes a configuration for a bridge plugin // https://github.com/containernetworking/plugins/tree/master/plugins/main/bridge#network-configuration-reference type HostLocalBridge struct { - PluginType string `json:"type"` - BrName string `json:"bridge,omitempty"` - IsGW bool `json:"isGateway"` - IsDefaultGW bool `json:"isDefaultGateway,omitempty"` - ForceAddress bool `json:"forceAddress,omitempty"` - IPMasq bool `json:"ipMasq,omitempty"` - MTU int `json:"mtu,omitempty"` - HairpinMode bool `json:"hairpinMode,omitempty"` - PromiscMode bool `json:"promiscMode,omitempty"` - Vlan int `json:"vlan,omitempty"` - IPAM IPAMHostLocalConf `json:"ipam"` + PluginType string `json:"type"` + BrName string `json:"bridge,omitempty"` + IsGW bool `json:"isGateway"` + IsDefaultGW bool `json:"isDefaultGateway,omitempty"` + ForceAddress bool `json:"forceAddress,omitempty"` + IPMasq bool `json:"ipMasq,omitempty"` + MTU int `json:"mtu,omitempty"` + HairpinMode bool `json:"hairpinMode,omitempty"` + PromiscMode bool `json:"promiscMode,omitempty"` + Vlan int `json:"vlan,omitempty"` + IPAM IPAMConfig `json:"ipam"` } // Bytes outputs []byte @@ -62,9 +62,9 @@ func (h *HostLocalBridge) Bytes() ([]byte, error) { return json.MarshalIndent(h, "", "\t") } -// IPAMHostLocalConf describes an IPAM configuration +// IPAMConfig describes an IPAM configuration // https://github.com/containernetworking/plugins/tree/master/plugins/ipam/host-local#network-configuration-reference -type IPAMHostLocalConf struct { +type IPAMConfig struct { PluginType string `json:"type"` Routes []IPAMRoute `json:"routes,omitempty"` ResolveConf string `json:"resolveConf,omitempty"` @@ -81,7 +81,7 @@ type IPAMLocalHostRangeConf struct { } // Bytes outputs the configuration as []byte -func (i IPAMHostLocalConf) Bytes() ([]byte, error) { +func (i IPAMConfig) Bytes() ([]byte, error) { return json.MarshalIndent(i, "", "\t") } @@ -101,19 +101,12 @@ func (p PortMapConfig) Bytes() ([]byte, error) { return json.MarshalIndent(p, "", "\t") } -// IPAMDHCP describes the ipamdhcp config -type IPAMDHCP struct { - DHCP string `json:"type"` - Routes []IPAMRoute `json:"routes,omitempty"` - Ranges [][]IPAMLocalHostRangeConf `json:"ranges,omitempty"` -} - // MacVLANConfig describes the macvlan config type MacVLANConfig struct { - PluginType string `json:"type"` - Master string `json:"master"` - IPAM IPAMDHCP `json:"ipam"` - MTU int `json:"mtu,omitempty"` + PluginType string `json:"type"` + Master string `json:"master"` + IPAM IPAMConfig `json:"ipam"` + MTU int `json:"mtu,omitempty"` } // Bytes outputs the configuration as []byte diff --git a/libpod/network/netconflist.go b/libpod/network/netconflist.go index d2031df6d..d6c33740e 100644 --- a/libpod/network/netconflist.go +++ b/libpod/network/netconflist.go @@ -45,7 +45,7 @@ func NewNcList(name, version string, labels NcLabels) NcList { } // NewHostLocalBridge creates a new LocalBridge for host-local -func NewHostLocalBridge(name string, isGateWay, isDefaultGW, ipMasq bool, mtu int, vlan int, ipamConf IPAMHostLocalConf) *HostLocalBridge { +func NewHostLocalBridge(name string, isGateWay, isDefaultGW, ipMasq bool, mtu int, vlan int, ipamConf IPAMConfig) *HostLocalBridge { hostLocalBridge := HostLocalBridge{ PluginType: "bridge", BrName: name, @@ -65,8 +65,8 @@ func NewHostLocalBridge(name string, isGateWay, isDefaultGW, ipMasq bool, mtu in } // NewIPAMHostLocalConf creates a new IPAMHostLocal configuration -func NewIPAMHostLocalConf(routes []IPAMRoute, ipamRanges [][]IPAMLocalHostRangeConf) (IPAMHostLocalConf, error) { - ipamConf := IPAMHostLocalConf{ +func NewIPAMHostLocalConf(routes []IPAMRoute, ipamRanges [][]IPAMLocalHostRangeConf) (IPAMConfig, error) { + ipamConf := IPAMConfig{ PluginType: "host-local", Routes: routes, // Possible future support ? Leaving for clues @@ -177,8 +177,10 @@ func HasDNSNamePlugin(paths []string) bool { // NewMacVLANPlugin creates a macvlanconfig with a given device name func NewMacVLANPlugin(device string, gateway net.IP, ipRange *net.IPNet, subnet *net.IPNet, mtu int) (MacVLANConfig, error) { - i := IPAMDHCP{DHCP: "dhcp"} - if gateway != nil || ipRange != nil || subnet != nil { + i := IPAMConfig{PluginType: "dhcp"} + if gateway != nil || + (ipRange != nil && ipRange.IP != nil && ipRange.Mask != nil) || + (subnet != nil && subnet.IP != nil && subnet.Mask != nil) { ipam, err := NewIPAMLocalHostRange(subnet, ipRange, gateway) if err != nil { return MacVLANConfig{}, err @@ -186,6 +188,12 @@ func NewMacVLANPlugin(device string, gateway net.IP, ipRange *net.IPNet, subnet ranges := make([][]IPAMLocalHostRangeConf, 0) ranges = append(ranges, ipam) i.Ranges = ranges + route, err := NewIPAMDefaultRoute(IsIPv6(subnet.IP)) + if err != nil { + return MacVLANConfig{}, err + } + i.Routes = []IPAMRoute{route} + i.PluginType = "host-local" } m := MacVLANConfig{ diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go index 6f28d7e19..a7e61932e 100644 --- a/test/e2e/network_test.go +++ b/test/e2e/network_test.go @@ -533,7 +533,11 @@ var _ = Describe("Podman network", func() { out, err := inspect.jq(".[0].plugins[0].master") Expect(err).To(BeNil()) - Expect(out).To(Equal("\"lo\"")) + Expect(out).To(Equal(`"lo"`)) + + ipamType, err := inspect.jq(".[0].plugins[0].ipam.type") + Expect(err).To(BeNil()) + Expect(ipamType).To(Equal(`"dhcp"`)) nc = podmanTest.Podman([]string{"network", "rm", net}) nc.WaitWithDefaultTimeout() @@ -571,13 +575,29 @@ var _ = Describe("Podman network", func() { Expect(err).To(BeNil()) Expect(mtu).To(Equal("1500")) + name, err := inspect.jq(".[0].plugins[0].type") + Expect(err).To(BeNil()) + Expect(name).To(Equal(`"macvlan"`)) + + netInt, err := inspect.jq(".[0].plugins[0].master") + Expect(err).To(BeNil()) + Expect(netInt).To(Equal(`"lo"`)) + + ipamType, err := inspect.jq(".[0].plugins[0].ipam.type") + Expect(err).To(BeNil()) + Expect(ipamType).To(Equal(`"host-local"`)) + gw, err := inspect.jq(".[0].plugins[0].ipam.ranges[0][0].gateway") Expect(err).To(BeNil()) - Expect(gw).To(Equal("\"192.168.1.254\"")) + Expect(gw).To(Equal(`"192.168.1.254"`)) subnet, err := inspect.jq(".[0].plugins[0].ipam.ranges[0][0].subnet") Expect(err).To(BeNil()) - Expect(subnet).To(Equal("\"192.168.1.0/24\"")) + Expect(subnet).To(Equal(`"192.168.1.0/24"`)) + + routes, err := inspect.jq(".[0].plugins[0].ipam.routes[0].dst") + Expect(err).To(BeNil()) + Expect(routes).To(Equal(`"0.0.0.0/0"`)) nc = podmanTest.Podman([]string{"network", "rm", net}) nc.WaitWithDefaultTimeout() -- cgit v1.2.3-54-g00ecf From 9647d88449f44028c9b870af74e5e44cb819ff9d Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Thu, 3 Jun 2021 14:46:04 -0400 Subject: Ensure minimum API version is set correctly in tests Signed-off-by: Matthew Heon --- test/apiv2/01-basic.at | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/apiv2/01-basic.at b/test/apiv2/01-basic.at index 64aafa013..ae078b900 100644 --- a/test/apiv2/01-basic.at +++ b/test/apiv2/01-basic.at @@ -19,7 +19,7 @@ for i in /version version; do t GET $i 200 \ .Components[0].Name="Podman Engine" \ .Components[0].Details.APIVersion~3[0-9.-]\\+ \ - .Components[0].Details.MinAPIVersion=3.1.0 \ + .Components[0].Details.MinAPIVersion=3.2.0 \ .Components[0].Details.Os=linux \ .ApiVersion=1.40 \ .MinAPIVersion=1.24 \ -- cgit v1.2.3-54-g00ecf