diff --git a/utils.go b/utils.go index 7011e63d..d2b6b902 100644 --- a/utils.go +++ b/utils.go @@ -141,36 +141,32 @@ func (h *Headscale) getAvailableIP() (*netaddr.IP, error) { return nil, err } + ipPrefixNetworkAddress, ipPrefixBroadcastAddress := func() (netaddr.IP, netaddr.IP) { + ipRange := ipPrefix.Range() + return ipRange.From(), ipRange.To() + }() + // Get the first IP in our prefix - ip := ipPrefix.IP() + ip := ipPrefixNetworkAddress.Next() for { if !ipPrefix.Contains(ip) { return nil, errCouldNotAllocateIP } - // Some OS (including Linux) does not like when IPs ends with 0 or 255, which - // is typically called network or broadcast. Lets avoid them and continue - // to look when we get one of those traditionally reserved IPs. - ipRaw := ip.As4() - if ipRaw[3] == 0 || ipRaw[3] == 255 { + switch { + case ip.Compare(ipPrefixBroadcastAddress) == 0: + fallthrough + case containsIPs(usedIps, ip): + fallthrough + case ip.IsZero() || ip.IsLoopback(): ip = ip.Next() continue - } - if ip.IsZero() && - ip.IsLoopback() { - ip = ip.Next() - - continue - } - - if !containsIPs(usedIps, ip) { + default: return &ip, nil } - - ip = ip.Next() } } diff --git a/utils_test.go b/utils_test.go index 95722a83..9b0295b3 100644 --- a/utils_test.go +++ b/utils_test.go @@ -93,7 +93,7 @@ func (s *Suite) TestGetMultiIp(c *check.C) { c.Assert(ips[0], check.Equals, netaddr.MustParseIP("10.27.0.1")) c.Assert(ips[9], check.Equals, netaddr.MustParseIP("10.27.0.10")) - c.Assert(ips[300], check.Equals, netaddr.MustParseIP("10.27.1.47")) + c.Assert(ips[300], check.Equals, netaddr.MustParseIP("10.27.1.45")) // Check that we can read back the IPs machine1, err := app.GetMachineByID(1) @@ -112,7 +112,7 @@ func (s *Suite) TestGetMultiIp(c *check.C) { netaddr.MustParseIP("10.27.0.50").String(), ) - expectedNextIP := netaddr.MustParseIP("10.27.1.97") + expectedNextIP := netaddr.MustParseIP("10.27.1.95") nextIP, err := app.getAvailableIP() c.Assert(err, check.IsNil)