238 lines
8.1 KiB
C
238 lines
8.1 KiB
C
//
|
||
// 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;
|
||
} |