Files
virtuallan/pkg/server/ipmgr_linux.go
lucheng a6bfacb0c2 Fix client ip by get client ip base on username hash
Count username hash, get client ip base on it, it will make ip
fixed base on client login username.
2024-08-09 12:30:26 +08:00

133 lines
2.4 KiB
Go

package server
import (
"encoding/binary"
"errors"
"fmt"
"net"
"github.com/lucheng0127/virtuallan/pkg/utils"
)
func (svc *Server) ParseDHCPRange() error {
ipStart, ipCount := utils.ValidateDHCPRange(svc.ServerConfig.DHCPRange)
if ipCount == 0 {
return fmt.Errorf("invalidate dhcp range %s, <ip start>-<ip end>", svc.ServerConfig.DHCPRange)
}
svc.IPStart = ipStart
svc.IPCount = ipCount
return nil
}
func (svc *Server) IPIdxInPool(idx int) bool {
for _, i := range svc.UsedIP {
if idx == i {
return true
}
}
return false
}
func (svc *Server) IPInPool(ip net.IP) bool {
ipInt := binary.BigEndian.Uint32(ip)
ipStartInt := binary.BigEndian.Uint32(svc.IPStart)
idx := ipInt - ipStartInt
return svc.IPIdxInPool(int(idx))
}
func (svc *Server) IPFromIdx(idx int) net.IP {
ipStartInt := binary.BigEndian.Uint32(svc.IPStart)
ipInt := ipStartInt + uint32(idx)
ipBytes := make([]byte, 4)
binary.BigEndian.PutUint32(ipBytes, ipInt)
return net.IP(ipBytes)
}
func (svc *Server) IdxFromIP(ip net.IP) int {
ipStartInt := binary.BigEndian.Uint32(svc.IPStart)
ipInt := binary.BigEndian.Uint32(ip)
return int(ipInt - ipStartInt)
}
func (svc *Server) IPForUser(username string) (net.IP, error) {
idx := utils.IdxFromString(svc.IPCount, username)
idxEnd := idx - 1
for idx < svc.IPCount {
if idx == idxEnd {
// Checked the last idx
if svc.IPIdxInPool(idx) {
break
}
svc.MLock.Lock()
svc.UsedIP = append(svc.UsedIP, idx)
svc.MLock.Unlock()
return svc.IPFromIdx(idx), nil
}
if svc.IPIdxInPool(idx) {
idx += 1
if idx == svc.IPCount {
// Check from zero
idx = 0
}
continue
}
svc.MLock.Lock()
svc.UsedIP = append(svc.UsedIP, idx)
svc.MLock.Unlock()
return svc.IPFromIdx(idx), nil
}
return nil, errors.New("run out of ip")
}
func (svc *Server) PopIPFromPool() (net.IP, error) {
for idx := 0; idx < svc.IPCount; idx++ {
if svc.IPIdxInPool(idx) {
continue
}
svc.MLock.Lock()
svc.UsedIP = append(svc.UsedIP, idx)
svc.MLock.Unlock()
return svc.IPFromIdx(idx), nil
}
return nil, errors.New("run out of ip")
}
func (svc *Server) ReleaseIP(ip net.IP) {
idx := svc.IdxFromIP(ip)
targetPoolIdx := -1
for i, ipIdx := range svc.UsedIP {
if ipIdx == idx {
targetPoolIdx = i
break
}
}
if targetPoolIdx == -1 {
return
}
svc.MLock.Lock()
svc.UsedIP = append(svc.UsedIP[:targetPoolIdx], svc.UsedIP[targetPoolIdx+1:]...)
svc.MLock.Unlock()
}