vcpe/srcs/service/dhcpd/lease.c

163 lines
5.2 KiB
C
Raw Normal View History

//
// Created by xajhuang on 2023/3/23.
//
#include <time.h>
#include "lease.h"
2023-03-31 06:32:32 +00:00
#include "user_errno.h"
#include "zlog_module.h"
#include "database.h"
#include "user_mgr.h"
2023-03-31 06:32:32 +00:00
#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;
2023-03-31 06:32:32 +00:00
#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," \
2023-03-31 06:32:32 +00:00
" 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;
}
2023-03-31 06:32:32 +00:00
int dhcp_lease_init() {
int rc = 0;
rc = db_sqlite3_sql_exec(CREATE_LEASE_TABLE(LEASE_DB_NAME), NULL, NULL, NULL);
2023-03-31 06:32:32 +00:00
if (rc != ERR_SUCCESS) {
return rc;
}
return ERR_SUCCESS;
}