Browse code

Implementing IPv6 functionality for ipallocator

Closes #6975

Signed-off-by: Malte Janduda <mail@janduda.net>

Malte Janduda authored on 2014/10/01 00:00:24
Showing 4 changed files
... ...
@@ -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
 	}