vcpe/srcs/service/dhcpd/db_interface.c

216 lines
8.0 KiB
C
Raw Normal View History

//
// Created by HuangXin on 2023/4/24.
//
#include <sqlite3.h>
#include "user_errno.h"
#include "database.h"
#include "dhcp_network.h"
#include "rfc2131.h"
#include "ip_pool.h"
#include "db_interface.h"
#include "misc.h"
#include "zlog_module.h"
#define DCHP_STEP_TIMEOUT (120)
#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 CHAR(24) NOT NULL," \
" lease INTEGER NOT NULL," \
" netmask CHAR(24)," \
" gateway CHAR(24)," \
" dns1 CHAR(24)," \
" dns2 CHAR(24)," \
" 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', '%s', %d, '%s', '%s', '%s', '%s');"
#define GET_PRE_ASSIGN_EXISTS_ROW_FMT \
"SELECT ip FROM pre_assign WHERE mac = '%s' AND hostname = '%s' AND uid = %d ORDER BY createTm DESC LIMIT 1;"
#define IP_IS_PRE_ASSIGN_NOT_TIMEOUT_FMT \
"SELECT (strftime('%%s', 'now', 'localtime') - strftime('%%s', createTm)) as tm FROM pre_assign WHERE ip = " \
"'%s' AND tm < %d AND uid = %d ORDER BY tm DESC LIMIT 1;"
#define IP_IS_PRE_ASSIGN "SELECT ip FROM pre_assign WHERE ip = '%s' AND uid = %d"
#define IP_IS_PRE_ASSIGN_TIMEOUT_FMT \
"SELECT (strftime('%%s', 'now', 'localtime') - strftime('%%s', createTm)) as tm, id FROM pre_assign WHERE ip = " \
"'%s' AND tm >= %d AND uid = %d ORDER BY tm DESC LIMIT 1;"
#define CLS_TIMEOUT_PRE_ASSIGN_ROW_FMT \
"DELETE FROM pre_assign WHERE (strftime('%%s', 'now', 'localtime') - - strftime('%%s', createTm)) > %d"
#define UPDATE_CREATE_TIME_BY_ID_FMT "UPDATE pre_assign SET createTm = datetime('now', 'localtime') WHERE id = %s"
int lease_clearup_timeout_pre_assign() {
int rc;
char buf[1024] = {0};
snprintf(buf, 1024, CLS_TIMEOUT_PRE_ASSIGN_ROW_FMT, DCHP_STEP_TIMEOUT);
rc = db_sqlite3_sql_exec(CREATE_LEASE_TABLE(), NULL, NULL, NULL);
if (rc != ERR_SUCCESS) {
return rc;
}
return ERR_SUCCESS;
}
int lease_ip_is_pre_assign(U32 uid, U32 ip) {
int rc;
char buf[1024] = {0};
char **dbResult;
int nRow = 0, nColumn = 0;
// 判断IP是否存曾经被预分配
snprintf(buf, 1024, IP_IS_PRE_ASSIGN, u32_to_str_ip(htonl(ip)), uid);
rc = db_sqlite3_get_rows(buf, &dbResult, &nRow, &nColumn, NULL);
sqlite3_free_table(dbResult);
if (rc == ERR_SUCCESS && nRow == 0) {
// 数据库没有相关记录,直接返回
LOG_MOD(debug, ZLOG_MOD_DHCPD, "New prepare assign ipaddr %s form user %u\n", u32_to_str_ip(htonl(ip)), uid);
return FALSE;
}
// 判断数据库中该IP是否未超时
memset(buf, 0, 1024);
snprintf(buf, 1024, IP_IS_PRE_ASSIGN_NOT_TIMEOUT_FMT, u32_to_str_ip(htonl(ip)), DCHP_STEP_TIMEOUT, uid);
rc = db_sqlite3_get_rows(buf, &dbResult, &nRow, &nColumn, NULL);
sqlite3_free_table(dbResult);
if (rc == ERR_SUCCESS && nRow > 0 && nColumn > 0) {
// 如果数据库存在记录说明该IP暂时不可以用
LOG_MOD(debug, ZLOG_MOD_DHCPD, "No free ip address form user %u\n", uid);
return TRUE;
}
// 判断是否有超时预分配的IP 存在的话可以预分配给其它请求
memset(buf, 0, 1024);
snprintf(buf, 1024, IP_IS_PRE_ASSIGN_TIMEOUT_FMT, u32_to_str_ip(htonl(ip)), DCHP_STEP_TIMEOUT, uid);
rc = db_sqlite3_get_rows(buf, &dbResult, &nRow, &nColumn, NULL);
if (rc == ERR_SUCCESS && nRow > 0 && nColumn > 0) {
// 清理超时资源并预分配
// 更新时间戳
memset(buf, 0, 1024);
snprintf(buf, 1024, UPDATE_CREATE_TIME_BY_ID_FMT, dbResult[3]);
db_sqlite3_sql_exec(buf, NULL, NULL, NULL);
sqlite3_free_table(dbResult);
LOG_MOD(debug, ZLOG_MOD_DHCPD, "New prepare assign ipaddr %s form user %u by clearup resource\n", u32_to_str_ip(htonl(ip)), uid);
return FALSE;
}
sqlite3_free_table(dbResult);
// 处理失败,默认返回
return TRUE;
}
int lease_get_pre_assign(U32 uid, const char *mac, const char *hostname, U32 *preAssign) {
int rc;
char buf[1024] = {0};
char **dbResult;
int nRow = 0, nColumn = 0;
snprintf(buf, 1024, GET_PRE_ASSIGN_EXISTS_ROW_FMT, mac, hostname, uid);
rc = db_sqlite3_get_rows(buf, &dbResult, &nRow, &nColumn, NULL);
if (rc == ERR_SUCCESS && nRow > 0 && nColumn > 0) {
if (preAssign) {
*preAssign = ntohl(inet_addr(dbResult[1]));
}
rc = ERR_ITEM_EXISTS;
} else {
rc = ERR_ITEM_UNEXISTS;
}
sqlite3_free_table(dbResult);
return rc;
}
int lease_db_add_pre_assign(PDHCP_REQ pReq, U32 ip, PIPPOOL_INFO pPool) {
int rc;
char buf[1024] = {0};
char macStr[20] = {0};
const char *pIp = u32_to_str_ip_safe(htonl(ip));
const char *pMask = u32_to_str_ip_safe(htonl(pPool->netMask));
const char *pGw = u32_to_str_ip_safe(htonl(pPool->gwAddr));
const char *pDns1 = u32_to_str_ip_safe(htonl(pPool->primeDNS));
const char *pDns2 = u32_to_str_ip_safe(htonl(pPool->salveDNS));
MAC_TO_STR(pReq->cliMac, macStr);
snprintf(buf,
1024,
INSERT_PRE_ASSIGN_ROW_FMT,
pReq->uid,
pReq->xid,
pReq->hostName,
macStr,
pIp,
pPool->leaseTime,
pMask,
pGw,
pDns1,
pDns2);
free((void *)pIp);
free((void *)pMask);
free((void *)pGw);
free((void *)pDns1);
free((void *)pDns2);
rc = db_sqlite3_sql_exec(buf, NULL, NULL, NULL);
if (rc != ERR_SUCCESS) {
return rc;
}
return ERR_SUCCESS;
}
int lease_init_database() {
int rc;
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;
}