mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-29 19:43:57 +01:00
70 lines
1.9 KiB
Go
70 lines
1.9 KiB
Go
|
package server
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"fmt"
|
||
|
"net"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
upperIPv4 = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 255, 255, 255, 255}
|
||
|
upperIPv6 = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
||
|
)
|
||
|
|
||
|
type Network struct {
|
||
|
Id string
|
||
|
Net net.IPNet
|
||
|
Dns string
|
||
|
}
|
||
|
|
||
|
// AllocatePeerIP pics an available IP from an net.IPNet.
|
||
|
// This method considers already taken IPs and reuses IPs if there are gaps in takenIps
|
||
|
// E.g. if ipNet=100.30.0.0/16 and takenIps=[100.30.0.1, 100.30.0.5] then the result would be 100.30.0.2
|
||
|
func AllocatePeerIP(ipNet net.IPNet, takenIps []net.IP) (net.IP, error) {
|
||
|
takenIpMap := make(map[string]net.IP)
|
||
|
takenIpMap[ipNet.IP.String()] = ipNet.IP
|
||
|
for _, ip := range takenIps {
|
||
|
takenIpMap[ip.String()] = ip
|
||
|
}
|
||
|
for ip := ipNet.IP.Mask(ipNet.Mask); ipNet.Contains(ip); ip = GetNextIP(ip) {
|
||
|
if _, ok := takenIpMap[ip.String()]; !ok {
|
||
|
return ip, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil, fmt.Errorf("failed allocating new IP for the ipNet %s and takenIps %s", ipNet.String(), takenIps)
|
||
|
}
|
||
|
|
||
|
// GetNextIP returns the next IP from the given IP address. If the given IP is
|
||
|
// the last IP of a v4 or v6 range, the same IP is returned.
|
||
|
// Credits to Cilium team.
|
||
|
// Copyright 2017-2020 Authors of Cilium
|
||
|
func GetNextIP(ip net.IP) net.IP {
|
||
|
if ip.Equal(upperIPv4) || ip.Equal(upperIPv6) {
|
||
|
return ip
|
||
|
}
|
||
|
|
||
|
nextIP := make(net.IP, len(ip))
|
||
|
switch len(ip) {
|
||
|
case net.IPv4len:
|
||
|
ipU32 := binary.BigEndian.Uint32(ip)
|
||
|
ipU32++
|
||
|
binary.BigEndian.PutUint32(nextIP, ipU32)
|
||
|
return nextIP
|
||
|
case net.IPv6len:
|
||
|
ipU64 := binary.BigEndian.Uint64(ip[net.IPv6len/2:])
|
||
|
ipU64++
|
||
|
binary.BigEndian.PutUint64(nextIP[net.IPv6len/2:], ipU64)
|
||
|
if ipU64 == 0 {
|
||
|
ipU64 = binary.BigEndian.Uint64(ip[:net.IPv6len/2])
|
||
|
ipU64++
|
||
|
binary.BigEndian.PutUint64(nextIP[:net.IPv6len/2], ipU64)
|
||
|
} else {
|
||
|
copy(nextIP[:net.IPv6len/2], ip[:net.IPv6len/2])
|
||
|
}
|
||
|
return nextIP
|
||
|
default:
|
||
|
return ip
|
||
|
}
|
||
|
}
|