зеркало из https://github.com/microsoft/docker.git
Merge pull request #8319 from MalteJ/ipv6-ipallocator
Implementing IPv6 functionality for ipallocator
This commit is contained in:
Коммит
fd19e473fc
|
@ -1,31 +1,38 @@
|
|||
package ipallocator
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"math/big"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/docker/daemon/networkdriver"
|
||||
"github.com/docker/docker/pkg/log"
|
||||
)
|
||||
|
||||
// allocatedMap is thread-unsafe set of allocated IP
|
||||
type allocatedMap struct {
|
||||
p map[uint32]struct{}
|
||||
last uint32
|
||||
begin uint32
|
||||
end uint32
|
||||
p map[string]struct{}
|
||||
last *big.Int
|
||||
begin *big.Int
|
||||
end *big.Int
|
||||
}
|
||||
|
||||
func newAllocatedMap(network *net.IPNet) *allocatedMap {
|
||||
firstIP, lastIP := networkdriver.NetworkRange(network)
|
||||
begin := ipToInt(firstIP) + 2
|
||||
end := ipToInt(lastIP) - 1
|
||||
begin := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
|
||||
end := big.NewInt(0).Sub(ipToBigInt(lastIP), big.NewInt(1))
|
||||
|
||||
// if IPv4 network, then allocation range starts at begin + 1 because begin is bridge IP
|
||||
if len(firstIP) == 4 {
|
||||
begin = begin.Add(begin, big.NewInt(1))
|
||||
}
|
||||
|
||||
return &allocatedMap{
|
||||
p: make(map[uint32]struct{}),
|
||||
p: make(map[string]struct{}),
|
||||
begin: begin,
|
||||
end: end,
|
||||
last: begin - 1, // so first allocated will be begin
|
||||
last: big.NewInt(0).Sub(begin, big.NewInt(1)), // so first allocated will be begin
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,13 +63,16 @@ func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
|
|||
}
|
||||
n := newAllocatedMap(network)
|
||||
beginIP, endIP := networkdriver.NetworkRange(subnet)
|
||||
begin, end := ipToInt(beginIP)+1, ipToInt(endIP)-1
|
||||
if !(begin >= n.begin && end <= n.end && begin < end) {
|
||||
begin := big.NewInt(0).Add(ipToBigInt(beginIP), big.NewInt(1))
|
||||
end := big.NewInt(0).Sub(ipToBigInt(endIP), big.NewInt(1))
|
||||
|
||||
// Check that subnet is within network
|
||||
if !(begin.Cmp(n.begin) >= 0 && end.Cmp(n.end) <= 0 && begin.Cmp(end) == -1) {
|
||||
return ErrBadSubnet
|
||||
}
|
||||
n.begin = begin
|
||||
n.end = end
|
||||
n.last = begin - 1
|
||||
n.begin.Set(begin)
|
||||
n.end.Set(end)
|
||||
n.last.Sub(begin, big.NewInt(1))
|
||||
allocatedIPs[key] = n
|
||||
return nil
|
||||
}
|
||||
|
@ -93,28 +103,25 @@ func ReleaseIP(network *net.IPNet, ip net.IP) error {
|
|||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
if allocated, exists := allocatedIPs[network.String()]; exists {
|
||||
pos := ipToInt(ip)
|
||||
delete(allocated.p, pos)
|
||||
delete(allocated.p, ip.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (allocated *allocatedMap) checkIP(ip net.IP) (net.IP, error) {
|
||||
pos := ipToInt(ip)
|
||||
|
||||
// Verify that the IP address has not been already allocated.
|
||||
if _, ok := allocated.p[pos]; ok {
|
||||
if _, ok := allocated.p[ip.String()]; ok {
|
||||
return nil, ErrIPAlreadyAllocated
|
||||
}
|
||||
|
||||
pos := ipToBigInt(ip)
|
||||
// Verify that the IP address is within our network range.
|
||||
if pos < allocated.begin || pos > allocated.end {
|
||||
if pos.Cmp(allocated.begin) == -1 || pos.Cmp(allocated.end) == 1 {
|
||||
return nil, ErrIPOutOfRange
|
||||
}
|
||||
|
||||
// Register the IP.
|
||||
allocated.p[pos] = struct{}{}
|
||||
allocated.last = pos
|
||||
allocated.p[ip.String()] = struct{}{}
|
||||
allocated.last.Set(pos)
|
||||
|
||||
return ip, nil
|
||||
}
|
||||
|
@ -122,29 +129,35 @@ func (allocated *allocatedMap) checkIP(ip net.IP) (net.IP, error) {
|
|||
// return an available ip if one is currently available. If not,
|
||||
// return the next available ip for the nextwork
|
||||
func (allocated *allocatedMap) getNextIP() (net.IP, error) {
|
||||
for pos := allocated.last + 1; pos != allocated.last; pos++ {
|
||||
if pos > allocated.end {
|
||||
pos = allocated.begin
|
||||
for pos := big.NewInt(0).Add(allocated.last, big.NewInt(1)); pos.Cmp(allocated.last) != 0; pos.Add(pos, big.NewInt(1)) {
|
||||
if pos.Cmp(allocated.end) == 1 {
|
||||
pos.Set(allocated.begin)
|
||||
}
|
||||
if _, ok := allocated.p[pos]; ok {
|
||||
if _, ok := allocated.p[bigIntToIP(pos).String()]; ok {
|
||||
continue
|
||||
}
|
||||
allocated.p[pos] = struct{}{}
|
||||
allocated.last = pos
|
||||
return intToIP(pos), nil
|
||||
allocated.p[bigIntToIP(pos).String()] = struct{}{}
|
||||
allocated.last.Set(pos)
|
||||
return bigIntToIP(pos), nil
|
||||
}
|
||||
return nil, ErrNoAvailableIPs
|
||||
}
|
||||
|
||||
// Converts a 4 bytes IP into a 32 bit integer
|
||||
func ipToInt(ip net.IP) uint32 {
|
||||
return binary.BigEndian.Uint32(ip.To4())
|
||||
// Converts a 4 bytes IP into a 128 bit integer
|
||||
func ipToBigInt(ip net.IP) *big.Int {
|
||||
x := big.NewInt(0)
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
return x.SetBytes(ip4)
|
||||
}
|
||||
if ip6 := ip.To16(); ip6 != nil {
|
||||
return x.SetBytes(ip6)
|
||||
}
|
||||
|
||||
log.Errorf("ipToBigInt: Wrong IP length! %s", ip)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Converts 32 bit integer into a 4 bytes IP address
|
||||
func intToIP(n uint32) net.IP {
|
||||
b := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(b, n)
|
||||
ip := net.IP(b)
|
||||
return ip
|
||||
// Converts 128 bit integer into a 4 bytes IP address
|
||||
func bigIntToIP(v *big.Int) net.IP {
|
||||
return net.IP(v.Bytes())
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package ipallocator
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
@ -10,6 +11,46 @@ func reset() {
|
|||
allocatedIPs = networkSet{}
|
||||
}
|
||||
|
||||
func TestConversion(t *testing.T) {
|
||||
ip := net.ParseIP("127.0.0.1")
|
||||
i := ipToBigInt(ip)
|
||||
if i.Cmp(big.NewInt(0x7f000001)) != 0 {
|
||||
t.Fatal("incorrect conversion")
|
||||
}
|
||||
conv := bigIntToIP(i)
|
||||
if !ip.Equal(conv) {
|
||||
t.Error(conv.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestConversionIPv6(t *testing.T) {
|
||||
ip := net.ParseIP("2a00:1450::1")
|
||||
ip2 := net.ParseIP("2a00:1450::2")
|
||||
ip3 := net.ParseIP("2a00:1450::1:1")
|
||||
i := ipToBigInt(ip)
|
||||
val, success := big.NewInt(0).SetString("2a001450000000000000000000000001", 16)
|
||||
if !success {
|
||||
t.Fatal("Hex-String to BigInt conversion failed.")
|
||||
}
|
||||
if i.Cmp(val) != 0 {
|
||||
t.Fatal("incorrent conversion")
|
||||
}
|
||||
|
||||
conv := bigIntToIP(i)
|
||||
conv2 := bigIntToIP(big.NewInt(0).Add(i, big.NewInt(1)))
|
||||
conv3 := bigIntToIP(big.NewInt(0).Add(i, big.NewInt(0x10000)))
|
||||
|
||||
if !ip.Equal(conv) {
|
||||
t.Error("2a00:1450::1 should be equal to " + conv.String())
|
||||
}
|
||||
if !ip2.Equal(conv2) {
|
||||
t.Error("2a00:1450::2 should be equal to " + conv2.String())
|
||||
}
|
||||
if !ip3.Equal(conv3) {
|
||||
t.Error("2a00:1450::1:1 should be equal to " + conv3.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequestNewIps(t *testing.T) {
|
||||
defer reset()
|
||||
network := &net.IPNet{
|
||||
|
@ -19,6 +60,7 @@ func TestRequestNewIps(t *testing.T) {
|
|||
|
||||
var ip net.IP
|
||||
var err error
|
||||
|
||||
for i := 2; i < 10; i++ {
|
||||
ip, err = RequestIP(network, nil)
|
||||
if err != nil {
|
||||
|
@ -29,7 +71,39 @@ func TestRequestNewIps(t *testing.T) {
|
|||
t.Fatalf("Expected ip %s got %s", expected, ip.String())
|
||||
}
|
||||
}
|
||||
value := intToIP(ipToInt(ip) + 1).String()
|
||||
value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip, err = RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if ip.String() != value {
|
||||
t.Fatalf("Expected to receive the next ip %s got %s", value, ip.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequestNewIpV6(t *testing.T) {
|
||||
defer reset()
|
||||
network := &net.IPNet{
|
||||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||||
}
|
||||
|
||||
var ip net.IP
|
||||
var err error
|
||||
for i := 1; i < 10; i++ {
|
||||
ip, err = RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if expected := fmt.Sprintf("2a00:1450::%d", i); ip.String() != expected {
|
||||
t.Fatalf("Expected ip %s got %s", expected, ip.String())
|
||||
}
|
||||
}
|
||||
value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -59,6 +133,23 @@ func TestReleaseIp(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestReleaseIpV6(t *testing.T) {
|
||||
defer reset()
|
||||
network := &net.IPNet{
|
||||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||||
}
|
||||
|
||||
ip, err := RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetReleasedIp(t *testing.T) {
|
||||
defer reset()
|
||||
network := &net.IPNet{
|
||||
|
@ -97,6 +188,44 @@ func TestGetReleasedIp(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetReleasedIpV6(t *testing.T) {
|
||||
defer reset()
|
||||
network := &net.IPNet{
|
||||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0},
|
||||
}
|
||||
|
||||
ip, err := RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
value := ip.String()
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := 0; i < 253; i++ {
|
||||
_, err = RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ReleaseIP(network, ip)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
ip, err = RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if ip.String() != value {
|
||||
t.Fatalf("Expected to receive same ip %s got %s", value, ip.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequestSpecificIp(t *testing.T) {
|
||||
defer reset()
|
||||
network := &net.IPNet{
|
||||
|
@ -122,15 +251,28 @@ func TestRequestSpecificIp(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestConversion(t *testing.T) {
|
||||
ip := net.ParseIP("127.0.0.1")
|
||||
i := ipToInt(ip)
|
||||
if i == 0 {
|
||||
t.Fatal("converted to zero")
|
||||
func TestRequestSpecificIpV6(t *testing.T) {
|
||||
defer reset()
|
||||
network := &net.IPNet{
|
||||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||||
}
|
||||
conv := intToIP(i)
|
||||
if !ip.Equal(conv) {
|
||||
t.Error(conv.String())
|
||||
|
||||
ip := net.ParseIP("2a00:1450::5")
|
||||
|
||||
// Request a "good" IP.
|
||||
if _, err := RequestIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Request the same IP again.
|
||||
if _, err := RequestIP(network, ip); err != ErrIPAlreadyAllocated {
|
||||
t.Fatalf("Got the same IP twice: %#v", err)
|
||||
}
|
||||
|
||||
// Request an out of range IP.
|
||||
if _, err := RequestIP(network, net.ParseIP("2a00:1500::1")); err != ErrIPOutOfRange {
|
||||
t.Fatalf("Got an out of range IP: %#v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,6 +286,7 @@ func TestIPAllocator(t *testing.T) {
|
|||
}
|
||||
|
||||
gwIP, n, _ := net.ParseCIDR("127.0.0.1/29")
|
||||
|
||||
network := &net.IPNet{IP: gwIP, Mask: n.Mask}
|
||||
// Pool after initialisation (f = free, u = used)
|
||||
// 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
|
||||
|
@ -237,13 +380,13 @@ func TestAllocateFirstIP(t *testing.T) {
|
|||
}
|
||||
|
||||
firstIP := network.IP.To4().Mask(network.Mask)
|
||||
first := ipToInt(firstIP) + 1
|
||||
first := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
|
||||
|
||||
ip, err := RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
allocated := ipToInt(ip)
|
||||
allocated := ipToBigInt(ip)
|
||||
|
||||
if allocated == first {
|
||||
t.Fatalf("allocated ip should not equal first ip: %d == %d", first, allocated)
|
||||
|
@ -301,11 +444,24 @@ func TestAllocateDifferentSubnets(t *testing.T) {
|
|||
IP: []byte{127, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 0},
|
||||
}
|
||||
network3 := &net.IPNet{
|
||||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||||
}
|
||||
network4 := &net.IPNet{
|
||||
IP: []byte{0x2a, 0x00, 0x16, 0x32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||||
}
|
||||
expectedIPs := []net.IP{
|
||||
0: net.IPv4(192, 168, 0, 2),
|
||||
1: net.IPv4(192, 168, 0, 3),
|
||||
2: net.IPv4(127, 0, 0, 2),
|
||||
3: net.IPv4(127, 0, 0, 3),
|
||||
4: net.ParseIP("2a00:1450::1"),
|
||||
5: net.ParseIP("2a00:1450::2"),
|
||||
6: net.ParseIP("2a00:1450::3"),
|
||||
7: net.ParseIP("2a00:1632::1"),
|
||||
8: net.ParseIP("2a00:1632::2"),
|
||||
}
|
||||
|
||||
ip11, err := RequestIP(network1, nil)
|
||||
|
@ -324,11 +480,37 @@ func TestAllocateDifferentSubnets(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip31, err := RequestIP(network3, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip32, err := RequestIP(network3, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip33, err := RequestIP(network3, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip41, err := RequestIP(network4, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip42, err := RequestIP(network4, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertIPEquals(t, expectedIPs[0], ip11)
|
||||
assertIPEquals(t, expectedIPs[1], ip12)
|
||||
assertIPEquals(t, expectedIPs[2], ip21)
|
||||
assertIPEquals(t, expectedIPs[3], ip22)
|
||||
assertIPEquals(t, expectedIPs[4], ip31)
|
||||
assertIPEquals(t, expectedIPs[5], ip32)
|
||||
assertIPEquals(t, expectedIPs[6], ip33)
|
||||
assertIPEquals(t, expectedIPs[7], ip41)
|
||||
assertIPEquals(t, expectedIPs[8], ip42)
|
||||
}
|
||||
|
||||
func TestRegisterBadTwice(t *testing.T) {
|
||||
defer reset()
|
||||
network := &net.IPNet{
|
||||
|
@ -378,6 +560,7 @@ func TestAllocateFromRange(t *testing.T) {
|
|||
IP: []byte{192, 168, 0, 8},
|
||||
Mask: []byte{255, 255, 255, 248},
|
||||
}
|
||||
|
||||
if err := RegisterSubnet(network, subnet); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -122,9 +122,6 @@ func TestNetworkRange(t *testing.T) {
|
|||
if !last.Equal(net.ParseIP("192.168.0.255")) {
|
||||
t.Error(last.String())
|
||||
}
|
||||
if size := NetworkSize(network.Mask); size != 256 {
|
||||
t.Error(size)
|
||||
}
|
||||
|
||||
// Class A test
|
||||
_, network, _ = net.ParseCIDR("10.0.0.1/8")
|
||||
|
@ -135,9 +132,6 @@ func TestNetworkRange(t *testing.T) {
|
|||
if !last.Equal(net.ParseIP("10.255.255.255")) {
|
||||
t.Error(last.String())
|
||||
}
|
||||
if size := NetworkSize(network.Mask); size != 16777216 {
|
||||
t.Error(size)
|
||||
}
|
||||
|
||||
// Class A, random IP address
|
||||
_, network, _ = net.ParseCIDR("10.1.2.3/8")
|
||||
|
@ -158,9 +152,6 @@ func TestNetworkRange(t *testing.T) {
|
|||
if !last.Equal(net.ParseIP("10.1.2.3")) {
|
||||
t.Error(last.String())
|
||||
}
|
||||
if size := NetworkSize(network.Mask); size != 1 {
|
||||
t.Error(size)
|
||||
}
|
||||
|
||||
// 31bit mask
|
||||
_, network, _ = net.ParseCIDR("10.1.2.3/31")
|
||||
|
@ -171,9 +162,6 @@ func TestNetworkRange(t *testing.T) {
|
|||
if !last.Equal(net.ParseIP("10.1.2.3")) {
|
||||
t.Error(last.String())
|
||||
}
|
||||
if size := NetworkSize(network.Mask); size != 2 {
|
||||
t.Error(size)
|
||||
}
|
||||
|
||||
// 26bit mask
|
||||
_, network, _ = net.ParseCIDR("10.1.2.3/26")
|
||||
|
@ -184,7 +172,4 @@ func TestNetworkRange(t *testing.T) {
|
|||
if !last.Equal(net.ParseIP("10.1.2.63")) {
|
||||
t.Error(last.String())
|
||||
}
|
||||
if size := NetworkSize(network.Mask); size != 64 {
|
||||
t.Error(size)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package networkdriver
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
@ -56,25 +55,21 @@ func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
|
|||
|
||||
// Calculates the first and last IP addresses in an IPNet
|
||||
func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
|
||||
var (
|
||||
netIP = network.IP.To4()
|
||||
firstIP = netIP.Mask(network.Mask)
|
||||
lastIP = net.IPv4(0, 0, 0, 0).To4()
|
||||
)
|
||||
var netIP net.IP
|
||||
if network.IP.To4() != nil {
|
||||
netIP = network.IP.To4()
|
||||
} else if network.IP.To16() != nil {
|
||||
netIP = network.IP.To16()
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(lastIP); i++ {
|
||||
lastIP := make([]byte, len(netIP), len(netIP))
|
||||
|
||||
for i := 0; i < len(netIP); i++ {
|
||||
lastIP[i] = netIP[i] | ^network.Mask[i]
|
||||
}
|
||||
return firstIP, lastIP
|
||||
}
|
||||
|
||||
// Given a netmask, calculates the number of available hosts
|
||||
func NetworkSize(mask net.IPMask) int32 {
|
||||
m := net.IPv4Mask(0, 0, 0, 0)
|
||||
for i := 0; i < net.IPv4len; i++ {
|
||||
m[i] = ^mask[i]
|
||||
}
|
||||
return int32(binary.BigEndian.Uint32(m)) + 1
|
||||
return netIP.Mask(network.Mask), net.IP(lastIP)
|
||||
}
|
||||
|
||||
// Return the IPv4 address of a network interface
|
||||
|
@ -90,7 +85,7 @@ func GetIfaceAddr(name string) (net.Addr, error) {
|
|||
var addrs4 []net.Addr
|
||||
for _, addr := range addrs {
|
||||
ip := (addr.(*net.IPNet)).IP
|
||||
if ip4 := ip.To4(); len(ip4) == net.IPv4len {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
addrs4 = append(addrs4, addr)
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче