package backend import ( "dhcp/global" "dhcp/internal/dao" "dhcp/internal/service" "dhcp/model" "math/rand" "net" "strconv" "sync" "time" ) type DHCPTemplate struct { DhcpInterface string //DHCP监听的端口 IPAddressRanges string // ip范围 DefaultGateway string // 默认网关 NameServers []string // DNS Hostname string // 主机名 DomainName string // 域名 BroadcastAddress string // 广播地址 NTPServers []string // NTP服务器 VLANID string // VLAN ID LeaseTime int // 租约 Arch string // 架构 DomainSearch []string // 域名搜索 } var record = make(map[string]struct{}) //记录分配的ip var recordMac = make(map[string]string) //物理地址对应ip func InitIPRecord() { all, err := dao.GetDHCP() if err != nil { global.Log.Info("初始化IP记录失败", err) } for _, v := range all { record[v.IPAddress] = struct{}{} recordMac[v.MACAddress] = v.IPAddress } } func UpdateRecord(mac string, ip string) { recordMac[mac] = ip delete(record, ip) record[ip] = struct{}{} } func DeleteRecord(mac string, ip string) { delete(record, ip) delete(recordMac, mac) } func CreateRecord(mac string, ip string) { record[ip] = struct{}{} recordMac[mac] = ip } func GenerateIP(mac string, ifName string) (model.DHCP, error) { var m sync.Mutex dh := service.DHCPServiceInfoMap[ifName] d := DHCPTemplate{ DhcpInterface: dh.BindInterface, IPAddressRanges: dh.NetworkSegment, DefaultGateway: dh.DefaultGateway, NameServers: dh.NameServers, Hostname: dh.Hostname, LeaseTime: 86400, } var randomIP net.IP // 确定网段范围 ip, ipNet, err := net.ParseCIDR(d.IPAddressRanges) if err != nil { global.Log.Error(err, "解析网段失败") return model.DHCP{}, err } if v, ok := recordMac[mac]; !ok { network := ip.Mask(ipNet.Mask) minIP := network.To4() maxIP := net.IPv4(minIP[0]|^ipNet.Mask[0], minIP[1]|^ipNet.Mask[1], minIP[2]|^ipNet.Mask[2], minIP[3]|^ipNet.Mask[3]).To4() // 生成随机种子 rand.NewSource(time.Now().UnixNano()) for { randomIP = generateRandomIP(minIP, maxIP) if _, ok := record[randomIP.String()]; !ok { m.Lock() record[randomIP.String()] = struct{}{} recordMac[mac] = randomIP.String() m.Unlock() break } } } else { randomIP = net.ParseIP(v) } // 构建DHCP信息 subnetMask := strconv.Itoa(int(ipNet.Mask[0])) + "." + strconv.Itoa(int(ipNet.Mask[1])) + "." + strconv.Itoa(int(ipNet.Mask[2])) + "." + strconv.Itoa(int(ipNet.Mask[3])) dhcp := buildDHCP(randomIP.String(), subnetMask, mac, d) _ = dao.AddDHCP(dhcp) return dhcp, err } func generateRandomIP(min, max net.IP) net.IP { // IP地址是32位的,每位都是一个字节 ip := make(net.IP, len(min)) for i := range min { n := int(max[i] - min[i]) if n == 0 { ip[i] = min[i] } else { ip[i] = byte(rand.Intn(n) + int(min[i])) } } if ip.Equal(min) || ip.Equal(max) { return generateRandomIP(min, max) } return ip } func buildDHCP(randomIP string, subnetMask, mac string, d DHCPTemplate) model.DHCP { ipinfo := model.DHCP{ Interface: d.DhcpInterface, MACAddress: mac, IPAddress: randomIP, SubnetMask: subnetMask, DefaultGateway: d.DefaultGateway, NameServers: d.NameServers, DomainName: d.DomainName, BroadcastAddress: d.BroadcastAddress, NTPServers: d.NTPServers, VLANID: d.VLANID, LeaseTime: uint32(d.LeaseTime), DomainSearch: d.DomainSearch, } return ipinfo } func isIPInSubnet(ip, ifName string) bool { // Parse the IP address ipAddr := net.ParseIP(ip) if ipAddr == nil { return false } // Parse the subnet _, ipNet, err := net.ParseCIDR(service.DHCPServiceInfoMap[ifName].NetworkSegment) if err != nil { return false } // Check if the IP address is in the subnet return ipNet.Contains(ipAddr) }