mirror of
https://github.com/slackhq/nebula.git
synced 2025-11-22 08:24:25 +01:00
Switch most everything to netip in prep for ipv6 in the overlay (#1173)
This commit is contained in:
@@ -1,41 +1,36 @@
|
||||
package nebula
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
|
||||
"github.com/slackhq/nebula/cidr"
|
||||
"github.com/gaissmai/bart"
|
||||
"github.com/slackhq/nebula/config"
|
||||
"github.com/slackhq/nebula/iputil"
|
||||
)
|
||||
|
||||
// This allows us to "guess" what the remote might be for a host while we wait
|
||||
// for the lighthouse response. See "lighthouse.calculated_remotes" in the
|
||||
// example config file.
|
||||
type calculatedRemote struct {
|
||||
ipNet net.IPNet
|
||||
maskIP iputil.VpnIp
|
||||
mask iputil.VpnIp
|
||||
port uint32
|
||||
ipNet netip.Prefix
|
||||
mask netip.Prefix
|
||||
port uint32
|
||||
}
|
||||
|
||||
func newCalculatedRemote(ipNet *net.IPNet, port int) (*calculatedRemote, error) {
|
||||
// Ensure this is an IPv4 mask that we expect
|
||||
ones, bits := ipNet.Mask.Size()
|
||||
if ones == 0 || bits != 32 {
|
||||
return nil, fmt.Errorf("invalid mask: %v", ipNet)
|
||||
}
|
||||
func newCalculatedRemote(maskCidr netip.Prefix, port int) (*calculatedRemote, error) {
|
||||
masked := maskCidr.Masked()
|
||||
if port < 0 || port > math.MaxUint16 {
|
||||
return nil, fmt.Errorf("invalid port: %d", port)
|
||||
}
|
||||
|
||||
return &calculatedRemote{
|
||||
ipNet: *ipNet,
|
||||
maskIP: iputil.Ip2VpnIp(ipNet.IP),
|
||||
mask: iputil.Ip2VpnIp(ipNet.Mask),
|
||||
port: uint32(port),
|
||||
ipNet: maskCidr,
|
||||
mask: masked,
|
||||
port: uint32(port),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -43,21 +38,41 @@ func (c *calculatedRemote) String() string {
|
||||
return fmt.Sprintf("CalculatedRemote(mask=%v port=%d)", c.ipNet, c.port)
|
||||
}
|
||||
|
||||
func (c *calculatedRemote) Apply(ip iputil.VpnIp) *Ip4AndPort {
|
||||
func (c *calculatedRemote) Apply(ip netip.Addr) *Ip4AndPort {
|
||||
// Combine the masked bytes of the "mask" IP with the unmasked bytes
|
||||
// of the overlay IP
|
||||
masked := (c.maskIP & c.mask) | (ip & ^c.mask)
|
||||
|
||||
return &Ip4AndPort{Ip: uint32(masked), Port: c.port}
|
||||
if c.ipNet.Addr().Is4() {
|
||||
return c.apply4(ip)
|
||||
}
|
||||
return c.apply6(ip)
|
||||
}
|
||||
|
||||
func NewCalculatedRemotesFromConfig(c *config.C, k string) (*cidr.Tree4[[]*calculatedRemote], error) {
|
||||
func (c *calculatedRemote) apply4(ip netip.Addr) *Ip4AndPort {
|
||||
//TODO: IPV6-WORK this can be less crappy
|
||||
maskb := net.CIDRMask(c.mask.Bits(), c.mask.Addr().BitLen())
|
||||
mask := binary.BigEndian.Uint32(maskb[:])
|
||||
|
||||
b := c.mask.Addr().As4()
|
||||
maskIp := binary.BigEndian.Uint32(b[:])
|
||||
|
||||
b = ip.As4()
|
||||
intIp := binary.BigEndian.Uint32(b[:])
|
||||
|
||||
return &Ip4AndPort{(maskIp & mask) | (intIp & ^mask), c.port}
|
||||
}
|
||||
|
||||
func (c *calculatedRemote) apply6(ip netip.Addr) *Ip4AndPort {
|
||||
//TODO: IPV6-WORK
|
||||
panic("Can not calculate ipv6 remote addresses")
|
||||
}
|
||||
|
||||
func NewCalculatedRemotesFromConfig(c *config.C, k string) (*bart.Table[[]*calculatedRemote], error) {
|
||||
value := c.Get(k)
|
||||
if value == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
calculatedRemotes := cidr.NewTree4[[]*calculatedRemote]()
|
||||
calculatedRemotes := new(bart.Table[[]*calculatedRemote])
|
||||
|
||||
rawMap, ok := value.(map[any]any)
|
||||
if !ok {
|
||||
@@ -69,17 +84,18 @@ func NewCalculatedRemotesFromConfig(c *config.C, k string) (*cidr.Tree4[[]*calcu
|
||||
return nil, fmt.Errorf("config `%s` has invalid key (type %T): %v", k, rawKey, rawKey)
|
||||
}
|
||||
|
||||
_, ipNet, err := net.ParseCIDR(rawCIDR)
|
||||
cidr, err := netip.ParsePrefix(rawCIDR)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("config `%s` has invalid CIDR: %s", k, rawCIDR)
|
||||
}
|
||||
|
||||
//TODO: IPV6-WORK this does not verify that rawValue contains the same bits as cidr here
|
||||
entry, err := newCalculatedRemotesListFromConfig(rawValue)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("config '%s.%s': %w", k, rawCIDR, err)
|
||||
}
|
||||
|
||||
calculatedRemotes.AddCIDR(ipNet, entry)
|
||||
calculatedRemotes.Insert(cidr, entry)
|
||||
}
|
||||
|
||||
return calculatedRemotes, nil
|
||||
@@ -117,7 +133,7 @@ func newCalculatedRemotesEntryFromConfig(raw any) (*calculatedRemote, error) {
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid mask (type %T): %v", rawValue, rawValue)
|
||||
}
|
||||
_, ipNet, err := net.ParseCIDR(rawMask)
|
||||
maskCidr, err := netip.ParsePrefix(rawMask)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid mask: %s", rawMask)
|
||||
}
|
||||
@@ -139,5 +155,5 @@ func newCalculatedRemotesEntryFromConfig(raw any) (*calculatedRemote, error) {
|
||||
return nil, fmt.Errorf("invalid port (type %T): %v", rawValue, rawValue)
|
||||
}
|
||||
|
||||
return newCalculatedRemote(ipNet, port)
|
||||
return newCalculatedRemote(maskCidr, port)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user