101 lines
2.3 KiB
Go
101 lines
2.3 KiB
Go
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
|
|
}
|