Add support for multiple IP prefixes

This commit is contained in:
Csaba Sarkadi 2022-01-16 14:16:59 +01:00
parent 3a3aecb774
commit 1a6e5d8770
18 changed files with 423 additions and 257 deletions

View file

@ -133,9 +133,24 @@ func encode(
return privKey.SealTo(*pubKey, b), nil
}
func (h *Headscale) getAvailableIP() (*netaddr.IP, error) {
ipPrefix := h.cfg.IPPrefix
func (h *Headscale) getAvailableIPs() (ips MachineAddresses, err error) {
ipPrefixes := h.cfg.IPPrefixes
for _, ipPrefix := range ipPrefixes {
var ip *netaddr.IP
ip, err = h.getAvailableIP(ipPrefix)
if err != nil {
return
}
ips = append(ips, *ip)
}
return
}
// TODO: Is this concurrency safe?
// What would happen if multiple hosts were to register at the same time?
// Would we attempt to assign the same addresses to multiple nodes?
func (h *Headscale) getAvailableIP(ipPrefix netaddr.IPPrefix) (*netaddr.IP, error) {
usedIps, err := h.getUsedIPs()
if err != nil {
return nil, err
@ -143,6 +158,7 @@ func (h *Headscale) getAvailableIP() (*netaddr.IP, error) {
ipPrefixNetworkAddress, ipPrefixBroadcastAddress := func() (netaddr.IP, netaddr.IP) {
ipRange := ipPrefix.Range()
return ipRange.From(), ipRange.To()
}()
@ -171,19 +187,20 @@ func (h *Headscale) getAvailableIP() (*netaddr.IP, error) {
}
func (h *Headscale) getUsedIPs() ([]netaddr.IP, error) {
var addresses []string
h.db.Model(&Machine{}).Pluck("ip_address", &addresses)
// FIXME: This really deserves a better data model,
// but this was quick to get running and it should be enough
// to begin experimenting with a dual stack tailnet.
var addressesSlices []string
h.db.Model(&Machine{}).Pluck("ip_addresses", &addressesSlices)
ips := make([]netaddr.IP, len(addresses))
for index, addr := range addresses {
if addr != "" {
ip, err := netaddr.ParseIP(addr)
if err != nil {
return nil, fmt.Errorf("failed to parse ip from database: %w", err)
}
ips[index] = ip
ips := make([]netaddr.IP, 0, len(h.cfg.IPPrefixes)*len(addressesSlices))
for _, slice := range addressesSlices {
var a MachineAddresses
err := a.Scan(slice)
if err != nil {
return nil, fmt.Errorf("failed to read ip from database: %w", err)
}
ips = append(ips, a...)
}
return ips, nil