// // Created by xajhuang on 2023/3/23. // #include #include "lease.h" #include "user_errno.h" #include "zlog_module.h" #include "database.h" #include "user_mgr.h" #define LEASE_DB_NAME ("lease") #define PREALLOC_IP_TIMEOUT (60) typedef struct { U32 ipAddr; char macAddr[20]; 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(name) \ "CREATE TABLE IF NOT EXISTS " #name \ " ( 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 " #name "_index ON " #name " (uid, mac);" int pre_alloc_dhcp_res(U32 uid, const char *pMac, U32 *pOutIp, PIPPOOL_INFO *pOutPool) { PIPPOOL_INFO pPool, pTemp; PPRE_ALLOC_IP pNewIp, pTmp, pCache = NULL; PIPPOOL_INFO pUserPool; if (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(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 (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; } } } 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; if (pMac) { strcpy(pNewIp->macAddr, pMac); } HASH_ADD_INT(g_pPreAllocIp, ipAddr, pNewIp); *pOutIp = ipAddr; *pOutPool = pPool; bitset_cls_bit(pPool->assignPool, addr); return ERR_SUCCESS; } else { if (time(NULL) - pNewIp->timeStamp < PREALLOC_IP_TIMEOUT) { continue; } *pOutIp = pNewIp->ipAddr; *pOutPool = pPool; 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", uid, pUserPool->poolKey); return -ERR_DHCP_NO_ADDR; } int dhcp_lease_init() { int rc = 0; rc = db_sqlite3_sql_exec(CREATE_LEASE_TABLE(LEASE_DB_NAME), NULL, NULL, NULL); if (rc != ERR_SUCCESS) { return rc; } return ERR_SUCCESS; }