|
@@ -0,0 +1,162 @@
|
|
|
+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)
|
|
|
+}
|