utils.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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/resolvconf"
  8. "github.com/vishvananda/netlink"
  9. )
  10. var (
  11. // PredefinedBroadNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
  12. // (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGranularNetworks`
  13. PredefinedBroadNetworks []*net.IPNet
  14. // PredefinedGranularNetworks contains a list of 64K IPv4 private networks with host size 8
  15. // (10.x.x.x/24) which do not overlap with the networks in `PredefinedBroadNetworks`
  16. PredefinedGranularNetworks []*net.IPNet
  17. )
  18. func init() {
  19. PredefinedBroadNetworks = initBroadPredefinedNetworks()
  20. PredefinedGranularNetworks = initGranularPredefinedNetworks()
  21. }
  22. // ElectInterfaceAddresses looks for an interface on the OS with the specified name
  23. // and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist,
  24. // it chooses from a predifined list the first IPv4 address which does not conflict
  25. // with other interfaces on the system.
  26. func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
  27. var (
  28. v4Net *net.IPNet
  29. v6Nets []*net.IPNet
  30. err error
  31. )
  32. link, _ := netlink.LinkByName(name)
  33. if link != nil {
  34. v4addr, err := netlink.AddrList(link, netlink.FAMILY_V4)
  35. if err != nil {
  36. return nil, nil, err
  37. }
  38. v6addr, err := netlink.AddrList(link, netlink.FAMILY_V6)
  39. if err != nil {
  40. return nil, nil, err
  41. }
  42. if len(v4addr) > 0 {
  43. v4Net = v4addr[0].IPNet
  44. }
  45. for _, nlAddr := range v6addr {
  46. v6Nets = append(v6Nets, nlAddr.IPNet)
  47. }
  48. }
  49. if link == nil || v4Net == nil {
  50. // Choose from predifined broad networks
  51. v4Net, err = FindAvailableNetwork(PredefinedBroadNetworks)
  52. if err != nil {
  53. return nil, nil, err
  54. }
  55. }
  56. return v4Net, v6Nets, nil
  57. }
  58. // FindAvailableNetwork returns a network from the passed list which does not
  59. // overlap with existing interfaces in the system
  60. func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
  61. // We don't check for an error here, because we don't really care if we
  62. // can't read /etc/resolv.conf. So instead we skip the append if resolvConf
  63. // is nil. It either doesn't exist, or we can't read it for some reason.
  64. var nameservers []string
  65. if rc, err := resolvconf.Get(); err == nil {
  66. nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
  67. }
  68. for _, nw := range list {
  69. if err := netutils.CheckNameserverOverlaps(nameservers, nw); err == nil {
  70. if err := netutils.CheckRouteOverlaps(nw); err == nil {
  71. return nw, nil
  72. }
  73. }
  74. }
  75. return nil, fmt.Errorf("no available network")
  76. }
  77. func initBroadPredefinedNetworks() []*net.IPNet {
  78. pl := make([]*net.IPNet, 0, 31)
  79. mask := []byte{255, 255, 0, 0}
  80. for i := 17; i < 32; i++ {
  81. pl = append(pl, &net.IPNet{IP: []byte{172, byte(i), 0, 0}, Mask: mask})
  82. }
  83. mask20 := []byte{255, 255, 240, 0}
  84. for i := 0; i < 16; i++ {
  85. pl = append(pl, &net.IPNet{IP: []byte{192, 168, byte(i << 4), 0}, Mask: mask20})
  86. }
  87. return pl
  88. }
  89. func initGranularPredefinedNetworks() []*net.IPNet {
  90. pl := make([]*net.IPNet, 0, 256*256)
  91. mask := []byte{255, 255, 255, 0}
  92. for i := 0; i < 256; i++ {
  93. for j := 0; j < 256; j++ {
  94. pl = append(pl, &net.IPNet{IP: []byte{10, byte(i), byte(j), 0}, Mask: mask})
  95. }
  96. }
  97. return pl
  98. }