vcpe/srcs/service/dhcpd/lease.c

238 lines
8.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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;
}