utils_linux.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // Package ipamutils provides utililty functions for ipam management
  2. package ipamutils
  3. import (
  4. "fmt"
  5. "net"
  6. "github.com/docker/libnetwork/netutils"
  7. "github.com/docker/libnetwork/osl"
  8. "github.com/docker/libnetwork/resolvconf"
  9. "github.com/vishvananda/netlink"
  10. )
  11. // ElectInterfaceAddresses looks for an interface on the OS with the specified name
  12. // and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist,
  13. // it chooses from a predifined list the first IPv4 address which does not conflict
  14. // with other interfaces on the system.
  15. func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
  16. var (
  17. v4Net *net.IPNet
  18. v6Nets []*net.IPNet
  19. err error
  20. )
  21. defer osl.InitOSContext()()
  22. link, _ := netlink.LinkByName(name)
  23. if link != nil {
  24. v4addr, err := netlink.AddrList(link, netlink.FAMILY_V4)
  25. if err != nil {
  26. return nil, nil, err
  27. }
  28. v6addr, err := netlink.AddrList(link, netlink.FAMILY_V6)
  29. if err != nil {
  30. return nil, nil, err
  31. }
  32. if len(v4addr) > 0 {
  33. v4Net = v4addr[0].IPNet
  34. }
  35. for _, nlAddr := range v6addr {
  36. v6Nets = append(v6Nets, nlAddr.IPNet)
  37. }
  38. }
  39. if link == nil || v4Net == nil {
  40. // Choose from predifined broad networks
  41. v4Net, err = FindAvailableNetwork(PredefinedBroadNetworks)
  42. if err != nil {
  43. return nil, nil, err
  44. }
  45. }
  46. return v4Net, v6Nets, nil
  47. }
  48. // FindAvailableNetwork returns a network from the passed list which does not
  49. // overlap with existing interfaces in the system
  50. func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
  51. // We don't check for an error here, because we don't really care if we
  52. // can't read /etc/resolv.conf. So instead we skip the append if resolvConf
  53. // is nil. It either doesn't exist, or we can't read it for some reason.
  54. var nameservers []string
  55. if rc, err := resolvconf.Get(); err == nil {
  56. nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
  57. }
  58. for _, nw := range list {
  59. if err := netutils.CheckNameserverOverlaps(nameservers, nw); err == nil {
  60. if err := netutils.CheckRouteOverlaps(nw); err == nil {
  61. return nw, nil
  62. }
  63. }
  64. }
  65. return nil, fmt.Errorf("no available network")
  66. }