setup_verify_linux.go 2.4 KB

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