// // Created by xajhuang on 2023/3/23. // #include <time.h> #include "lease.h" #include "user_errno.h" #include "zlog_module.h" #include "database.h" #include "user_mgr.h" #include "rfc2131.h" #include "dhcp_network.h" #define LEASE_DB_NAME "lease" #define PREALLOC_IP_TIMEOUT (60) typedef struct { U32 ipAddr; U8 macAddr[ETH_ALEN]; U32 bitset; PIPPOOL_INFO pCtx; U32 timeStamp; UT_hash_handle hh; } PRE_ALLOC_IP, *PPRE_ALLOC_IP; //static PMAC_FILTER g_allowTbl = NULL; //static PMAC_FILTER g_blackListTbl = NULL; static PPRE_ALLOC_IP g_pPreAllocIp = NULL; #define CREATE_LEASE_TABLE() \ "CREATE TABLE IF NOT EXISTS lease " \ " ( id INTEGER PRIMARY KEY AUTOINCREMENT," \ " uid INTEGER NOT NULL," \ " mac CHAR(20) NOT NULL," \ " ip INTEGER NOT NULL," \ " lease INTEGER NOT NULL," \ " createTm INTEGER NOT NULL," \ " netmask INTEGER," \ " gateway INTEGER," \ " dns1 INTEGER," \ " dns2 INTEGER," \ " server INTEGER NOT NULL," \ " hostname CHAR(64) DEFAULT '' NOT NULL," \ " keyType INTEGER NOT NULL" \ ");" \ "CREATE INDEX IF NOT EXISTS " \ "lease_index ON lease (uid, mac);" #define CREATE_PRE_ASSIGN_TABLE() \ "CREATE TABLE IF NOT EXISTS pre_assign" \ " ( id INTEGER PRIMARY KEY AUTOINCREMENT," \ " uid INTEGER NOT NULL," \ " xid INTEGER NOT NULL," \ " hostname CHAR(64) DEFAULT '' NOT NULL," \ " mac CHAR(20) NOT NULL," \ " ip INTEGER NOT NULL," \ " lease INTEGER NOT NULL," \ " netmask INTEGER," \ " gateway INTEGER," \ " dns1 INTEGER," \ " dns2 INTEGER," \ " createTm TIMESTAMP DEFAULT (datetime('now', 'localtime')) NOT NULL" \ "); CREATE INDEX IF NOT EXISTS pre_assign_index ON pre_assign(ip, uid);" #define INSERT_PRE_ASSIGN_ROW_FMT \ "INSERT INTO pre_assign (uid, xid, hostname, mac, ip, lease, netmask, gateway, dns1, dns2) " \ "VALUES (%d, %d, \'%s\', \'%s\', %d, %d, %d, %d, %d, %d);" static int lease_db_add_pre_assign(PDHCP_REQ pReq, U32 ip, PIPPOOL_INFO pPool) { int rc; char buf[1024] = {0}; char macStr[20] = {0}; MAC_TO_STR(pReq->cliMac, macStr); snprintf(buf, 1024, INSERT_PRE_ASSIGN_ROW_FMT, pReq->uid, pReq->xid, pReq->hostName, macStr, ip, pPool->leaseTime, pPool->netMask, pPool->gwAddr, pPool->primeDNS, pPool->salveDNS); rc = db_sqlite3_sql_exec(CREATE_PRE_ASSIGN_TABLE(), NULL, NULL, NULL); if (rc != ERR_SUCCESS) { return rc; } DEBUG_CODE_LINE(); return ERR_SUCCESS; } //int pre_alloc_dhcp_res(U32 uid, const char *pMac, U32 *pOutIp, PIPPOOL_INFO *pOutPool) { int pre_alloc_dhcp_res(PDHCP_REQ pReq, U32 *pOutIp, PIPPOOL_INFO *pOutPool) { PIPPOOL_INFO pPool, pTemp; PPRE_ALLOC_IP pNewIp, pTmp, pCache = NULL; PIPPOOL_INFO pUserPool; if (pReq == NULL || pOutIp == NULL || pOutPool == NULL) { LOG_MOD(error, ZLOG_MOD_DHCPD, "Input params error: %p, %p\n", pOutIp, pOutPool); return -ERR_INPUT_PARAMS; } pUserPool = user_get_pool(pReq->uid); if (pUserPool == NULL) { LOG_MOD(error, ZLOG_MOD_DHCPD, "Can't found avaliable address pool\n"); return -ERR_DHCP_NO_POOL; } // 遍历当前用户所有IP地址池 HASH_ITER(hh, pUserPool, pPool, pTemp) { U32 addr; // 查看是否预分配过该设备 #if 0 if (pMac && strlen(pMac) > 0) { HASH_ITER(hh, g_pPreAllocIp, pNewIp, pTmp) { if (strcmp(pNewIp->macAddr, pMac) == 0) { *pOutIp = pNewIp->ipAddr; *pOutPool = pPool; return ERR_SUCCESS; } } } #endif while ((addr = bitset_minimum(pPool->assignPool)) > 0) { U32 ipAddr = (pPool->minAddr & pPool->netMask) + addr; // 查找租约配置文件中是否记录了曾经分配的地址, 如果已经分配则获取下一个 // TODO: add process // if (FALSE) { // bitset_set(pPool->assignPool, addr); // continue; // } // 查找IP地址是否已经被预分配 HASH_FIND_INT(g_pPreAllocIp, &ipAddr, pNewIp); if (pNewIp == NULL) { pNewIp = (PPRE_ALLOC_IP)malloc(sizeof(PRE_ALLOC_IP)); if (!pNewIp) { LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %lu\n", sizeof(PRE_ALLOC_IP)); continue; } memset(pNewIp, 0, sizeof(PRE_ALLOC_IP)); pNewIp->timeStamp = time(NULL); pNewIp->pCtx = pPool; pNewIp->ipAddr = ipAddr; pNewIp->bitset = addr; memcpy(pNewIp->macAddr, pReq->cliMac, ETH_ALEN); //HASH_ADD_INT(g_pPreAllocIp, ipAddr, pNewIp); DEBUG_CODE_LINE(); lease_db_add_pre_assign(pReq, ipAddr, pPool); *pOutIp = ipAddr; *pOutPool = pPool; bitset_cls_bit(pPool->assignPool, addr); LOG_MOD(trace, ZLOG_MOD_DHCPD, "Select ipaddr %08X at %d of %p\n", ipAddr, addr, pPool->assignPool); return ERR_SUCCESS; } else { DEBUG_CODE_LINE(); if (time(NULL) - pNewIp->timeStamp < PREALLOC_IP_TIMEOUT) { continue; } *pOutIp = pNewIp->ipAddr; *pOutPool = pPool; LOG_MOD(trace, ZLOG_MOD_DHCPD, "Used prepard ipaddr %08X at %d of %p\n", ipAddr, addr, pPool->assignPool); return ERR_SUCCESS; } } } // 如果没有分配到IP,清理过期的预分配IP HASH_ITER(hh, g_pPreAllocIp, pNewIp, pTmp) { if (time(NULL) - pNewIp->timeStamp > PREALLOC_IP_TIMEOUT) { if (pCache == NULL) { pCache = pNewIp; } else { HASH_DEL(g_pPreAllocIp, pNewIp); free(pNewIp); bitset_cls_bit(pNewIp->pCtx->assignPool, pNewIp->bitset); } } } if (pCache) { *pOutIp = pCache->ipAddr; *pOutPool = pPool; return ERR_SUCCESS; } // 没有可预分配的IP,报错 LOG_MOD(error, ZLOG_MOD_DHCPD, "No free ipaddress in poll: uid = %u, pool = 0x%08X\n", pReq->uid, pUserPool->poolKey); return -ERR_DHCP_NO_ADDR; } int dhcp_lease_init() { int rc = 0; rc = db_sqlite3_sql_exec(CREATE_LEASE_TABLE(), NULL, NULL, NULL); if (rc != ERR_SUCCESS) { return rc; } rc = db_sqlite3_sql_exec(CREATE_PRE_ASSIGN_TABLE(), NULL, NULL, NULL); if (rc != ERR_SUCCESS) { return rc; } return ERR_SUCCESS; }