Allow overlapping change in bridge's IPv6 network.
**- What I did**

The original ticket reports that the daemon won't start if the `fixed-cidr-v6` address is changed from `fe80::/64` to, for example, `fe80::/80` ... those are link local addresses, which turn out to be a special case. But, the same applies to any IPv6 subnet - if the daemon is started with IPv6 enabled on the default bridge, then the `fixed-cidr-v6` is changed to an overlapping subnet, the daemon fails to start. (For example, `2001:db8::/64` to `2001:db8::/80`.)

This change makes it possible to change the configured address for the default bridge to an overlapping subnet (without manually deleting the `docker0` bridge).

Link-local addresses were a special case because they were not released when a container stopped. So, for the default bridge where IP addresses are based on MAC addresses - and MAC addresses were recycled - with `fixed-cidr-v6=fe80::/64`, once a container was stopped new containers could not be started.  For non-default bridge networks with a link-local subnet, addresses leaked when containers stopped.

Linux always uses the `fe80::/64` network, the 'veth' devices get addresses in that subnet. So, overlapping LL subnets are not allowed by this change, other LL subnets are ok.

**- How I did it**

The code was doing this:
```
setupBridgeIPv6():
   - programIPv6Address(<default link local address>)
   - programIPv6Address(<configured address>)
if !config.InhibitIPv4 then setupVerifyAndReconcile():
  - some IPv4 stuff
  - remove global-unicast IPv6 addresses, apart from the configured on
```

So, it was trying to add the new configured address before deleting the old one. Nowhere in the code has a complete picture of the IPv6 addresses the bridge needs, so it's not able to reconcile existing/required config properly.

This change calculates the IPv6 addresses needed on the bridge, then reconciles them with the addresses on an existing bridge by deleting then adding addresses as required - all in `setupBridgeIPv6()`.

If the configured subnet is link-local, it replaces the default link local address/network.

Link local addresses are returned to their address pool when containers are stopped.

Also...

The only remaining calls of `bridgeInterface.addresses()` want either IPv4 or IPv6, but not both. So, made the address family a param.

Because the IPv6 addresses are now calculated and applied in one go, there's no need for `setupVerifyAndReconcile()` to check the set of IPv6 addresses on the bridge. And, that code was guarded by `!config.InhibitIPv4`, which can't have been right. So, removed its IPv6 parts, and added IPv4 to the function's name.

Fixes #46829

**- How to verify it**

New integration test, and updated unit tests.

Overlapping change to `--fixed-cidr-v6`:
```
# dockerd  --ipv6 --experimental --ip6tables --fixed-cidr-v6=fc00:1234::/64
...
# ip a
[...]
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:b8:f5:44:23 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fc00:1234::1/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::1/64 scope link
       valid_lft forever preferred_lft forever

# dockerd  --ipv6 --experimental --ip6tables --fixed-cidr-v6=fc00:1234::/80
...
# ip a
[...]
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:b8:f5:44:23 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fc00:1234::1/80 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::1/64 scope link
       valid_lft forever preferred_lft forever
```

Explicit errors if `--fixed-cidr-v6` is link local and overlaps with (but isn't equal to) `fe80::/64`:

```
# dockerd --ipv6 --experimental --ip6tables --fixed-cidr-v6=fe80::/65 --validate
unable to configure the Docker daemon with file /etc/docker/daemon.json: merged configuration validation from file and command line flags failed: invalid fixed-cidr-v6: clash with the Link-Local prefix 'fe80::/64'

# docker network create --subnet=fe80::/65 testnet
Error response from daemon: clash with the Link-Local prefix 'fe80::/64'
```

**- Description for the changelog**

Allow overlapping change in bridge's IPv6 subnet, support link-local subnets.
libnetwork/drivers/bridge/interface_linux.go
package bridge

import (
	"context"
	"fmt"
	"net"

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

const (
	// DefaultBridgeName is the default name for the bridge interface managed
	// by the driver when unspecified by the caller.
	DefaultBridgeName = "docker0"
)

// Interface models the bridge network device.
type bridgeInterface struct {
	Link        netlink.Link
	bridgeIPv4  *net.IPNet
	bridgeIPv6  *net.IPNet
	gatewayIPv4 net.IP
	gatewayIPv6 net.IP
	nlh         *netlink.Handle
}

// newInterface creates a new bridge interface structure. It attempts to find
// an already existing device identified by the configuration BridgeName field,
// or the default bridge name when unspecified, but doesn't attempt to create
// one when missing
func newInterface(nlh *netlink.Handle, config *networkConfiguration) (*bridgeInterface, error) {
	var err error
	i := &bridgeInterface{nlh: nlh}

	// Initialize the bridge name to the default if unspecified.
	if config.BridgeName == "" {
		config.BridgeName = DefaultBridgeName
	}

	// Attempt to find an existing bridge named with the specified name.
	i.Link, err = nlh.LinkByName(config.BridgeName)
	if err != nil {
		log.G(context.TODO()).Debugf("Did not find any interface with name %s: %v", config.BridgeName, err)
	} else if _, ok := i.Link.(*netlink.Bridge); !ok {
		return nil, fmt.Errorf("existing interface %s is not a bridge", i.Link.Attrs().Name)
	}
	return i, nil
}

// exists indicates if the existing bridge interface exists on the system.
func (i *bridgeInterface) exists() bool {
	return i.Link != nil
}

// addresses returns all IPv4 addresses and all IPv6 addresses for the bridge interface.
func (i *bridgeInterface) addresses() ([]netlink.Addr, []netlink.Addr, error) {
	if !i.exists() {
		// A nonexistent interface, by definition, cannot have any addresses.
		return nil, nil, nil
	}
	v4addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V4)
	if err != nil {
		return nil, nil, fmt.Errorf("Failed to retrieve V4 addresses: %v", err)
	}

	v6addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V6)
	if err != nil {
		return nil, nil, fmt.Errorf("Failed to retrieve V6 addresses: %v", err)
	}

	if len(v4addr) == 0 {
		return nil, v6addr, nil
	}
	return v4addr, v6addr, nil
}

func (i *bridgeInterface) programIPv6Address() error {
	_, nlAddressList, err := i.addresses()
	if err != nil {
		return &IPv6AddrAddError{IP: i.bridgeIPv6, Err: fmt.Errorf("failed to retrieve address list: %v", err)}
	}
	nlAddr := netlink.Addr{IPNet: i.bridgeIPv6}
	if findIPv6Address(nlAddr, nlAddressList) {
		return nil
	}
	if err := i.nlh.AddrAdd(i.Link, &nlAddr); err != nil {
		return &IPv6AddrAddError{IP: i.bridgeIPv6, Err: err}
	}
	return nil
}

package bridge

import (
	"context"
	"fmt"
	"net"
	"net/netip"

	"github.com/containerd/log"
	"github.com/docker/docker/errdefs"
	"github.com/docker/docker/libnetwork/internal/netiputil"
	"github.com/vishvananda/netlink"
)

const (
	// DefaultBridgeName is the default name for the bridge interface managed
	// by the driver when unspecified by the caller.
	DefaultBridgeName = "docker0"
)

// Interface models the bridge network device.
type bridgeInterface struct {
	Link        netlink.Link
	bridgeIPv4  *net.IPNet
	bridgeIPv6  *net.IPNet
	gatewayIPv4 net.IP
	gatewayIPv6 net.IP
	nlh         *netlink.Handle
}

// newInterface creates a new bridge interface structure. It attempts to find
// an already existing device identified by the configuration BridgeName field,
// or the default bridge name when unspecified, but doesn't attempt to create
// one when missing
func newInterface(nlh *netlink.Handle, config *networkConfiguration) (*bridgeInterface, error) {
	var err error
	i := &bridgeInterface{nlh: nlh}

	// Initialize the bridge name to the default if unspecified.
	if config.BridgeName == "" {
		config.BridgeName = DefaultBridgeName
	}

	// Attempt to find an existing bridge named with the specified name.
	i.Link, err = nlh.LinkByName(config.BridgeName)
	if err != nil {
		log.G(context.TODO()).Debugf("Did not find any interface with name %s: %v", config.BridgeName, err)
	} else if _, ok := i.Link.(*netlink.Bridge); !ok {
		return nil, fmt.Errorf("existing interface %s is not a bridge", i.Link.Attrs().Name)
	}
	return i, nil
}

// exists indicates if the existing bridge interface exists on the system.
func (i *bridgeInterface) exists() bool {
	return i.Link != nil
}

// addresses returns a bridge's addresses, IPv4 (with family=netlink.FAMILY_V4)
// or IPv6 (family=netlink.FAMILY_V6).
func (i *bridgeInterface) addresses(family int) ([]netlink.Addr, error) {
	if !i.exists() {
		// A nonexistent interface, by definition, cannot have any addresses.
		return nil, nil
	}
	addrs, err := i.nlh.AddrList(i.Link, family)
	if err != nil {
		return nil, fmt.Errorf("Failed to retrieve addresses: %v", err)
	}
	return addrs, nil
}

func getRequiredIPv6Addrs(config *networkConfiguration) (requiredAddrs map[netip.Addr]netip.Prefix, addr *net.IPNet, gateway net.IP, err error) {
	requiredAddrs = make(map[netip.Addr]netip.Prefix)

	// TODO(robmry) - is config.AddressIPv6 always set at this point?
	//   The logic here is preserved from the original setupBridgeIPv6(), but
	//   can probably be simplified.

	// Always give the bridge 'fe80::1' - every interface is required to have an
	// address in 'fe80::/64'. Linux may assign an address, but we'll replace it with
	// 'fe80::1'. Then, if the configured prefix is 'fe80::/64', the IPAM pool
	// assigned address will not be a second address in the LL subnet.
	addr = bridgeIPv6
	gateway = bridgeIPv6.IP
	ra, ok := netiputil.ToPrefix(bridgeIPv6)
	if !ok {
		err = fmt.Errorf("Failed to convert Link-Local IPv6 address to netip.Prefix")
		return nil, nil, net.IP{}, err
	}
	requiredAddrs[ra.Addr()] = ra

	// Set up the user-specified bridge address and gateway.
	if config.AddressIPv6 != nil {
		addr = config.AddressIPv6
		gateway = config.AddressIPv6.IP
		ra, ok := netiputil.ToPrefix(config.AddressIPv6)
		if !ok {
			err = fmt.Errorf("failed to convert bridge IPv6 address '%s' to netip.Prefix", config.AddressIPv6.String())
			return nil, nil, net.IP{}, err
		}
		requiredAddrs[ra.Addr()] = ra
	}

	return requiredAddrs, addr, gateway, nil
}

func (i *bridgeInterface) programIPv6Addresses(config *networkConfiguration) error {
	// Get the IPv6 addresses currently assigned to the bridge, if any.
	existingAddrs, err := i.addresses(netlink.FAMILY_V6)
	if err != nil {
		return errdefs.System(err)
	}

	// Get the list of required IPv6 addresses for this bridge.
	var requiredAddrs map[netip.Addr]netip.Prefix
	requiredAddrs, i.bridgeIPv6, i.gatewayIPv6, err = getRequiredIPv6Addrs(config)
	if err != nil {
		return errdefs.System(err)
	}

	// Remove addresses that aren't required.
	for _, existingAddr := range existingAddrs {
		ea, ok := netip.AddrFromSlice(existingAddr.IP)
		if !ok {
			return errdefs.System(fmt.Errorf("Failed to convert IPv6 address '%s' to netip.Addr", config.AddressIPv6))
		}
		// Ignore the prefix length when comparing addresses, it's informational
		// (RFC-5942 section 4), and removing/re-adding an address that's still valid
		// would disrupt traffic on live-restore.
		if _, required := requiredAddrs[ea]; !required {
			err := i.nlh.AddrDel(i.Link, &existingAddr) //#nosec G601 -- Memory aliasing is not an issue in practice as the &existingAddr pointer is not retained by the callee after the AddrDel() call returns.
			if err != nil {
				log.G(context.TODO()).WithFields(log.Fields{"error": err, "address": existingAddr.IPNet}).Warnf("Failed to remove residual IPv6 address from bridge")
			}
		}
	}
	// Add or update required addresses.
	for _, addrPrefix := range requiredAddrs {
		// Using AddrReplace(), rather than AddrAdd(). When the subnet is changed for an
		// existing bridge in a way that doesn't affect the bridge's assigned address,
		// the old address has not been removed at this point - because that would be
		// service-affecting for a running container.
		//
		// But if, for example, 'fixed-cidr-v6' is changed from '2000:dbe::/64' to
		// '2000:dbe::/80', the default bridge will still be assigned address
		// '2000:dbe::1'. In the output of 'ip a', the prefix length is displayed - and
		// the user is likely to expect to see it updated from '64' to '80'.
		// Unfortunately, 'netlink.AddrReplace()' ('RTM_NEWADDR' with 'NLM_F_REPLACE')
		// doesn't update the prefix length. This is a cosmetic problem, the prefix
		// length of an assigned address is not used to determine whether an address is
		// "on-link" (RFC-5942).
		if err := i.nlh.AddrReplace(i.Link, &netlink.Addr{IPNet: netiputil.ToIPNet(addrPrefix)}); err != nil {
			return errdefs.System(fmt.Errorf("failed to add IPv6 address %s to bridge: %v", i.bridgeIPv6, err))
		}
	}
	return nil
}

```suggestion
```
Shallow-copying won't do much good here. It won't protect the address from being mutated by `AddrDel()` as it is a pointer field. And it is a synchronous call so there are no concerns about loop-variable footguns. If some linter demanded that you add this line, the linter is wrong.