2021-05-25 19:48:54 -04:00
|
|
|
// +build linux
|
|
|
|
|
2015-02-22 20:58:52 -05:00
|
|
|
package bridge
|
|
|
|
|
2015-05-14 17:56:15 -04:00
|
|
|
import (
|
2016-05-16 14:51:40 -04:00
|
|
|
"fmt"
|
2016-06-27 23:42:50 -04:00
|
|
|
"strings"
|
2016-05-16 14:51:40 -04:00
|
|
|
|
2021-04-05 20:24:47 -04:00
|
|
|
"github.com/docker/docker/libnetwork/ns"
|
|
|
|
"github.com/docker/docker/libnetwork/types"
|
2017-07-26 17:18:31 -04:00
|
|
|
"github.com/sirupsen/logrus"
|
2015-05-14 17:56:15 -04:00
|
|
|
"github.com/vishvananda/netlink"
|
|
|
|
)
|
2015-02-22 20:58:52 -05:00
|
|
|
|
2015-05-22 13:56:36 -04:00
|
|
|
func setupVerifyAndReconcile(config *networkConfiguration, i *bridgeInterface) error {
|
2016-09-17 01:40:44 -04:00
|
|
|
// Fetch a slice of IPv4 addresses and a slice of IPv6 addresses from the bridge.
|
|
|
|
addrsv4, addrsv6, err := i.addresses()
|
2015-02-22 20:58:52 -05:00
|
|
|
if err != nil {
|
2016-05-16 14:51:40 -04:00
|
|
|
return fmt.Errorf("Failed to verify ip addresses: %v", err)
|
2015-02-22 20:58:52 -05:00
|
|
|
}
|
|
|
|
|
2016-09-17 01:40:44 -04:00
|
|
|
addrv4, _ := selectIPv4Address(addrsv4, config.AddressIPv4)
|
|
|
|
|
2015-02-24 21:41:17 -05:00
|
|
|
// Verify that the bridge does have an IPv4 address.
|
|
|
|
if addrv4.IPNet == nil {
|
2015-05-14 17:56:15 -04:00
|
|
|
return &ErrNoIPAddr{}
|
2015-02-24 21:41:17 -05:00
|
|
|
}
|
|
|
|
|
2015-02-22 20:58:52 -05:00
|
|
|
// Verify that the bridge IPv4 address matches the requested configuration.
|
2015-04-15 01:25:42 -04:00
|
|
|
if config.AddressIPv4 != nil && !addrv4.IP.Equal(config.AddressIPv4.IP) {
|
2015-05-14 17:56:15 -04:00
|
|
|
return &IPv4AddrNoMatchError{IP: addrv4.IP, CfgIP: config.AddressIPv4.IP}
|
2015-02-22 20:58:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that one of the bridge IPv6 addresses matches the requested
|
|
|
|
// configuration.
|
2015-04-15 01:25:42 -04:00
|
|
|
if config.EnableIPv6 && !findIPv6Address(netlink.Addr{IPNet: bridgeIPv6}, addrsv6) {
|
2015-04-16 22:47:12 -04:00
|
|
|
return (*IPv6AddrNoMatchError)(bridgeIPv6)
|
2015-02-22 20:58:52 -05:00
|
|
|
}
|
|
|
|
|
2016-01-06 21:13:08 -05:00
|
|
|
// Release any residual IPv6 address that might be there because of older daemon instances
|
|
|
|
for _, addrv6 := range addrsv6 {
|
2021-06-18 18:20:06 -04:00
|
|
|
addrv6 := addrv6
|
2016-01-06 21:13:08 -05:00
|
|
|
if addrv6.IP.IsGlobalUnicast() && !types.CompareIPNet(addrv6.IPNet, i.bridgeIPv6) {
|
2021-06-18 18:20:06 -04:00
|
|
|
if err := i.nlh.AddrDel(i.Link, &addrv6); err != nil {
|
2016-11-01 00:26:14 -04:00
|
|
|
logrus.Warnf("Failed to remove residual IPv6 address %s from bridge: %v", addrv6.IPNet, err)
|
2016-01-06 21:13:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-16 01:02:21 -04:00
|
|
|
|
2015-02-24 21:41:17 -05:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func findIPv6Address(addr netlink.Addr, addresses []netlink.Addr) bool {
|
|
|
|
for _, addrv6 := range addresses {
|
|
|
|
if addrv6.String() == addr.String() {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
2015-02-22 20:58:52 -05:00
|
|
|
}
|
2016-06-27 23:42:50 -04:00
|
|
|
|
|
|
|
func bridgeInterfaceExists(name string) (bool, error) {
|
|
|
|
nlh := ns.NlHandle()
|
|
|
|
link, err := nlh.LinkByName(name)
|
|
|
|
if err != nil {
|
|
|
|
if strings.Contains(err.Error(), "Link not found") {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
return false, fmt.Errorf("failed to check bridge interface existence: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if link.Type() == "bridge" {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
return false, fmt.Errorf("existing interface %s is not a bridge", name)
|
|
|
|
}
|