github.com/jfrazelle/docker@v1.1.2-0.20210712172922-bf78e25fe508/libnetwork/drivers/bridge/setup_verify.go (about)

     1  // +build linux
     2  
     3  package bridge
     4  
     5  import (
     6  	"fmt"
     7  	"strings"
     8  
     9  	"github.com/docker/docker/libnetwork/ns"
    10  	"github.com/docker/docker/libnetwork/types"
    11  	"github.com/sirupsen/logrus"
    12  	"github.com/vishvananda/netlink"
    13  )
    14  
    15  func setupVerifyAndReconcile(config *networkConfiguration, i *bridgeInterface) error {
    16  	// Fetch a slice of IPv4 addresses and a slice of IPv6 addresses from the bridge.
    17  	addrsv4, addrsv6, err := i.addresses()
    18  	if err != nil {
    19  		return fmt.Errorf("Failed to verify ip addresses: %v", err)
    20  	}
    21  
    22  	addrv4, _ := selectIPv4Address(addrsv4, config.AddressIPv4)
    23  
    24  	// Verify that the bridge does have an IPv4 address.
    25  	if addrv4.IPNet == nil {
    26  		return &ErrNoIPAddr{}
    27  	}
    28  
    29  	// Verify that the bridge IPv4 address matches the requested configuration.
    30  	if config.AddressIPv4 != nil && !addrv4.IP.Equal(config.AddressIPv4.IP) {
    31  		return &IPv4AddrNoMatchError{IP: addrv4.IP, CfgIP: config.AddressIPv4.IP}
    32  	}
    33  
    34  	// Verify that one of the bridge IPv6 addresses matches the requested
    35  	// configuration.
    36  	if config.EnableIPv6 && !findIPv6Address(netlink.Addr{IPNet: bridgeIPv6}, addrsv6) {
    37  		return (*IPv6AddrNoMatchError)(bridgeIPv6)
    38  	}
    39  
    40  	// Release any residual IPv6 address that might be there because of older daemon instances
    41  	for _, addrv6 := range addrsv6 {
    42  		addrv6 := addrv6
    43  		if addrv6.IP.IsGlobalUnicast() && !types.CompareIPNet(addrv6.IPNet, i.bridgeIPv6) {
    44  			if err := i.nlh.AddrDel(i.Link, &addrv6); err != nil {
    45  				logrus.Warnf("Failed to remove residual IPv6 address %s from bridge: %v", addrv6.IPNet, err)
    46  			}
    47  		}
    48  	}
    49  
    50  	return nil
    51  }
    52  
    53  func findIPv6Address(addr netlink.Addr, addresses []netlink.Addr) bool {
    54  	for _, addrv6 := range addresses {
    55  		if addrv6.String() == addr.String() {
    56  			return true
    57  		}
    58  	}
    59  	return false
    60  }
    61  
    62  func bridgeInterfaceExists(name string) (bool, error) {
    63  	nlh := ns.NlHandle()
    64  	link, err := nlh.LinkByName(name)
    65  	if err != nil {
    66  		if strings.Contains(err.Error(), "Link not found") {
    67  			return false, nil
    68  		}
    69  		return false, fmt.Errorf("failed to check bridge interface existence: %v", err)
    70  	}
    71  
    72  	if link.Type() == "bridge" {
    73  		return true, nil
    74  	}
    75  	return false, fmt.Errorf("existing interface %s is not a bridge", name)
    76  }