Added logic to find next available IP address
This commit is contained in:
100
ipaddresses.go
Normal file
100
ipaddresses.go
Normal file
@ -0,0 +1,100 @@
|
||||
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
|
||||
}
|
Reference in New Issue
Block a user