From ae7e3b6d80eaaf3f027c74edc4e15bccd869747d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=98=95?= Date: Tue, 25 Apr 2023 09:17:08 +0800 Subject: [PATCH] =?UTF-8?q?OCT=201.=20=E6=9A=82=E5=AD=98=E5=BC=80=E5=8F=91?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E4=BB=A3=E7=A0=81=202.=20=E9=87=8D=E5=86=99?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=E6=B1=A0=E9=85=8D=E7=BD=AE=EF=BC=8C=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=AE=A1=E7=90=86=203.=20=E5=88=A9=E7=94=A8=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E6=95=B0=E6=8D=AE=E5=BA=93=E7=AE=A1=E7=90=86=E7=A7=9F?= =?UTF-8?q?=E7=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/vcpe.cfg | 4 +- dhcp_tools/main_wnd.c | 18 +- dhcp_tools/res/main.glade | 124 +++++++------ srcs/libs/database/database.c | 28 ++- srcs/libs/include/database.h | 1 + srcs/libs/include/misc.h | 1 + srcs/libs/include/zlog_module.h | 12 +- srcs/libs/misc/misc.c | 13 ++ srcs/service/CMakeLists.txt | 2 +- srcs/service/dhcpd/db_interface.c | 216 ++++++++++++++++++++++ srcs/service/dhcpd/dhcpd_network.c | 4 +- srcs/service/dhcpd/include/db_interface.h | 18 ++ srcs/service/dhcpd/include/ip_pool.h | 30 +++ srcs/service/dhcpd/include/user_mgr.h | 6 + srcs/service/dhcpd/ip_pool.c | 33 +++- srcs/service/dhcpd/lease.c | 156 ++-------------- srcs/service/dhcpd/user_mgr.c | 138 ++++++++++---- 17 files changed, 557 insertions(+), 247 deletions(-) create mode 100644 srcs/service/dhcpd/db_interface.c create mode 100644 srcs/service/dhcpd/include/db_interface.h diff --git a/config/vcpe.cfg b/config/vcpe.cfg index 32d71d1..23dc248 100644 --- a/config/vcpe.cfg +++ b/config/vcpe.cfg @@ -40,7 +40,7 @@ application: mysql_passwd = "AES@5/BQyUIfVxgV9BZAz/D3Rg=="; # mysql 数据库密码 mysql_database = "test"; # mysql 数据库名称 - sqlite_dbname = "/home/hx/vcpe.db"; # sqlite3 数据库文件名 + sqlite_dbname = "./vcpe.db"; # sqlite3 数据库文件名 sqlite_passwd = ""; # sqlite3 数据库密码 }; @@ -90,7 +90,7 @@ application: # DHCP Server Config dhcp_server: { # DHCP服务物理网卡名称 - nic = "ens192"; + nic = "eth0"; # 全局租约时间 lease_time = 86400; # 监听网卡 diff --git a/dhcp_tools/main_wnd.c b/dhcp_tools/main_wnd.c index d64d57f..3e4ace5 100644 --- a/dhcp_tools/main_wnd.c +++ b/dhcp_tools/main_wnd.c @@ -166,7 +166,6 @@ static void tree_view_data_store_create() { static gboolean tree_view_data_store_upgade(gpointer pInfo) { char buf[32] = {0}; - GtkTreePath *path; GtkTreeIter iter; GtkListStore *store = GTK_LIST_STORE(gtk_builder_get_object(g_mainBuilder, "tsDhcpInfo")); @@ -314,7 +313,7 @@ static void cleanupDHCPInfo() { } G_MODULE_EXPORT void __mainWnd_on_tb_start(GObject *object, gpointer user_data) { - int i; + int i, j, index = 0; GtkTreeIter iter; PDHCP_INFO pInfo; GtkTreeModel *cobModel; @@ -326,11 +325,13 @@ G_MODULE_EXPORT void __mainWnd_on_tb_start(GObject *object, gpointer user_data) GtkWidget *macBegin = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "txtMacStart")); GtkWidget *preHostname = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "txtHostname")); GtkWidget *vniStart = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbVni")); + GtkWidget *numVniCli = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbVniClient")); GtkWidget *numRequest = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbReqNum")); const char *strMacBegin = gtk_entry_get_text(GTK_ENTRY(macBegin)); const char *strPreHostname = gtk_entry_get_text(GTK_ENTRY(preHostname)); U32 nRequest = (U32)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(numRequest)); U32 nVni = (U32)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vniStart)); + U32 nVniCnt = (U32)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(numVniCli)); string_mac_to_bytes(strMacBegin, mac); macVal = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5]; @@ -338,8 +339,8 @@ G_MODULE_EXPORT void __mainWnd_on_tb_start(GObject *object, gpointer user_data) cleanupDHCPInfo(); for (i = 0; i < nRequest; i++) { - char strMac[6]; - U32 macAddr = macVal + i; + for (j = 0; j < nVniCnt; j++) { + U32 macAddr = macVal + index; pInfo = (PDHCP_INFO)malloc(sizeof(DHCP_INFO)); if (pInfo == NULL) { @@ -348,7 +349,7 @@ G_MODULE_EXPORT void __mainWnd_on_tb_start(GObject *object, gpointer user_data) } memset(pInfo, 0, sizeof(DHCP_INFO)); - pInfo->index = i; + pInfo->index = index; pInfo->vni = nVni + i; pInfo->mac[0] = mac[0]; pInfo->mac[1] = mac[1]; @@ -357,11 +358,13 @@ G_MODULE_EXPORT void __mainWnd_on_tb_start(GObject *object, gpointer user_data) pInfo->mac[4] = (macAddr & 0xFF00) >> 8; pInfo->mac[5] = (macAddr & 0xFF); - sprintf(pInfo->hostname, "%s_%u", strPreHostname, pInfo->vni); + sprintf(pInfo->hostname, "%s_%u", strPreHostname, pInfo->vni + index); pInfo->step = STEP_BEGIN; pInfo->status = STA_WAIT_START; HASH_ADD_INT(g_pDhcpInfo, index, pInfo); + index++; + } } gtk_widget_set_sensitive(GTK_WIDGET(object), FALSE); @@ -452,6 +455,9 @@ int main(int args, char **argv) { GtkAdjustment *adjVni = gtk_adjustment_new(1, 1, 10000000, 1, 0, 0); gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(numVni), adjVni); + GtkWidget *numVniCli = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "sbVniClient")); + GtkAdjustment *adjVniCli = gtk_adjustment_new(1, 1, 1000, 1, 0, 0); + gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(numVniCli), adjVniCli); GtkWidget *view = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "treeResult")); #if 0 diff --git a/dhcp_tools/res/main.glade b/dhcp_tools/res/main.glade index 7765b2e..68a74b9 100644 --- a/dhcp_tools/res/main.glade +++ b/dhcp_tools/res/main.glade @@ -235,17 +235,6 @@ MAC起始地址: - - - True - 0 - DHCP 并发请求数: - - - 1 - 2 - - True @@ -257,19 +246,6 @@ 3 - - - True - 0 - VNI 起始值: - - - 2 - 3 - 1 - 2 - - True @@ -294,32 +270,6 @@ 4 - - - True - True - - - - 1 - 2 - 1 - 2 - - - - - True - True - - - - 3 - 4 - 1 - 2 - - True @@ -349,10 +299,80 @@ - + + True + 0 + VNI客户端数: + + + 4 + 5 + 1 + 2 + - + + True + True + + + + 5 + 6 + 1 + 2 + + + + + True + True + + + + 1 + 2 + 1 + 2 + + + + + True + True + + + + 3 + 4 + 1 + 2 + + + + + True + 0 + VNI 请求数: + + + 2 + 3 + 1 + 2 + + + + + True + 0 + VNI 起始值: + + + 1 + 2 + diff --git a/srcs/libs/database/database.c b/srcs/libs/database/database.c index 1d12c63..00dc4a5 100644 --- a/srcs/libs/database/database.c +++ b/srcs/libs/database/database.c @@ -24,7 +24,12 @@ int db_sqlite3_init() { rc = sqlite3_open_v2(pDbPath, &g_pSqlHandle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); if (rc != SQLITE_OK) { - LOG_MOD(error, ZLOG_MOD_DB, "Create SQLite3 Database at %s error: %s(%d)\n", pDbPath, sqlite3_errstr(rc), rc); + LOG_MOD(error, + ZLOG_MOD_DB, + "Create SQLite3 Database at %s error: %s(%d)\n", + pDbPath, + sqlite3_errstr(rc), + rc); return -ERR_DB_CONNECT; } } @@ -34,6 +39,27 @@ int db_sqlite3_init() { return ERR_SUCCESS; } +int db_sqlite3_get_rows(const char *pSqlCmd, char ***dbResult, int *pnRow, int *pnColumn, char **pErr) { + if (pSqlCmd == NULL || strlen(pSqlCmd) == 0) { + LOG_MOD(error, ZLOG_MOD_DB, "Input params pSqlCmd error\n"); + return -ERR_INPUT_PARAMS; + } + + if (g_pSqlHandle) { + int rc = sqlite3_get_table(g_pSqlHandle, pSqlCmd, dbResult, pnRow, pnColumn, pErr); + + if (rc != SQLITE_OK) { + LOG_MOD(error, ZLOG_MOD_DB, "Run {%s} SQL command error:\n%s\n", pSqlCmd, sqlite3_errmsg(g_pSqlHandle)); + return -ERR_DB_SQL_EXEC; + } + + return ERR_SUCCESS; + } else { + LOG_MOD(error, ZLOG_MOD_DB, "SQlite3 database uninit\n"); + return -ERR_DB_UNINIT; + } +} + int db_sqlite3_sql_exec(const char *pSqlCmd, void *pCallback, void *pData, char **pErr) { if (pSqlCmd == NULL || strlen(pSqlCmd) == 0) { diff --git a/srcs/libs/include/database.h b/srcs/libs/include/database.h index 006752c..915d530 100644 --- a/srcs/libs/include/database.h +++ b/srcs/libs/include/database.h @@ -11,6 +11,7 @@ extern "C" { int db_sqlite3_init(); void db_sqlite3_uninit(); int db_sqlite3_sql_exec(const char *pSqlCmd, void *pCallback, void *pData, char **pErr); +int db_sqlite3_get_rows(const char *pSqlCmd, char ***dbResult, int *pnRow, int *pnColumn, char **pErr); #ifdef __cplusplus } #endif diff --git a/srcs/libs/include/misc.h b/srcs/libs/include/misc.h index b791689..31ed204 100644 --- a/srcs/libs/include/misc.h +++ b/srcs/libs/include/misc.h @@ -42,6 +42,7 @@ int process_lock_pidfile(char *pFilePath); void process_unlock_pidfile(); int get_all_network_info(PSYS_NIC_INFO pInfo); const char *u32_to_str_ip(unsigned int ip); +const char *u32_to_str_ip_safe(unsigned int ip); unsigned short udp_checksum(unsigned int saddr, unsigned int daddr, unsigned char *pUdp); unsigned short ip_checksum(unsigned char *pIp); int string_mac_to_bytes(const char *pStrMac, unsigned char macByte[6]); diff --git a/srcs/libs/include/zlog_module.h b/srcs/libs/include/zlog_module.h index 94f86d1..2803a81 100644 --- a/srcs/libs/include/zlog_module.h +++ b/srcs/libs/include/zlog_module.h @@ -15,13 +15,13 @@ enum { }; typedef enum { - trace = ZLOG_LEVEL_TRACE, - debug = ZLOG_LEVEL_DEBUG, - info = ZLOG_LEVEL_INFO, + trace = ZLOG_LEVEL_TRACE, + debug = ZLOG_LEVEL_DEBUG, + info = ZLOG_LEVEL_INFO, notice = ZLOG_LEVEL_NOTICE, - warn = ZLOG_LEVEL_WARN, - error = ZLOG_LEVEL_ERROR, - fatal = ZLOG_LEVEL_FATAL + warn = ZLOG_LEVEL_WARN, + error = ZLOG_LEVEL_ERROR, + fatal = ZLOG_LEVEL_FATAL } ZLOG_LV; #define DEF_ZLOG_MOD(ZLOG_MOD) \ diff --git a/srcs/libs/misc/misc.c b/srcs/libs/misc/misc.c index e61cfdb..d2c7dbf 100644 --- a/srcs/libs/misc/misc.c +++ b/srcs/libs/misc/misc.c @@ -252,9 +252,21 @@ int get_nic_info(const char *pName, const char *u32_to_str_ip(unsigned int ip) { struct in_addr s = {.s_addr = ip}; + if (ip == 0) { + return ""; + } return inet_ntoa(s); } +const char *u32_to_str_ip_safe(unsigned int ip) { + struct in_addr s = {.s_addr = ip}; + + if (ip == 0) { + return strdup(""); + } + return strdup(inet_ntoa(s)); +} + int get_all_network_info(PSYS_NIC_INFO pInfo) { int i; unsigned long nicCnt; @@ -336,6 +348,7 @@ int get_all_network_info(PSYS_NIC_INFO pInfo) { pNicInfo->nicCnt++; pNic++; + } else { LOG_MOD(warn, ZLOG_MOD_MISC, diff --git a/srcs/service/CMakeLists.txt b/srcs/service/CMakeLists.txt index d3dcbae..eefa0e2 100644 --- a/srcs/service/CMakeLists.txt +++ b/srcs/service/CMakeLists.txt @@ -6,4 +6,4 @@ AUX_SOURCE_DIRECTORY(dhcpd DHCPD_SRC) ADD_DEFINITIONS(-DOPENDHCPD_ON) ADD_DEFINITIONS(${COMMON_DEFINE}) -ADD_LIBRARY(dhcpd ${DHCPD_SRC} ${DHCPD_HEADS}) \ No newline at end of file +ADD_LIBRARY(dhcpd ${DHCPD_SRC} ${DHCPD_HEADS} dhcpd/db_interface.c dhcpd/include/db_interface.h) \ No newline at end of file diff --git a/srcs/service/dhcpd/db_interface.c b/srcs/service/dhcpd/db_interface.c new file mode 100644 index 0000000..256ea94 --- /dev/null +++ b/srcs/service/dhcpd/db_interface.c @@ -0,0 +1,216 @@ +// +// Created by HuangXin on 2023/4/24. +// + +#include +#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; +} \ No newline at end of file diff --git a/srcs/service/dhcpd/dhcpd_network.c b/srcs/service/dhcpd/dhcpd_network.c index 37bd2ce..c9058ca 100644 --- a/srcs/service/dhcpd/dhcpd_network.c +++ b/srcs/service/dhcpd/dhcpd_network.c @@ -367,7 +367,7 @@ static void on_sock_recv(uv_work_t *req) { ret = pre_alloc_dhcp_res(&reqDhcp, &ip, &pIpInfo); if (ret == ERR_SUCCESS) { - LOG_MOD(trace, + LOG_MOD(debug, ZLOG_MOD_DHCPD, "DHCP prepare assign ipaddress: [%s(%s)] --> %s\n", macStr, @@ -404,7 +404,7 @@ static void on_sock_recv(uv_work_t *req) { //dhcp_option_prase(optMsg, pkg->dhcp.options, pWork->nSize - sizeof(DHCP_PACKAGE)); //LOG_MSG_HEX(trace, pkg, pWork->nSize); - LOG_MSG(info, "vni: %d, xid: 0x%08X\n", VLAN_VNI_ID(pkg->vlan_hdr.vlan.id), DHCP_XID(pkg->dhcp.xid)); +// LOG_MSG(info, "vni: %d, xid: 0x%08X\n", VLAN_VNI_ID(pkg->vlan_hdr.vlan.id), DHCP_XID(pkg->dhcp.xid)); #if 0 LOG_MOD(info, ZLOG_MOD_DHCPD, "vlan = %u\n", VXLAN_VIN_ID_PACK(pkg->vlan_hdr.vlan.id)); diff --git a/srcs/service/dhcpd/include/db_interface.h b/srcs/service/dhcpd/include/db_interface.h new file mode 100644 index 0000000..a4c33aa --- /dev/null +++ b/srcs/service/dhcpd/include/db_interface.h @@ -0,0 +1,18 @@ +// +// Created by HuangXin on 2023/4/24. +// + +#ifndef VCPE_DB_INTERFACE_H +#define VCPE_DB_INTERFACE_H +#ifdef __cplusplus +extern "C" { +#endif +int lease_db_add_pre_assign(PDHCP_REQ pReq, U32 ip, PIPPOOL_INFO pPool); +int lease_init_database(); +int lease_get_pre_assign(U32 uid, const char *mac, const char *hostname, U32 *preAssign); +int lease_ip_is_pre_assign(U32 uid, U32 ip); +int lease_clearup_timeout_pre_assign(); +#ifdef __cplusplus +} +#endif +#endif //VCPE_DB_INTERFACE_H diff --git a/srcs/service/dhcpd/include/ip_pool.h b/srcs/service/dhcpd/include/ip_pool.h index 724d251..a9db393 100644 --- a/srcs/service/dhcpd/include/ip_pool.h +++ b/srcs/service/dhcpd/include/ip_pool.h @@ -19,6 +19,18 @@ extern "C" { */ #define MAX_POOL_HASH_KEY (18) +typedef struct POOL_CTX { + U32 minAddr; + U32 maxAddr; + U32 netMask; + U32 gwAddr; + U32 primeDNS; + U32 salveDNS; + U32 leaseTime; + + struct POOL_CTX *next, *prev; +} POOL_CTX, *PPOOL_CTX; + typedef struct { U32 poolKey; U32 minAddr; @@ -32,6 +44,24 @@ typedef struct { UT_hash_handle hh; } IPPOOL_INFO, *PIPPOOL_INFO; +typedef struct POOL_INFO { + U32 minAddr; + U32 maxAddr; + U32 netMask; + U32 gwAddr; + U32 primeDNS; + U32 salveDNS; + U32 leaseTime; + struct POOL_INFO *next; +} POOL_INFO, *PPOOL_INFO; + +typedef struct { + U32 uid; ///< 用户 ID + U32 gid; ///< 用户组 ID + PPOOL_CTX pCtx; ///< 用户配置信息 + + UT_hash_handle hh; +} POOL_CONFIG, *PPOOL_CONFIG; void init_default_pool(); #ifdef __cplusplus diff --git a/srcs/service/dhcpd/include/user_mgr.h b/srcs/service/dhcpd/include/user_mgr.h index 28ddb29..a4f73c0 100644 --- a/srcs/service/dhcpd/include/user_mgr.h +++ b/srcs/service/dhcpd/include/user_mgr.h @@ -18,6 +18,12 @@ typedef struct { PMAC_FILTER pAllowTbl; PMAC_FILTER pDenyTbl; UT_hash_handle hh; +} DHCP_USER_CFG, *PDHCP_USER_CFG; + +typedef struct { + unsigned int uid; + + PDHCP_USER_CFG pCfg; } DHCP_USER_INFO, *PDHCP_USER_INFO; int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool); diff --git a/srcs/service/dhcpd/ip_pool.c b/srcs/service/dhcpd/ip_pool.c index e49a0bb..d1d60c0 100644 --- a/srcs/service/dhcpd/ip_pool.c +++ b/srcs/service/dhcpd/ip_pool.c @@ -9,13 +9,44 @@ #include "zlog_module.h" #include "user_mgr.h" #include "ipaddr.h" +#include "uthash/utlist.h" -static PIPPOOL_INFO g_defPool = NULL; +static PIPPOOL_INFO g_defPool = NULL; +static PPOOL_CONFIG g_pUsrCommonCfg = NULL; +static PPOOL_CONFIG g_pUsrGrpCfg = NULL; +static PPOOL_CONFIG g_pUsrCfg = NULL; U32 get_ip_pool_addr(U32 defAddr) { return 0; } +static void add_usr_pool_cfg(U32 id, PPOOL_CONFIG pPoolList, PIPPOOL_INFO pPool) { + PPOOL_CTX p, pTmp; + PPOOL_CONFIG pCfg; + + // 判断当前用户组是否存在 + HASH_FIND_INT(pPoolList, &id, pCfg); + + // 不存在则新建一个配置并保存 + if (pCfg == NULL) { + + } + + // 如果存在,则遍历当前所有IP地址池配置,检查配置是否合法 + LL_FOREACH_SAFE(pPoolList->pCtx, p, pTmp) { + if (p->minAddr > pPool->minAddr && p->maxAddr < pPool->maxAddr) { + LOG_MOD(error, + ZLOG_MOD_DHCPD, + "Pool [%08X, %08X] conflict with [%08X, %08X]", + pPool->minAddr, + pPool->maxAddr, + p->minAddr, + p->maxAddr); + return; + } + } +} + void init_default_pool() { c_vector pool = (c_vector)config_get_dhcp_server_range_set(); diff --git a/srcs/service/dhcpd/lease.c b/srcs/service/dhcpd/lease.c index 1588cd3..9822a7a 100644 --- a/srcs/service/dhcpd/lease.c +++ b/srcs/service/dhcpd/lease.c @@ -10,8 +10,8 @@ #include "user_mgr.h" #include "rfc2131.h" #include "dhcp_network.h" +#include "db_interface.h" -#define LEASE_DB_NAME "lease" #define PREALLOC_IP_TIMEOUT (60) typedef struct { @@ -25,75 +25,18 @@ typedef struct { //static PMAC_FILTER g_allowTbl = NULL; //static PMAC_FILTER g_blackListTbl = NULL; -static PPRE_ALLOC_IP g_pPreAllocIp = 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}; +U32 lease_is_pre_assign(PDHCP_REQ pReq) { char macStr[20] = {0}; + U32 ipAddr; 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; + if (lease_get_pre_assign(pReq->uid, macStr, pReq->hostName, &ipAddr) == ERR_ITEM_EXISTS) { + return ipAddr; } - DEBUG_CODE_LINE(); - return ERR_SUCCESS; + return 0; } //int pre_alloc_dhcp_res(U32 uid, const char *pMac, U32 *pOutIp, PIPPOOL_INFO *pOutPool) { @@ -118,18 +61,12 @@ int pre_alloc_dhcp_res(PDHCP_REQ pReq, U32 *pOutIp, PIPPOOL_INFO *pOutPool) { 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; - } - } + if ((addr = lease_is_pre_assign(pReq)) != 0) { + *pOutIp = addr; + *pOutPool = pPool; + return ERR_SUCCESS; } -#endif + while ((addr = bitset_minimum(pPool->assignPool)) > 0) { U32 ipAddr = (pPool->minAddr & pPool->netMask) + addr; @@ -140,27 +77,8 @@ int pre_alloc_dhcp_res(PDHCP_REQ pReq, U32 *pOutIp, PIPPOOL_INFO *pOutPool) { // 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(); + // 查找IP地址是否已经被预分配, 未分配直接分配IP地址 + if (lease_ip_is_pre_assign(pReq->uid, ipAddr) == FALSE) { lease_db_add_pre_assign(pReq, ipAddr, pPool); *pOutIp = ipAddr; @@ -170,46 +88,12 @@ int pre_alloc_dhcp_res(PDHCP_REQ pReq, U32 *pOutIp, PIPPOOL_INFO *pOutPool) { 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 + lease_clearup_timeout_pre_assign(); // 没有可预分配的IP,报错 LOG_MOD(error, ZLOG_MOD_DHCPD, @@ -222,13 +106,7 @@ int pre_alloc_dhcp_res(PDHCP_REQ pReq, U32 *pOutIp, PIPPOOL_INFO *pOutPool) { 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); + rc = lease_init_database(); if (rc != ERR_SUCCESS) { return rc; diff --git a/srcs/service/dhcpd/user_mgr.c b/srcs/service/dhcpd/user_mgr.c index 7adfb0d..1a172ec 100644 --- a/srcs/service/dhcpd/user_mgr.c +++ b/srcs/service/dhcpd/user_mgr.c @@ -1,6 +1,7 @@ // // Created by xajhuang on 2023/3/21. // +#include #include "user_mgr.h" #include "user_errno.h" #include "zlog_module.h" @@ -11,23 +12,37 @@ #include "misc.h" #endif -static PDHCP_USER_INFO g_dhcpUsrCfg = NULL; -#define INIT_DHCP_USER(id) \ - /* region INIT_DHCP_USER Macro define */ \ - do { \ - HASH_FIND_INT(g_dhcpUsrCfg, &(id), pUserCfg); \ - if (pUserCfg == NULL) { \ - pUserCfg = (PDHCP_USER_INFO)malloc(sizeof(DHCP_USER_INFO)); \ - \ - if (pUserCfg == NULL) { \ - LOG_MOD(error, ZLOG_MOD_USER, "Malloc memory error: %lu\n", sizeof(DHCP_USER_INFO)); \ - return -ERR_MALLOC_MEMORY; \ - } \ - memset(pUserCfg, 0, sizeof(DHCP_USER_INFO)); \ - pUserCfg->uid = (id); \ - HASH_ADD_INT(g_dhcpUsrCfg, uid, pUserCfg); \ - } \ +typedef struct { + U32 uid; ///< 用户ID + + PPOOL_INFO pUserPool; ///< 用户地址池 + UT_hash_handle hh; +} DHCP_USER, *PDHCP_USER; + +static PDHCP_USER_CFG g_dhcpUsrCfg = NULL; + +static PPOOL_INFO g_userCommonPool = NULL; +//static PPOOL_INFO g_userGrpPool = NULL; + +// 当前用户列表,通过数据包自动发现 +static PDHCP_USER g_dhcpUserList = NULL; + +#define INIT_DHCP_USER(id) \ + /* region INIT_DHCP_USER Macro define */ \ + do { \ + HASH_FIND_INT(g_dhcpUsrCfg, &(id), pUserCfg); \ + if (pUserCfg == NULL) { \ + pUserCfg = (PDHCP_USER_CFG)malloc(sizeof(DHCP_USER_CFG)); \ + \ + if (pUserCfg == NULL) { \ + LOG_MOD(error, ZLOG_MOD_USER, "Malloc memory error: %lu\n", sizeof(DHCP_USER_CFG)); \ + return -ERR_MALLOC_MEMORY; \ + } \ + memset(pUserCfg, 0, sizeof(DHCP_USER_CFG)); \ + pUserCfg->uid = (id); \ + HASH_ADD_INT(g_dhcpUsrCfg, uid, pUserCfg); \ + } \ } while (0) // endregion @@ -67,7 +82,7 @@ static int get_user_pool_cfg(const char **pRsp, const char *pRequest) { cJSON_AddItemToObject(pRspRoot, "poolSet", pPoolCfgs); if (cJSON_GetArraySize(pUidSet) == 0) { - PDHCP_USER_INFO pInfo, pTemp; + PDHCP_USER_CFG pInfo, pTemp; HASH_ITER(hh, g_dhcpUsrCfg, pInfo, pTemp) { cJSON *pUid = cJSON_CreateObject(); @@ -84,14 +99,17 @@ static int get_user_pool_cfg(const char **pRsp, const char *pRequest) { cJSON *pItem = cJSON_CreateObject(); memset(buf, 0, 256); - sprintf(buf, "%s-%s", u32_to_str_ip(pPool->minAddr), u32_to_str_ip(pPool->maxAddr)); + sprintf(buf, "%s-", u32_to_str_ip_safe(htonl(pPool->minAddr))); + // Because: u32_to_str_ip call inet_ntoa not thread safe + strcat(buf, u32_to_str_ip_safe(htonl(pPool->maxAddr))); cJSON_AddStringToObject(pItem, "dhcp_range", buf); - cJSON_AddStringToObject(pItem, "netMask", u32_to_str_ip(pPool->netMask)); - cJSON_AddStringToObject(pItem, "gateway", u32_to_str_ip(pPool->gwAddr)); + cJSON_AddStringToObject(pItem, "netMask", u32_to_str_ip(htonl(pPool->netMask))); + cJSON_AddStringToObject(pItem, "gateway", u32_to_str_ip(htonl(pPool->gwAddr))); memset(buf, 0, 256); - sprintf(buf, "%s,", u32_to_str_ip(pPool->primeDNS)); - strcat(buf, u32_to_str_ip(pPool->salveDNS)); + sprintf(buf, "%s,", u32_to_str_ip(htonl(pPool->primeDNS))); + // Because: u32_to_str_ip call inet_ntoa not thread safe + strcat(buf, u32_to_str_ip(htonl(pPool->salveDNS))); cJSON_AddStringToObject(pItem, "domain_server", buf); cJSON_AddNumberToObject(pItem, "lease", pPool->leaseTime); @@ -102,9 +120,9 @@ static int get_user_pool_cfg(const char **pRsp, const char *pRequest) { } } else { for (i = 0; i < cJSON_GetArraySize(pUidSet); i++) { - PDHCP_USER_INFO pInfo; - cJSON *pId = cJSON_GetArrayItem(pUidSet, i); - cJSON *pUid = cJSON_CreateObject(); + PDHCP_USER_CFG pInfo; + cJSON *pId = cJSON_GetArrayItem(pUidSet, i); + cJSON *pUid = cJSON_CreateObject(); cJSON_AddItemToArray(pPoolCfgs, pUid); cJSON_AddNumberToObject(pUid, "uid", pId->valueint); @@ -123,14 +141,16 @@ static int get_user_pool_cfg(const char **pRsp, const char *pRequest) { cJSON *pItem = cJSON_CreateObject(); memset(buf, 0, 256); - sprintf(buf, "%s-%s", u32_to_str_ip(pPool->minAddr), u32_to_str_ip(pPool->maxAddr)); + sprintf(buf, "%s-", u32_to_str_ip_safe(htonl(pPool->minAddr))); + strcat(buf, u32_to_str_ip_safe(htonl(pPool->maxAddr))); + cJSON_AddStringToObject(pItem, "dhcp_range", buf); - cJSON_AddStringToObject(pItem, "netMask", u32_to_str_ip(pPool->netMask)); - cJSON_AddStringToObject(pItem, "gateway", u32_to_str_ip(pPool->gwAddr)); + cJSON_AddStringToObject(pItem, "netMask", u32_to_str_ip(htonl(pPool->netMask))); + cJSON_AddStringToObject(pItem, "gateway", u32_to_str_ip(htonl(pPool->gwAddr))); memset(buf, 0, 256); - sprintf(buf, "%s,", u32_to_str_ip(pPool->primeDNS)); - strcat(buf, u32_to_str_ip(pPool->salveDNS)); + sprintf(buf, "%s,", u32_to_str_ip(htonl(pPool->primeDNS))); + strcat(buf, u32_to_str_ip(htonl(pPool->salveDNS))); cJSON_AddStringToObject(pItem, "domain_server", buf); cJSON_AddNumberToObject(pItem, "lease", pPool->leaseTime); @@ -180,6 +200,50 @@ int user_init_httpd() { // endregion #endif +PDHCP_USER dhcp_user_create(U32 uId) { + PDHCP_USER pUser; + + // 判断当前用户是否存在 + HASH_FIND_INT(g_dhcpUserList, &uId, pUser); + + if (pUser) { + return pUser; + } + + pUser = (PDHCP_USER)malloc(sizeof(DHCP_USER)); + + // 创建一个新用户 + if (pUser) { + memset(pUser, 0, sizeof(DHCP_USER)); + pUser->uid = uId; + // 添加用户 + HASH_ADD_INT(g_dhcpUserList, uid, pUser); + return pUser; + } + + return NULL; +} + +int dhcp_user_assign_common_pool(PDHCP_USER pUser, PPOOL_INFO pPool) { + if (pUser == NULL || pPool == NULL) { + return -ERR_INPUT_PARAMS; + } + + LL_APPEND(g_userCommonPool, pPool); + + return ERR_SUCCESS; +} + +int dhcp_user_assign_pool(PDHCP_USER pUser, PPOOL_INFO pPool) { + if (pUser == NULL || pPool == NULL) { + return -ERR_INPUT_PARAMS; + } + + LL_APPEND(pUser->pUserPool, pPool); + + return ERR_SUCCESS; +} + int dhcp_user_mgr_init() { #ifdef HTTPSERVER_ON user_init_httpd(); @@ -190,7 +254,7 @@ int dhcp_user_mgr_init() { } int user_alloc_addr(U32 uId, U8 mac[ETH_ALEN], U32 *pAddr) { - PDHCP_USER_INFO pUserCfg, pTemp; + PDHCP_USER_CFG pUserCfg, pTemp; INIT_DHCP_USER(uId); @@ -198,7 +262,7 @@ int user_alloc_addr(U32 uId, U8 mac[ETH_ALEN], U32 *pAddr) { } PIPPOOL_INFO user_get_pool(U32 uId) { - PDHCP_USER_INFO pUser; + PDHCP_USER_CFG pUser; HASH_FIND_INT(g_dhcpUsrCfg, &uId, pUser); @@ -218,11 +282,11 @@ PIPPOOL_INFO user_get_pool(U32 uId) { } int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool) { - U32 k; - U32 begin; - U32 end; - PIPPOOL_INFO pPoolCfg; - PDHCP_USER_INFO pUserCfg, pTemp; + U32 k; + U32 begin; + U32 end; + PIPPOOL_INFO pPoolCfg; + PDHCP_USER_CFG pUserCfg, pTemp; INIT_DHCP_USER(uId);