package main import ( "fmt" "log" "net" "os" ) func getInterfaceIPAndMask(interfaceName string) (ip net.IP, mask net.IPMask, err error) { iface, err := net.InterfaceByName(interfaceName) if err != nil { return nil, nil, fmt.Errorf("failed to get interface %s: %w", interfaceName, err) } addrs, err := iface.Addrs() if err != nil { return nil, nil, fmt.Errorf("failed to get addresses for %s: %w", interfaceName, err) } for _, addr := range addrs { ipNet, ok := addr.(*net.IPNet) if !ok || ipNet.IP.IsLoopback() || ipNet.IP.To4() == nil { continue } return ipNet.IP, ipNet.Mask, nil } return nil, nil, fmt.Errorf("no valid IPv4 address found for interface %s", interfaceName) } func getNextFreeIP() (net.IP, error) { var wg string = os.Getenv("WIREGUARD_INTERFACE") ip, mask, err := getInterfaceIPAndMask(wg) if err != nil { log.Fatal(err) } used, err := parseUsedIPsFromConfigs("./configs") if err != nil { fmt.Println("Error:", err) return nil, fmt.Errorf("Unkown err: %s", err) } for _, ip := range used { fmt.Println("Used IP:", ip) } // used := []net.IP{ // net.ParseIP("10.200.34.1"), // net.ParseIP("10.200.34.2"), // net.ParseIP("10.200.34.3"), // net.ParseIP("10.200.34.4"), // net.ParseIP("10.200.34.5"), // net.ParseIP("10.200.34.6"), // net.ParseIP("10.200.34.225"), // net.ParseIP("10.200.34.226"), // net.ParseIP("10.200.34.227"), // } network := ip.Mask(mask) ipNet := &net.IPNet{IP: network, Mask: mask} // Turn the used list into a map for fast lookup usedMap := make(map[string]bool) for _, u := range used { usedMap[u.String()] = true } // Get network boundaries start := ipToUint32(network) + 1 end := ipToUint32(lastIP(ipNet)) - 1 // Skip broadcast for i := start; i <= end; i++ { candidate := uint32ToIP(i) if !usedMap[candidate.String()] { return candidate, nil } } return nil, fmt.Errorf("no free IPs in subnet %s", ipNet.String()) } func ipToUint32(ip net.IP) uint32 { ip = ip.To4() return uint32(ip[0])<<24 | uint32(ip[1])<<16 | uint32(ip[2])<<8 | uint32(ip[3]) } func uint32ToIP(n uint32) net.IP { return net.IPv4(byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) } func lastIP(ipNet *net.IPNet) net.IP { ip := ipNet.IP.To4() mask := ipNet.Mask broadcast := make(net.IP, len(ip)) for i := range ip { broadcast[i] = ip[i] | ^mask[i] } return broadcast }