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 }