libnetwork/iptables: some cleanups and refactoring
### libnetwork/iptables: inline some args

Just inline the args if they're not dynamically constructed.

### libnetwork/iptables: IPTable.NewChain() minor cleanups

- validate input variables before constructing the ChainInfo
- only construct the ChainInfo if things were successful

### libnetwork/iptables: don't use err.Error() if not needed

### libnetwork/iptables: IPTable.exists(): return early on error

Also remove a redundant string cast for the Table value.

### libnetwork/iptables: IPTable.RemoveExistingChain() slight refactor

### libnetwork/iptables: ChainInfo.Output(): explicitly suppress errors

### libnetwork/iptables: ChainInfo: don't pass whole IPTable as value

It only needed the IPVersion, so let's pass that instead.

### libnetwork/drivers/bridge: rename vars that collided with type


### libnetwork/iptables: TestPassthrough(): skip without firewalld

The test was not doing anything without firewalld running, but did
not skip either.


### libnetwork/iptables: TestReloaded(): minor cleanup

- remove local bridgeName variable that shadowed the const, but
  used the same value
- remove some redundant `var` declarations, and changed fixed
  values to a const

### libnetwork/iptables: remove unused Ebtables const

This const was added in 8301dcc6d702a97feeb968ee79ae381fd8a4997a, before
being moved to libnetwork, and moved back, but it was never used.

### libnetwork/iptables: checkRunning(): use early return

Remove redundant variable declarations, and use an early return instead.

### libnetwork/iptables: merge Conn.initConnection into newConnection

initConnection was effectively just part of the constructor; ot was not
used elsewhere. Merge the two functions to simplify things a bit.


### libnetwork/iptables: signalHandler(): use s switch

It felt ever-so-slightly more readable than if/else if/(else if...)


### libnetwork/drivers/bridge: minor cleanups for iptables funcs

setupBridgeNetFiltering:
- Indicate that the bridgeInterface argument is unused (but it's needed
  to satisfy the signature).
- Return instead of nullifying the err. Still not great, but I thought it
  was very slightly more logical thing to do.

checkBridgeNetFiltering:
- Remove unused argument, and scope ipVerName to the branch where it's
  used.

### libnetwork/iptables: remove ErrIptablesNotFound

looks like this error was added in 1cbdaebaa1c2326e57945333420d25d6f77011d5,
and later moved to libnetwork in https://github.com/moby/libnetwork/commit/44c96449c2aafbb22487086ad94ff865f9ee855a
which also updated the description to something that doesn't match what
it means.

In either case, this error was never used as a special / sentinel error,
so we can just use a regular error return.

While at it, I also lower-cased the error-message; it's not string-matched
anywhere, so we can update it to make linters more happy.

### libnetwork/iptables: errors should not be capitalized

None of these errors were string-matched anywhere, so let's change them
to be non-capitalized, as they should.

**- How I did it**

**- How to verify it**

**- Description for the changelog**
<!--
Write a short (one line) summary that describes the changes in this
pull request for inclusion in the changelog:
-->


**- A picture of a cute animal (not mandatory but encouraged)**


libnetwork/drivers/bridge/setup_bridgenetfiltering.go
//go:build linux

package bridge

import (
	"context"
	"errors"
	"fmt"
	"os"
	"syscall"

	"github.com/containerd/containerd/log"
)

// Enumeration type saying which versions of IP protocol to process.
type ipVersion int

const (
	ipvnone ipVersion = iota
	ipv4
	ipv6
	ipvboth
)

// getIPVersion gets the IP version in use ( [ipv4], [ipv6] or [ipv4 and ipv6] )
func getIPVersion(config *networkConfiguration) ipVersion {
	ipVersion := ipv4
	if config.AddressIPv6 != nil || config.EnableIPv6 {
		ipVersion |= ipv6
	}
	return ipVersion
}

func setupBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) error {
	err := checkBridgeNetFiltering(config, i)
	if err != nil {
		if ptherr, ok := err.(*os.PathError); ok {
			if errno, ok := ptherr.Err.(syscall.Errno); ok && errno == syscall.ENOENT {
				if isRunningInContainer() {
					log.G(context.TODO()).Warnf("running inside docker container, ignoring missing kernel params: %v", err)
					err = nil
				} else {
					err = errors.New("please ensure that br_netfilter kernel module is loaded")
				}
			}
		}
		if err != nil {
			return fmt.Errorf("cannot restrict inter-container communication: %v", err)
		}
	}
	return nil
}

// Enable bridge net filtering if ip forwarding is enabled. See github issue #11404
func checkBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) error {
	ipVer := getIPVersion(config)
	iface := config.BridgeName
	doEnable := func(ipVer ipVersion) error {
		var ipVerName string
		if ipVer == ipv4 {
			ipVerName = "IPv4"
		} else {
			ipVerName = "IPv6"
		}
		enabled, err := isPacketForwardingEnabled(ipVer, iface)
		if err != nil {
			log.G(context.TODO()).Warnf("failed to check %s forwarding: %v", ipVerName, err)
		} else if enabled {
			enabled, err := getKernelBoolParam(getBridgeNFKernelParam(ipVer))
			if err != nil || enabled {
				return err
			}
			return setKernelBoolParam(getBridgeNFKernelParam(ipVer), true)
		}
		return nil
	}

	switch ipVer {
	case ipv4, ipv6:
		return doEnable(ipVer)
	case ipvboth:
		v4err := doEnable(ipv4)
		v6err := doEnable(ipv6)
		if v4err == nil {
			return v6err
		}
		return v4err
	default:
		return nil
	}
}

// Get kernel param path saying whether IPv${ipVer} traffic is being forwarded
// on particular interface. Interface may be specified for IPv6 only. If
// `iface` is empty, `default` will be assumed, which represents default value
// for new interfaces.
func getForwardingKernelParam(ipVer ipVersion, iface string) string {
	switch ipVer {
	case ipv4:
		return "/proc/sys/net/ipv4/ip_forward"
	case ipv6:
		if iface == "" {
			iface = "default"
		}
		return fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/forwarding", iface)
	default:
		return ""
	}
}

// Get kernel param path saying whether bridged IPv${ipVer} traffic shall be
// passed to ip${ipVer}tables' chains.
func getBridgeNFKernelParam(ipVer ipVersion) string {
	switch ipVer {
	case ipv4:
		return "/proc/sys/net/bridge/bridge-nf-call-iptables"
	case ipv6:
		return "/proc/sys/net/bridge/bridge-nf-call-ip6tables"
	default:
		return ""
	}
}

// Gets the value of the kernel parameters located at the given path
func getKernelBoolParam(path string) (bool, error) {
	enabled := false
	line, err := os.ReadFile(path)
	if err != nil {
		return false, err
	}
	if len(line) > 0 {
		enabled = line[0] == '1'
	}
	return enabled, err
}

// Sets the value of the kernel parameter located at the given path
func setKernelBoolParam(path string, on bool) error {
	value := byte('0')
	if on {
		value = byte('1')
	}
	return os.WriteFile(path, []byte{value, '\n'}, 0o644)
}

// Checks to see if packet forwarding is enabled
func isPacketForwardingEnabled(ipVer ipVersion, iface string) (bool, error) {
	switch ipVer {
	case ipv4, ipv6:
		return getKernelBoolParam(getForwardingKernelParam(ipVer, iface))
	case ipvboth:
		enabled, err := getKernelBoolParam(getForwardingKernelParam(ipv4, ""))
		if err != nil || !enabled {
			return enabled, err
		}
		return getKernelBoolParam(getForwardingKernelParam(ipv6, iface))
	default:
		return true, nil
	}
}

func isRunningInContainer() bool {
	_, err := os.Stat("/.dockerenv")
	return !os.IsNotExist(err)
}

//go:build linux

package bridge

import (
	"context"
	"errors"
	"fmt"
	"os"
	"syscall"

	"github.com/containerd/containerd/log"
)

// Enumeration type saying which versions of IP protocol to process.
type ipVersion int

const (
	ipvnone ipVersion = iota
	ipv4
	ipv6
	ipvboth
)

// getIPVersion gets the IP version in use ( [ipv4], [ipv6] or [ipv4 and ipv6] )
func getIPVersion(config *networkConfiguration) ipVersion {
	ipVer := ipv4
	if config.AddressIPv6 != nil || config.EnableIPv6 {
		ipVer |= ipv6
	}
	return ipVer
}

func setupBridgeNetFiltering(config *networkConfiguration, _ *bridgeInterface) error {
	if err := checkBridgeNetFiltering(config); err != nil {
		if ptherr, ok := err.(*os.PathError); ok {
			if errno, ok := ptherr.Err.(syscall.Errno); ok && errno == syscall.ENOENT {
				if isRunningInContainer() {
					log.G(context.TODO()).Warnf("running inside docker container, ignoring missing kernel params: %v", err)
					return nil
				}
				err = errors.New("please ensure that br_netfilter kernel module is loaded")
			}
		}
		if err != nil {
			return fmt.Errorf("cannot restrict inter-container communication: %v", err)
		}
	}
	return nil
}

// Enable bridge net filtering if ip forwarding is enabled. See github issue #11404
func checkBridgeNetFiltering(config *networkConfiguration) error {
	ipVer := getIPVersion(config)
	iface := config.BridgeName
	doEnable := func(ipVer ipVersion) error {
		enabled, err := isPacketForwardingEnabled(ipVer, iface)
		if err != nil {
			var ipVerName string
			if ipVer == ipv4 {
				ipVerName = "IPv4"
			} else {
				ipVerName = "IPv6"
			}
			log.G(context.TODO()).Warnf("failed to check %s forwarding: %v", ipVerName, err)
		} else if enabled {
			enabled, err := getKernelBoolParam(getBridgeNFKernelParam(ipVer))
			if err != nil || enabled {
				return err
			}
			return setKernelBoolParam(getBridgeNFKernelParam(ipVer), true)
		}
		return nil
	}

	switch ipVer {
	case ipv4, ipv6:
		return doEnable(ipVer)
	case ipvboth:
		v4err := doEnable(ipv4)
		v6err := doEnable(ipv6)
		if v4err == nil {
			return v6err
		}
		return v4err
	default:
		return nil
	}
}

// Get kernel param path saying whether IPv${ipVer} traffic is being forwarded
// on particular interface. Interface may be specified for IPv6 only. If
// `iface` is empty, `default` will be assumed, which represents default value
// for new interfaces.
func getForwardingKernelParam(ipVer ipVersion, iface string) string {
	switch ipVer {
	case ipv4:
		return "/proc/sys/net/ipv4/ip_forward"
	case ipv6:
		if iface == "" {
			iface = "default"
		}
		return fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/forwarding", iface)
	default:
		return ""
	}
}

// Get kernel param path saying whether bridged IPv${ipVer} traffic shall be
// passed to ip${ipVer}tables' chains.
func getBridgeNFKernelParam(ipVer ipVersion) string {
	switch ipVer {
	case ipv4:
		return "/proc/sys/net/bridge/bridge-nf-call-iptables"
	case ipv6:
		return "/proc/sys/net/bridge/bridge-nf-call-ip6tables"
	default:
		return ""
	}
}

// Gets the value of the kernel parameters located at the given path
func getKernelBoolParam(path string) (bool, error) {
	enabled := false
	line, err := os.ReadFile(path)
	if err != nil {
		return false, err
	}
	if len(line) > 0 {
		enabled = line[0] == '1'
	}
	return enabled, err
}

// Sets the value of the kernel parameter located at the given path
func setKernelBoolParam(path string, on bool) error {
	value := byte('0')
	if on {
		value = byte('1')
	}
	return os.WriteFile(path, []byte{value, '\n'}, 0o644)
}

// Checks to see if packet forwarding is enabled
func isPacketForwardingEnabled(ipVer ipVersion, iface string) (bool, error) {
	switch ipVer {
	case ipv4, ipv6:
		return getKernelBoolParam(getForwardingKernelParam(ipVer, iface))
	case ipvboth:
		enabled, err := getKernelBoolParam(getForwardingKernelParam(ipv4, ""))
		if err != nil || !enabled {
			return enabled, err
		}
		return getKernelBoolParam(getForwardingKernelParam(ipv6, iface))
	default:
		return true, nil
	}
}

func isRunningInContainer() bool {
	_, err := os.Stat("/.dockerenv")
	return !os.IsNotExist(err)
}

OHMAN, yes. I may include that one in my follow-up 😅 