github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/network/subnets/selectors.go (about) 1 package subnets 2 3 import ( 4 "fmt" 5 "net" 6 ) 7 8 // StaticSubnetSelector requests a specific ("static") subnet. Returns an error if the subnet is already allocated. 9 type StaticSubnetSelector struct { 10 *net.IPNet 11 } 12 13 func (s StaticSubnetSelector) SelectSubnet(dynamic *net.IPNet, existing []*net.IPNet) (*net.IPNet, error) { 14 if overlaps(dynamic, s.IPNet) { 15 return nil, fmt.Errorf("the requested subnet (%v) overlaps the dynamic allocation range (%v)", s.IPNet.String(), dynamic.String()) 16 } 17 18 for _, e := range existing { 19 if overlaps(s.IPNet, e) && !equals(s.IPNet, e) { 20 return nil, fmt.Errorf("the requested subnet (%v) overlaps an existing subnet (%v)", s.IPNet.String(), e.String()) 21 } 22 } 23 24 return s.IPNet, nil 25 } 26 27 type dynamicSubnetSelector int 28 29 // DynamicSubnetSelector requests the next unallocated ("dynamic") subnet from the dynamic range. 30 // Returns an error if there are no remaining subnets in the dynamic range. 31 var DynamicSubnetSelector dynamicSubnetSelector = 0 32 33 func (dynamicSubnetSelector) SelectSubnet(dynamic *net.IPNet, existing []*net.IPNet) (*net.IPNet, error) { 34 exists := make(map[string]bool) 35 for _, e := range existing { 36 exists[e.String()] = true 37 } 38 39 min := dynamic.IP 40 mask := net.CIDRMask(30, 32) // /30 41 for ip := min; dynamic.Contains(ip); ip = next(ip) { 42 subnet := &net.IPNet{ip, mask} 43 ip = next(next(next(ip))) 44 if dynamic.Contains(ip) && !exists[subnet.String()] { 45 return subnet, nil 46 } 47 } 48 49 return nil, ErrInsufficientSubnets 50 } 51 52 // StaticIPSelector requests a specific ("static") IP address. Returns an error if the IP is already 53 // allocated, or if it is outside the given subnet. 54 type StaticIPSelector struct { 55 net.IP 56 } 57 58 func (s StaticIPSelector) SelectIP(subnet *net.IPNet, existing []net.IP) (net.IP, error) { 59 if BroadcastIP(subnet).Equal(s.IP) { 60 return nil, ErrIPEqualsBroadcast 61 } 62 63 if GatewayIP(subnet).Equal(s.IP) { 64 return nil, ErrIPEqualsGateway 65 } 66 67 if !subnet.Contains(s.IP) { 68 return nil, ErrInvalidIP 69 } 70 71 for _, e := range existing { 72 if e.Equal(s.IP) { 73 return nil, ErrIPAlreadyAcquired 74 } 75 } 76 77 return s.IP, nil 78 } 79 80 type dynamicIPSelector int 81 82 // DynamicIPSelector requests the next available ("dynamic") IP address from a given subnet. 83 // Returns an error if no more IP addresses remain in the subnet. 84 var DynamicIPSelector dynamicIPSelector = 0 85 86 func (dynamicIPSelector) SelectIP(subnet *net.IPNet, existing []net.IP) (net.IP, error) { 87 exists := make(map[string]bool) 88 for _, e := range existing { 89 exists[e.String()] = true 90 } 91 92 for i := subnet.IP; subnet.Contains(i); i = next(i) { 93 if !exists[i.String()] { 94 return i, nil 95 } 96 } 97 98 return nil, ErrInsufficientIPs 99 }