79 lines
1.2 KiB
Go
79 lines
1.2 KiB
Go
|
package ipfunc
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"net"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
type IPSubnet struct {
|
||
|
freeIPs []string
|
||
|
mux sync.Mutex
|
||
|
}
|
||
|
|
||
|
func NewIPSubnet(network string) (IPSubnet, error) {
|
||
|
i := IPSubnet{}
|
||
|
|
||
|
ip, ipnet, err := net.ParseCIDR(network)
|
||
|
if err != nil {
|
||
|
return IPSubnet{}, fmt.Errorf("Cant create IPSubnet, input ip cant pase: %w", err)
|
||
|
}
|
||
|
|
||
|
var ips []string
|
||
|
for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
|
||
|
ips = append(ips, ip.String())
|
||
|
}
|
||
|
|
||
|
lenIPs := len(ips)
|
||
|
switch {
|
||
|
case lenIPs < 2:
|
||
|
i.freeIPs = ips
|
||
|
|
||
|
default:
|
||
|
i.freeIPs = ips[1 : len(ips)-1]
|
||
|
}
|
||
|
|
||
|
|
||
|
return i, nil
|
||
|
}
|
||
|
|
||
|
func (i *IPSubnet) GetNextFreeIP() (string, error) {
|
||
|
if len(i.freeIPs) == 0 {
|
||
|
return "", errors.New("No free IP")
|
||
|
}
|
||
|
|
||
|
i.mux.Lock()
|
||
|
defer i.mux.Unlock()
|
||
|
|
||
|
rip := i.freeIPs[0]
|
||
|
i.remove(rip)
|
||
|
return rip, nil
|
||
|
}
|
||
|
|
||
|
func (i *IPSubnet) remove (ip string) {
|
||
|
var newips []string
|
||
|
for _, oneIp := range i.freeIPs {
|
||
|
if oneIp != ip {
|
||
|
newips = append(newips, oneIp)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
i.freeIPs = newips
|
||
|
}
|
||
|
|
||
|
func (i *IPSubnet)Remove(ip string) {
|
||
|
i.mux.Lock()
|
||
|
defer i.mux.Unlock()
|
||
|
|
||
|
i.remove(ip)
|
||
|
}
|
||
|
|
||
|
func inc(ip net.IP) {
|
||
|
for j := len(ip) - 1; j >= 0; j-- {
|
||
|
ip[j]++
|
||
|
if ip[j] > 0 {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|