Closes #6975
Signed-off-by: Malte Janduda <mail@janduda.net>
| ... | ... |
@@ -1,31 +1,38 @@ |
| 1 | 1 |
package ipallocator |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "encoding/binary" |
|
| 5 | 4 |
"errors" |
| 5 |
+ "math/big" |
|
| 6 | 6 |
"net" |
| 7 | 7 |
"sync" |
| 8 | 8 |
|
| 9 | 9 |
"github.com/docker/docker/daemon/networkdriver" |
| 10 |
+ "github.com/docker/docker/pkg/log" |
|
| 10 | 11 |
) |
| 11 | 12 |
|
| 12 | 13 |
// allocatedMap is thread-unsafe set of allocated IP |
| 13 | 14 |
type allocatedMap struct {
|
| 14 |
- p map[uint32]struct{}
|
|
| 15 |
- last uint32 |
|
| 16 |
- begin uint32 |
|
| 17 |
- end uint32 |
|
| 15 |
+ p map[string]struct{}
|
|
| 16 |
+ last *big.Int |
|
| 17 |
+ begin *big.Int |
|
| 18 |
+ end *big.Int |
|
| 18 | 19 |
} |
| 19 | 20 |
|
| 20 | 21 |
func newAllocatedMap(network *net.IPNet) *allocatedMap {
|
| 21 | 22 |
firstIP, lastIP := networkdriver.NetworkRange(network) |
| 22 |
- begin := ipToInt(firstIP) + 2 |
|
| 23 |
- end := ipToInt(lastIP) - 1 |
|
| 23 |
+ begin := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1)) |
|
| 24 |
+ end := big.NewInt(0).Sub(ipToBigInt(lastIP), big.NewInt(1)) |
|
| 25 |
+ |
|
| 26 |
+ // if IPv4 network, then allocation range starts at begin + 1 because begin is bridge IP |
|
| 27 |
+ if len(firstIP) == 4 {
|
|
| 28 |
+ begin = begin.Add(begin, big.NewInt(1)) |
|
| 29 |
+ } |
|
| 30 |
+ |
|
| 24 | 31 |
return &allocatedMap{
|
| 25 |
- p: make(map[uint32]struct{}),
|
|
| 32 |
+ p: make(map[string]struct{}),
|
|
| 26 | 33 |
begin: begin, |
| 27 | 34 |
end: end, |
| 28 |
- last: begin - 1, // so first allocated will be begin |
|
| 35 |
+ last: big.NewInt(0).Sub(begin, big.NewInt(1)), // so first allocated will be begin |
|
| 29 | 36 |
} |
| 30 | 37 |
} |
| 31 | 38 |
|
| ... | ... |
@@ -56,13 +63,16 @@ func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
|
| 56 | 56 |
} |
| 57 | 57 |
n := newAllocatedMap(network) |
| 58 | 58 |
beginIP, endIP := networkdriver.NetworkRange(subnet) |
| 59 |
- begin, end := ipToInt(beginIP)+1, ipToInt(endIP)-1 |
|
| 60 |
- if !(begin >= n.begin && end <= n.end && begin < end) {
|
|
| 59 |
+ begin := big.NewInt(0).Add(ipToBigInt(beginIP), big.NewInt(1)) |
|
| 60 |
+ end := big.NewInt(0).Sub(ipToBigInt(endIP), big.NewInt(1)) |
|
| 61 |
+ |
|
| 62 |
+ // Check that subnet is within network |
|
| 63 |
+ if !(begin.Cmp(n.begin) >= 0 && end.Cmp(n.end) <= 0 && begin.Cmp(end) == -1) {
|
|
| 61 | 64 |
return ErrBadSubnet |
| 62 | 65 |
} |
| 63 |
- n.begin = begin |
|
| 64 |
- n.end = end |
|
| 65 |
- n.last = begin - 1 |
|
| 66 |
+ n.begin.Set(begin) |
|
| 67 |
+ n.end.Set(end) |
|
| 68 |
+ n.last.Sub(begin, big.NewInt(1)) |
|
| 66 | 69 |
allocatedIPs[key] = n |
| 67 | 70 |
return nil |
| 68 | 71 |
} |
| ... | ... |
@@ -93,28 +103,25 @@ func ReleaseIP(network *net.IPNet, ip net.IP) error {
|
| 93 | 93 |
lock.Lock() |
| 94 | 94 |
defer lock.Unlock() |
| 95 | 95 |
if allocated, exists := allocatedIPs[network.String()]; exists {
|
| 96 |
- pos := ipToInt(ip) |
|
| 97 |
- delete(allocated.p, pos) |
|
| 96 |
+ delete(allocated.p, ip.String()) |
|
| 98 | 97 |
} |
| 99 | 98 |
return nil |
| 100 | 99 |
} |
| 101 | 100 |
|
| 102 | 101 |
func (allocated *allocatedMap) checkIP(ip net.IP) (net.IP, error) {
|
| 103 |
- pos := ipToInt(ip) |
|
| 104 |
- |
|
| 105 |
- // Verify that the IP address has not been already allocated. |
|
| 106 |
- if _, ok := allocated.p[pos]; ok {
|
|
| 102 |
+ if _, ok := allocated.p[ip.String()]; ok {
|
|
| 107 | 103 |
return nil, ErrIPAlreadyAllocated |
| 108 | 104 |
} |
| 109 | 105 |
|
| 106 |
+ pos := ipToBigInt(ip) |
|
| 110 | 107 |
// Verify that the IP address is within our network range. |
| 111 |
- if pos < allocated.begin || pos > allocated.end {
|
|
| 108 |
+ if pos.Cmp(allocated.begin) == -1 || pos.Cmp(allocated.end) == 1 {
|
|
| 112 | 109 |
return nil, ErrIPOutOfRange |
| 113 | 110 |
} |
| 114 | 111 |
|
| 115 | 112 |
// Register the IP. |
| 116 |
- allocated.p[pos] = struct{}{}
|
|
| 117 |
- allocated.last = pos |
|
| 113 |
+ allocated.p[ip.String()] = struct{}{}
|
|
| 114 |
+ allocated.last.Set(pos) |
|
| 118 | 115 |
|
| 119 | 116 |
return ip, nil |
| 120 | 117 |
} |
| ... | ... |
@@ -122,29 +129,35 @@ func (allocated *allocatedMap) checkIP(ip net.IP) (net.IP, error) {
|
| 122 | 122 |
// return an available ip if one is currently available. If not, |
| 123 | 123 |
// return the next available ip for the nextwork |
| 124 | 124 |
func (allocated *allocatedMap) getNextIP() (net.IP, error) {
|
| 125 |
- for pos := allocated.last + 1; pos != allocated.last; pos++ {
|
|
| 126 |
- if pos > allocated.end {
|
|
| 127 |
- pos = allocated.begin |
|
| 125 |
+ for pos := big.NewInt(0).Add(allocated.last, big.NewInt(1)); pos.Cmp(allocated.last) != 0; pos.Add(pos, big.NewInt(1)) {
|
|
| 126 |
+ if pos.Cmp(allocated.end) == 1 {
|
|
| 127 |
+ pos.Set(allocated.begin) |
|
| 128 | 128 |
} |
| 129 |
- if _, ok := allocated.p[pos]; ok {
|
|
| 129 |
+ if _, ok := allocated.p[bigIntToIP(pos).String()]; ok {
|
|
| 130 | 130 |
continue |
| 131 | 131 |
} |
| 132 |
- allocated.p[pos] = struct{}{}
|
|
| 133 |
- allocated.last = pos |
|
| 134 |
- return intToIP(pos), nil |
|
| 132 |
+ allocated.p[bigIntToIP(pos).String()] = struct{}{}
|
|
| 133 |
+ allocated.last.Set(pos) |
|
| 134 |
+ return bigIntToIP(pos), nil |
|
| 135 | 135 |
} |
| 136 | 136 |
return nil, ErrNoAvailableIPs |
| 137 | 137 |
} |
| 138 | 138 |
|
| 139 |
-// Converts a 4 bytes IP into a 32 bit integer |
|
| 140 |
-func ipToInt(ip net.IP) uint32 {
|
|
| 141 |
- return binary.BigEndian.Uint32(ip.To4()) |
|
| 139 |
+// Converts a 4 bytes IP into a 128 bit integer |
|
| 140 |
+func ipToBigInt(ip net.IP) *big.Int {
|
|
| 141 |
+ x := big.NewInt(0) |
|
| 142 |
+ if ip4 := ip.To4(); ip4 != nil {
|
|
| 143 |
+ return x.SetBytes(ip4) |
|
| 144 |
+ } |
|
| 145 |
+ if ip6 := ip.To16(); ip6 != nil {
|
|
| 146 |
+ return x.SetBytes(ip6) |
|
| 147 |
+ } |
|
| 148 |
+ |
|
| 149 |
+ log.Errorf("ipToBigInt: Wrong IP length! %s", ip)
|
|
| 150 |
+ return nil |
|
| 142 | 151 |
} |
| 143 | 152 |
|
| 144 |
-// Converts 32 bit integer into a 4 bytes IP address |
|
| 145 |
-func intToIP(n uint32) net.IP {
|
|
| 146 |
- b := make([]byte, 4) |
|
| 147 |
- binary.BigEndian.PutUint32(b, n) |
|
| 148 |
- ip := net.IP(b) |
|
| 149 |
- return ip |
|
| 153 |
+// Converts 128 bit integer into a 4 bytes IP address |
|
| 154 |
+func bigIntToIP(v *big.Int) net.IP {
|
|
| 155 |
+ return net.IP(v.Bytes()) |
|
| 150 | 156 |
} |
| ... | ... |
@@ -2,6 +2,7 @@ package ipallocator |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 |
+ "math/big" |
|
| 5 | 6 |
"net" |
| 6 | 7 |
"testing" |
| 7 | 8 |
) |
| ... | ... |
@@ -10,6 +11,46 @@ func reset() {
|
| 10 | 10 |
allocatedIPs = networkSet{}
|
| 11 | 11 |
} |
| 12 | 12 |
|
| 13 |
+func TestConversion(t *testing.T) {
|
|
| 14 |
+ ip := net.ParseIP("127.0.0.1")
|
|
| 15 |
+ i := ipToBigInt(ip) |
|
| 16 |
+ if i.Cmp(big.NewInt(0x7f000001)) != 0 {
|
|
| 17 |
+ t.Fatal("incorrect conversion")
|
|
| 18 |
+ } |
|
| 19 |
+ conv := bigIntToIP(i) |
|
| 20 |
+ if !ip.Equal(conv) {
|
|
| 21 |
+ t.Error(conv.String()) |
|
| 22 |
+ } |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 25 |
+func TestConversionIPv6(t *testing.T) {
|
|
| 26 |
+ ip := net.ParseIP("2a00:1450::1")
|
|
| 27 |
+ ip2 := net.ParseIP("2a00:1450::2")
|
|
| 28 |
+ ip3 := net.ParseIP("2a00:1450::1:1")
|
|
| 29 |
+ i := ipToBigInt(ip) |
|
| 30 |
+ val, success := big.NewInt(0).SetString("2a001450000000000000000000000001", 16)
|
|
| 31 |
+ if !success {
|
|
| 32 |
+ t.Fatal("Hex-String to BigInt conversion failed.")
|
|
| 33 |
+ } |
|
| 34 |
+ if i.Cmp(val) != 0 {
|
|
| 35 |
+ t.Fatal("incorrent conversion")
|
|
| 36 |
+ } |
|
| 37 |
+ |
|
| 38 |
+ conv := bigIntToIP(i) |
|
| 39 |
+ conv2 := bigIntToIP(big.NewInt(0).Add(i, big.NewInt(1))) |
|
| 40 |
+ conv3 := bigIntToIP(big.NewInt(0).Add(i, big.NewInt(0x10000))) |
|
| 41 |
+ |
|
| 42 |
+ if !ip.Equal(conv) {
|
|
| 43 |
+ t.Error("2a00:1450::1 should be equal to " + conv.String())
|
|
| 44 |
+ } |
|
| 45 |
+ if !ip2.Equal(conv2) {
|
|
| 46 |
+ t.Error("2a00:1450::2 should be equal to " + conv2.String())
|
|
| 47 |
+ } |
|
| 48 |
+ if !ip3.Equal(conv3) {
|
|
| 49 |
+ t.Error("2a00:1450::1:1 should be equal to " + conv3.String())
|
|
| 50 |
+ } |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 13 | 53 |
func TestRequestNewIps(t *testing.T) {
|
| 14 | 54 |
defer reset() |
| 15 | 55 |
network := &net.IPNet{
|
| ... | ... |
@@ -19,6 +60,7 @@ func TestRequestNewIps(t *testing.T) {
|
| 19 | 19 |
|
| 20 | 20 |
var ip net.IP |
| 21 | 21 |
var err error |
| 22 |
+ |
|
| 22 | 23 |
for i := 2; i < 10; i++ {
|
| 23 | 24 |
ip, err = RequestIP(network, nil) |
| 24 | 25 |
if err != nil {
|
| ... | ... |
@@ -29,7 +71,39 @@ func TestRequestNewIps(t *testing.T) {
|
| 29 | 29 |
t.Fatalf("Expected ip %s got %s", expected, ip.String())
|
| 30 | 30 |
} |
| 31 | 31 |
} |
| 32 |
- value := intToIP(ipToInt(ip) + 1).String() |
|
| 32 |
+ value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String() |
|
| 33 |
+ if err := ReleaseIP(network, ip); err != nil {
|
|
| 34 |
+ t.Fatal(err) |
|
| 35 |
+ } |
|
| 36 |
+ ip, err = RequestIP(network, nil) |
|
| 37 |
+ if err != nil {
|
|
| 38 |
+ t.Fatal(err) |
|
| 39 |
+ } |
|
| 40 |
+ if ip.String() != value {
|
|
| 41 |
+ t.Fatalf("Expected to receive the next ip %s got %s", value, ip.String())
|
|
| 42 |
+ } |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 45 |
+func TestRequestNewIpV6(t *testing.T) {
|
|
| 46 |
+ defer reset() |
|
| 47 |
+ network := &net.IPNet{
|
|
| 48 |
+ IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
| 49 |
+ Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ var ip net.IP |
|
| 53 |
+ var err error |
|
| 54 |
+ for i := 1; i < 10; i++ {
|
|
| 55 |
+ ip, err = RequestIP(network, nil) |
|
| 56 |
+ if err != nil {
|
|
| 57 |
+ t.Fatal(err) |
|
| 58 |
+ } |
|
| 59 |
+ |
|
| 60 |
+ if expected := fmt.Sprintf("2a00:1450::%d", i); ip.String() != expected {
|
|
| 61 |
+ t.Fatalf("Expected ip %s got %s", expected, ip.String())
|
|
| 62 |
+ } |
|
| 63 |
+ } |
|
| 64 |
+ value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String() |
|
| 33 | 65 |
if err := ReleaseIP(network, ip); err != nil {
|
| 34 | 66 |
t.Fatal(err) |
| 35 | 67 |
} |
| ... | ... |
@@ -59,6 +133,23 @@ func TestReleaseIp(t *testing.T) {
|
| 59 | 59 |
} |
| 60 | 60 |
} |
| 61 | 61 |
|
| 62 |
+func TestReleaseIpV6(t *testing.T) {
|
|
| 63 |
+ defer reset() |
|
| 64 |
+ network := &net.IPNet{
|
|
| 65 |
+ IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
| 66 |
+ Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
|
| 67 |
+ } |
|
| 68 |
+ |
|
| 69 |
+ ip, err := RequestIP(network, nil) |
|
| 70 |
+ if err != nil {
|
|
| 71 |
+ t.Fatal(err) |
|
| 72 |
+ } |
|
| 73 |
+ |
|
| 74 |
+ if err := ReleaseIP(network, ip); err != nil {
|
|
| 75 |
+ t.Fatal(err) |
|
| 76 |
+ } |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 62 | 79 |
func TestGetReleasedIp(t *testing.T) {
|
| 63 | 80 |
defer reset() |
| 64 | 81 |
network := &net.IPNet{
|
| ... | ... |
@@ -97,6 +188,44 @@ func TestGetReleasedIp(t *testing.T) {
|
| 97 | 97 |
} |
| 98 | 98 |
} |
| 99 | 99 |
|
| 100 |
+func TestGetReleasedIpV6(t *testing.T) {
|
|
| 101 |
+ defer reset() |
|
| 102 |
+ network := &net.IPNet{
|
|
| 103 |
+ IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
| 104 |
+ Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0},
|
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ ip, err := RequestIP(network, nil) |
|
| 108 |
+ if err != nil {
|
|
| 109 |
+ t.Fatal(err) |
|
| 110 |
+ } |
|
| 111 |
+ |
|
| 112 |
+ value := ip.String() |
|
| 113 |
+ if err := ReleaseIP(network, ip); err != nil {
|
|
| 114 |
+ t.Fatal(err) |
|
| 115 |
+ } |
|
| 116 |
+ |
|
| 117 |
+ for i := 0; i < 253; i++ {
|
|
| 118 |
+ _, err = RequestIP(network, nil) |
|
| 119 |
+ if err != nil {
|
|
| 120 |
+ t.Fatal(err) |
|
| 121 |
+ } |
|
| 122 |
+ err = ReleaseIP(network, ip) |
|
| 123 |
+ if err != nil {
|
|
| 124 |
+ t.Fatal(err) |
|
| 125 |
+ } |
|
| 126 |
+ } |
|
| 127 |
+ |
|
| 128 |
+ ip, err = RequestIP(network, nil) |
|
| 129 |
+ if err != nil {
|
|
| 130 |
+ t.Fatal(err) |
|
| 131 |
+ } |
|
| 132 |
+ |
|
| 133 |
+ if ip.String() != value {
|
|
| 134 |
+ t.Fatalf("Expected to receive same ip %s got %s", value, ip.String())
|
|
| 135 |
+ } |
|
| 136 |
+} |
|
| 137 |
+ |
|
| 100 | 138 |
func TestRequestSpecificIp(t *testing.T) {
|
| 101 | 139 |
defer reset() |
| 102 | 140 |
network := &net.IPNet{
|
| ... | ... |
@@ -122,15 +251,28 @@ func TestRequestSpecificIp(t *testing.T) {
|
| 122 | 122 |
} |
| 123 | 123 |
} |
| 124 | 124 |
|
| 125 |
-func TestConversion(t *testing.T) {
|
|
| 126 |
- ip := net.ParseIP("127.0.0.1")
|
|
| 127 |
- i := ipToInt(ip) |
|
| 128 |
- if i == 0 {
|
|
| 129 |
- t.Fatal("converted to zero")
|
|
| 125 |
+func TestRequestSpecificIpV6(t *testing.T) {
|
|
| 126 |
+ defer reset() |
|
| 127 |
+ network := &net.IPNet{
|
|
| 128 |
+ IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
| 129 |
+ Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
|
| 130 | 130 |
} |
| 131 |
- conv := intToIP(i) |
|
| 132 |
- if !ip.Equal(conv) {
|
|
| 133 |
- t.Error(conv.String()) |
|
| 131 |
+ |
|
| 132 |
+ ip := net.ParseIP("2a00:1450::5")
|
|
| 133 |
+ |
|
| 134 |
+ // Request a "good" IP. |
|
| 135 |
+ if _, err := RequestIP(network, ip); err != nil {
|
|
| 136 |
+ t.Fatal(err) |
|
| 137 |
+ } |
|
| 138 |
+ |
|
| 139 |
+ // Request the same IP again. |
|
| 140 |
+ if _, err := RequestIP(network, ip); err != ErrIPAlreadyAllocated {
|
|
| 141 |
+ t.Fatalf("Got the same IP twice: %#v", err)
|
|
| 142 |
+ } |
|
| 143 |
+ |
|
| 144 |
+ // Request an out of range IP. |
|
| 145 |
+ if _, err := RequestIP(network, net.ParseIP("2a00:1500::1")); err != ErrIPOutOfRange {
|
|
| 146 |
+ t.Fatalf("Got an out of range IP: %#v", err)
|
|
| 134 | 147 |
} |
| 135 | 148 |
} |
| 136 | 149 |
|
| ... | ... |
@@ -144,6 +286,7 @@ func TestIPAllocator(t *testing.T) {
|
| 144 | 144 |
} |
| 145 | 145 |
|
| 146 | 146 |
gwIP, n, _ := net.ParseCIDR("127.0.0.1/29")
|
| 147 |
+ |
|
| 147 | 148 |
network := &net.IPNet{IP: gwIP, Mask: n.Mask}
|
| 148 | 149 |
// Pool after initialisation (f = free, u = used) |
| 149 | 150 |
// 2(f) - 3(f) - 4(f) - 5(f) - 6(f) |
| ... | ... |
@@ -237,13 +380,13 @@ func TestAllocateFirstIP(t *testing.T) {
|
| 237 | 237 |
} |
| 238 | 238 |
|
| 239 | 239 |
firstIP := network.IP.To4().Mask(network.Mask) |
| 240 |
- first := ipToInt(firstIP) + 1 |
|
| 240 |
+ first := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1)) |
|
| 241 | 241 |
|
| 242 | 242 |
ip, err := RequestIP(network, nil) |
| 243 | 243 |
if err != nil {
|
| 244 | 244 |
t.Fatal(err) |
| 245 | 245 |
} |
| 246 |
- allocated := ipToInt(ip) |
|
| 246 |
+ allocated := ipToBigInt(ip) |
|
| 247 | 247 |
|
| 248 | 248 |
if allocated == first {
|
| 249 | 249 |
t.Fatalf("allocated ip should not equal first ip: %d == %d", first, allocated)
|
| ... | ... |
@@ -301,11 +444,24 @@ func TestAllocateDifferentSubnets(t *testing.T) {
|
| 301 | 301 |
IP: []byte{127, 0, 0, 1},
|
| 302 | 302 |
Mask: []byte{255, 255, 255, 0},
|
| 303 | 303 |
} |
| 304 |
+ network3 := &net.IPNet{
|
|
| 305 |
+ IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
| 306 |
+ Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
|
| 307 |
+ } |
|
| 308 |
+ network4 := &net.IPNet{
|
|
| 309 |
+ IP: []byte{0x2a, 0x00, 0x16, 0x32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
| 310 |
+ Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
|
| 311 |
+ } |
|
| 304 | 312 |
expectedIPs := []net.IP{
|
| 305 | 313 |
0: net.IPv4(192, 168, 0, 2), |
| 306 | 314 |
1: net.IPv4(192, 168, 0, 3), |
| 307 | 315 |
2: net.IPv4(127, 0, 0, 2), |
| 308 | 316 |
3: net.IPv4(127, 0, 0, 3), |
| 317 |
+ 4: net.ParseIP("2a00:1450::1"),
|
|
| 318 |
+ 5: net.ParseIP("2a00:1450::2"),
|
|
| 319 |
+ 6: net.ParseIP("2a00:1450::3"),
|
|
| 320 |
+ 7: net.ParseIP("2a00:1632::1"),
|
|
| 321 |
+ 8: net.ParseIP("2a00:1632::2"),
|
|
| 309 | 322 |
} |
| 310 | 323 |
|
| 311 | 324 |
ip11, err := RequestIP(network1, nil) |
| ... | ... |
@@ -324,11 +480,37 @@ func TestAllocateDifferentSubnets(t *testing.T) {
|
| 324 | 324 |
if err != nil {
|
| 325 | 325 |
t.Fatal(err) |
| 326 | 326 |
} |
| 327 |
+ ip31, err := RequestIP(network3, nil) |
|
| 328 |
+ if err != nil {
|
|
| 329 |
+ t.Fatal(err) |
|
| 330 |
+ } |
|
| 331 |
+ ip32, err := RequestIP(network3, nil) |
|
| 332 |
+ if err != nil {
|
|
| 333 |
+ t.Fatal(err) |
|
| 334 |
+ } |
|
| 335 |
+ ip33, err := RequestIP(network3, nil) |
|
| 336 |
+ if err != nil {
|
|
| 337 |
+ t.Fatal(err) |
|
| 338 |
+ } |
|
| 339 |
+ ip41, err := RequestIP(network4, nil) |
|
| 340 |
+ if err != nil {
|
|
| 341 |
+ t.Fatal(err) |
|
| 342 |
+ } |
|
| 343 |
+ ip42, err := RequestIP(network4, nil) |
|
| 344 |
+ if err != nil {
|
|
| 345 |
+ t.Fatal(err) |
|
| 346 |
+ } |
|
| 327 | 347 |
assertIPEquals(t, expectedIPs[0], ip11) |
| 328 | 348 |
assertIPEquals(t, expectedIPs[1], ip12) |
| 329 | 349 |
assertIPEquals(t, expectedIPs[2], ip21) |
| 330 | 350 |
assertIPEquals(t, expectedIPs[3], ip22) |
| 351 |
+ assertIPEquals(t, expectedIPs[4], ip31) |
|
| 352 |
+ assertIPEquals(t, expectedIPs[5], ip32) |
|
| 353 |
+ assertIPEquals(t, expectedIPs[6], ip33) |
|
| 354 |
+ assertIPEquals(t, expectedIPs[7], ip41) |
|
| 355 |
+ assertIPEquals(t, expectedIPs[8], ip42) |
|
| 331 | 356 |
} |
| 357 |
+ |
|
| 332 | 358 |
func TestRegisterBadTwice(t *testing.T) {
|
| 333 | 359 |
defer reset() |
| 334 | 360 |
network := &net.IPNet{
|
| ... | ... |
@@ -378,6 +560,7 @@ func TestAllocateFromRange(t *testing.T) {
|
| 378 | 378 |
IP: []byte{192, 168, 0, 8},
|
| 379 | 379 |
Mask: []byte{255, 255, 255, 248},
|
| 380 | 380 |
} |
| 381 |
+ |
|
| 381 | 382 |
if err := RegisterSubnet(network, subnet); err != nil {
|
| 382 | 383 |
t.Fatal(err) |
| 383 | 384 |
} |
| ... | ... |
@@ -122,9 +122,6 @@ func TestNetworkRange(t *testing.T) {
|
| 122 | 122 |
if !last.Equal(net.ParseIP("192.168.0.255")) {
|
| 123 | 123 |
t.Error(last.String()) |
| 124 | 124 |
} |
| 125 |
- if size := NetworkSize(network.Mask); size != 256 {
|
|
| 126 |
- t.Error(size) |
|
| 127 |
- } |
|
| 128 | 125 |
|
| 129 | 126 |
// Class A test |
| 130 | 127 |
_, network, _ = net.ParseCIDR("10.0.0.1/8")
|
| ... | ... |
@@ -135,9 +132,6 @@ func TestNetworkRange(t *testing.T) {
|
| 135 | 135 |
if !last.Equal(net.ParseIP("10.255.255.255")) {
|
| 136 | 136 |
t.Error(last.String()) |
| 137 | 137 |
} |
| 138 |
- if size := NetworkSize(network.Mask); size != 16777216 {
|
|
| 139 |
- t.Error(size) |
|
| 140 |
- } |
|
| 141 | 138 |
|
| 142 | 139 |
// Class A, random IP address |
| 143 | 140 |
_, network, _ = net.ParseCIDR("10.1.2.3/8")
|
| ... | ... |
@@ -158,9 +152,6 @@ func TestNetworkRange(t *testing.T) {
|
| 158 | 158 |
if !last.Equal(net.ParseIP("10.1.2.3")) {
|
| 159 | 159 |
t.Error(last.String()) |
| 160 | 160 |
} |
| 161 |
- if size := NetworkSize(network.Mask); size != 1 {
|
|
| 162 |
- t.Error(size) |
|
| 163 |
- } |
|
| 164 | 161 |
|
| 165 | 162 |
// 31bit mask |
| 166 | 163 |
_, network, _ = net.ParseCIDR("10.1.2.3/31")
|
| ... | ... |
@@ -171,9 +162,6 @@ func TestNetworkRange(t *testing.T) {
|
| 171 | 171 |
if !last.Equal(net.ParseIP("10.1.2.3")) {
|
| 172 | 172 |
t.Error(last.String()) |
| 173 | 173 |
} |
| 174 |
- if size := NetworkSize(network.Mask); size != 2 {
|
|
| 175 |
- t.Error(size) |
|
| 176 |
- } |
|
| 177 | 174 |
|
| 178 | 175 |
// 26bit mask |
| 179 | 176 |
_, network, _ = net.ParseCIDR("10.1.2.3/26")
|
| ... | ... |
@@ -184,7 +172,4 @@ func TestNetworkRange(t *testing.T) {
|
| 184 | 184 |
if !last.Equal(net.ParseIP("10.1.2.63")) {
|
| 185 | 185 |
t.Error(last.String()) |
| 186 | 186 |
} |
| 187 |
- if size := NetworkSize(network.Mask); size != 64 {
|
|
| 188 |
- t.Error(size) |
|
| 189 |
- } |
|
| 190 | 187 |
} |
| ... | ... |
@@ -1,7 +1,6 @@ |
| 1 | 1 |
package networkdriver |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "encoding/binary" |
|
| 5 | 4 |
"errors" |
| 6 | 5 |
"fmt" |
| 7 | 6 |
"net" |
| ... | ... |
@@ -56,25 +55,21 @@ func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
|
| 56 | 56 |
|
| 57 | 57 |
// Calculates the first and last IP addresses in an IPNet |
| 58 | 58 |
func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
|
| 59 |
- var ( |
|
| 60 |
- netIP = network.IP.To4() |
|
| 61 |
- firstIP = netIP.Mask(network.Mask) |
|
| 62 |
- lastIP = net.IPv4(0, 0, 0, 0).To4() |
|
| 63 |
- ) |
|
| 64 |
- |
|
| 65 |
- for i := 0; i < len(lastIP); i++ {
|
|
| 66 |
- lastIP[i] = netIP[i] | ^network.Mask[i] |
|
| 59 |
+ var netIP net.IP |
|
| 60 |
+ if network.IP.To4() != nil {
|
|
| 61 |
+ netIP = network.IP.To4() |
|
| 62 |
+ } else if network.IP.To16() != nil {
|
|
| 63 |
+ netIP = network.IP.To16() |
|
| 64 |
+ } else {
|
|
| 65 |
+ return nil, nil |
|
| 67 | 66 |
} |
| 68 |
- return firstIP, lastIP |
|
| 69 |
-} |
|
| 70 | 67 |
|
| 71 |
-// Given a netmask, calculates the number of available hosts |
|
| 72 |
-func NetworkSize(mask net.IPMask) int32 {
|
|
| 73 |
- m := net.IPv4Mask(0, 0, 0, 0) |
|
| 74 |
- for i := 0; i < net.IPv4len; i++ {
|
|
| 75 |
- m[i] = ^mask[i] |
|
| 68 |
+ lastIP := make([]byte, len(netIP), len(netIP)) |
|
| 69 |
+ |
|
| 70 |
+ for i := 0; i < len(netIP); i++ {
|
|
| 71 |
+ lastIP[i] = netIP[i] | ^network.Mask[i] |
|
| 76 | 72 |
} |
| 77 |
- return int32(binary.BigEndian.Uint32(m)) + 1 |
|
| 73 |
+ return netIP.Mask(network.Mask), net.IP(lastIP) |
|
| 78 | 74 |
} |
| 79 | 75 |
|
| 80 | 76 |
// Return the IPv4 address of a network interface |
| ... | ... |
@@ -90,7 +85,7 @@ func GetIfaceAddr(name string) (net.Addr, error) {
|
| 90 | 90 |
var addrs4 []net.Addr |
| 91 | 91 |
for _, addr := range addrs {
|
| 92 | 92 |
ip := (addr.(*net.IPNet)).IP |
| 93 |
- if ip4 := ip.To4(); len(ip4) == net.IPv4len {
|
|
| 93 |
+ if ip4 := ip.To4(); ip4 != nil {
|
|
| 94 | 94 |
addrs4 = append(addrs4, addr) |
| 95 | 95 |
} |
| 96 | 96 |
} |