Merge branch 'libuv_dhcpd_dev' of http://git.komect.net/ZNJK/vcpe into v1.2.0_dev

This commit is contained in:
dongwenze 2023-04-10 16:45:10 +08:00
commit e03b56e745
25 changed files with 1322 additions and 157 deletions

View File

@ -72,7 +72,7 @@ BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true BreakStringLiterals: true
ColumnLimit: 120 ColumnLimit: 140
CommentPragmas: '^ IWYU pragma:' CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: true CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
@ -135,7 +135,7 @@ ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 1000 PenaltyBreakAssignment: 1000
PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300 PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120 PenaltyBreakFirstLessLess: 140
PenaltyBreakString: 1000 PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10 PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000 PenaltyExcessCharacter: 1000000

View File

@ -131,9 +131,21 @@ ENDIF ()
IF (USED_SQLITE) IF (USED_SQLITE)
MESSAGE("Select Option USED_SQLITE") MESSAGE("Select Option USED_SQLITE")
LIST(APPEND COMMON_DEFINE "-DSQLITE_ON")
ENDIF ()
IF (USED_MYSQL)
MESSAGE("Select Option USED_MYSQL")
LIST(APPEND COMMON_DEFINE "-DUSED_MYSQL")
ENDIF ()
IF (USED_REDIS)
MESSAGE("Select Option USED_REDIS")
LIST(APPEND COMMON_DEFINE "-DUSED_REDIS")
ENDIF () ENDIF ()
IF (USED_SQLITE_CRYPTO) IF (USED_SQLITE_CRYPTO)
LIST(APPEND COMMON_DEFINE "-DSQLITE_CRYPTO_ON")
MESSAGE("Select Option USED_SQLITE_CRYPTO") MESSAGE("Select Option USED_SQLITE_CRYPTO")
ENDIF () ENDIF ()

View File

@ -40,8 +40,8 @@ application:
mysql_passwd = "AES@5/BQyUIfVxgV9BZAz/D3Rg=="; # mysql 数据库密码 mysql_passwd = "AES@5/BQyUIfVxgV9BZAz/D3Rg=="; # mysql 数据库密码
mysql_database = "test"; # mysql 数据库名称 mysql_database = "test"; # mysql 数据库名称
sqlite_dbname = "vcpe.db"; # sqlite3 数据库文件名 sqlite_dbname = "/home/hx/vcpe.db"; # sqlite3 数据库文件名
sqlite_passwd = "test123"; # sqlite3 数据库密码 sqlite_passwd = ""; # sqlite3 数据库密码
}; };
# MQ 相关配置 # MQ 相关配置
@ -101,7 +101,7 @@ application:
# mac_filter = ["00:01:02:03:04:07", "00:01:02:03:04:01"]; # mac_filter = ["00:01:02:03:04:07", "00:01:02:03:04:01"];
# IP地址池配置 # IP地址池配置
range_set: ( range_set: (
{ dhcp_range = "192.168.101.2-192.168.101.4"; { dhcp_range = "192.168.101.0-192.168.101.4";
subnet_mask = "255.255.255.0"; subnet_mask = "255.255.255.0";
domain_server = "114.114.114.114,8.8.8.8"; domain_server = "114.114.114.114,8.8.8.8";
gateway = "192.168.101.1"; gateway = "192.168.101.1";

View File

@ -9,6 +9,9 @@
extern "C" { extern "C" {
#endif #endif
#define DHCP_SVR_PORT (67)
#define DHCP_CLI_PORT (68)
/** /**
* Message op code / message type * Message op code / message type
* Request Message * Request Message
@ -21,6 +24,7 @@ extern "C" {
#define BOOTP_REPLY 2 #define BOOTP_REPLY 2
#define DHCP_MSG_NONE 0 #define DHCP_MSG_NONE 0
/** /**
* DHCP客户端在请求IP地址时并不知道DHCP服务器的位置 * DHCP客户端在请求IP地址时并不知道DHCP服务器的位置
* DHCP客户端会在本地网络内以广播方式发送Discover请求报文DHCP服务器 * DHCP客户端会在本地网络内以广播方式发送Discover请求报文DHCP服务器
@ -28,6 +32,7 @@ extern "C" {
* DHCP客户端据此可以知道网络中存在的DHCP服务器的位置 * DHCP客户端据此可以知道网络中存在的DHCP服务器的位置
*/ */
#define DHCP_MSG_DISCOVER 1 #define DHCP_MSG_DISCOVER 1
/** /**
* DHCP服务器收到Discover报文后IP地址 * DHCP服务器收到Discover报文后IP地址
* DNS服务器等Offer报文 * DNS服务器等Offer报文
@ -35,6 +40,7 @@ extern "C" {
* ARP来检测该IP地址是否重复 * ARP来检测该IP地址是否重复
*/ */
#define DHCP_MSG_OFFER 2 #define DHCP_MSG_OFFER 2
/** /**
* DHCP客户端可能会收到很多Offer请求报文 * DHCP客户端可能会收到很多Offer请求报文
* Offer应答报文的服务器作为自己的目标服务器 * Offer应答报文的服务器作为自己的目标服务器
@ -44,28 +50,33 @@ extern "C" {
* ACK报文87.5%广Request请求报文以请求续延租约 * ACK报文87.5%广Request请求报文以请求续延租约
*/ */
#define DHCP_MSG_REQUEST 3 #define DHCP_MSG_REQUEST 3
/** /**
* DHCP客户端收到DHCP服务器ACK应答报文后 * DHCP客户端收到DHCP服务器ACK应答报文后
* 使 * 使
* DHCP服务器发送Decline请求报文IP地址不可用IP地址 * DHCP服务器发送Decline请求报文IP地址不可用IP地址
*/ */
#define DHCP_MSG_DECLINE 4 #define DHCP_MSG_DECLINE 4
/** /**
* DHCP服务器收到Request请求报文后Request报文中携带的用户MAC来查找有没有相应的租约记录 * DHCP服务器收到Request请求报文后Request报文中携带的用户MAC来查找有没有相应的租约记录
* ACK应答报文使IP地址 * ACK应答报文使IP地址
*/ */
#define DHCP_MSG_ACK 5 #define DHCP_MSG_ACK 5
/** /**
* DHCP服务器收到Request请求报文后IP地址 * DHCP服务器收到Request请求报文后IP地址
* DHCP客户端发送NAK应答报文IP地址 * DHCP客户端发送NAK应答报文IP地址
*/ */
#define DHCP_MSG_NAK 6 #define DHCP_MSG_NAK 6
/** /**
* DHCP客户端不再需要使用分配IP地址时线 * DHCP客户端不再需要使用分配IP地址时线
* DHCP服务器发送RELEASE请求报文IP地址 * DHCP服务器发送RELEASE请求报文IP地址
* DHCP服务器释放对应的IP地址 * DHCP服务器释放对应的IP地址
*/ */
#define DHCP_MSG_RELEASE 7 #define DHCP_MSG_RELEASE 7
/** /**
* DHCP客户端如果需要从DHCP服务器端获取更为详细的配置信息 * DHCP客户端如果需要从DHCP服务器端获取更为详细的配置信息
* DHCP服务器发送Inform请求报文DHCP服务器在收到该报文后 * DHCP服务器发送Inform请求报文DHCP服务器在收到该报文后

View File

@ -17,6 +17,7 @@ AUX_SOURCE_DIRECTORY(json C_SRC)
AUX_SOURCE_DIRECTORY(args C_SRC) AUX_SOURCE_DIRECTORY(args C_SRC)
AUX_SOURCE_DIRECTORY(init C_SRC) AUX_SOURCE_DIRECTORY(init C_SRC)
AUX_SOURCE_DIRECTORY(misc C_SRC) AUX_SOURCE_DIRECTORY(misc C_SRC)
AUX_SOURCE_DIRECTORY(bitset C_SRC)
AUX_SOURCE_DIRECTORY(banner C_SRC) AUX_SOURCE_DIRECTORY(banner C_SRC)
AUX_SOURCE_DIRECTORY(configure C_SRC) AUX_SOURCE_DIRECTORY(configure C_SRC)
AUX_SOURCE_DIRECTORY(network C_SRC) AUX_SOURCE_DIRECTORY(network C_SRC)
@ -40,22 +41,13 @@ IF (USED_HTTP_SVR)
AUX_SOURCE_DIRECTORY(mongoose C_SRC) AUX_SOURCE_DIRECTORY(mongoose C_SRC)
ENDIF () ENDIF ()
IF (USED_REDIS)
ADD_DEFINITIONS(-DUSED_REDIS)
ENDIF ()
IF (USED_SQLITE) IF (USED_SQLITE)
ADD_DEFINITIONS(-DSQLITE_ON) LIST(APPEND C_SRC database/database.c)
IF (SQLITE_CRYPTO_ON) IF (SQLITE_CRYPTO_ON)
ADD_DEFINITIONS(-DSQLITE_CRYPTO_ON)
AUX_SOURCE_DIRECTORY(database/sqlite3 C_SRC) AUX_SOURCE_DIRECTORY(database/sqlite3 C_SRC)
ENDIF () ENDIF ()
ENDIF () ENDIF ()
IF (USED_MYSQL)
ADD_DEFINITIONS(-DUSED_MYSQL)
ENDIF ()
SET(CMAKE_C_STANDARD 99) SET(CMAKE_C_STANDARD 99)
SET_SOURCE_FILES_PROPERTIES(misc/zvector.c PROPERTIES COMPILE_FLAGS "-Wall -Wextra -flto") SET_SOURCE_FILES_PROPERTIES(misc/zvector.c PROPERTIES COMPILE_FLAGS "-Wall -Wextra -flto")
@ -71,7 +63,11 @@ IF (USED_SQLITE_CRYPTO)
-DSQLITE_HAVE_ZLIB=1 -DSQLITE_TEMP_STORE=2") -DSQLITE_HAVE_ZLIB=1 -DSQLITE_TEMP_STORE=2")
ENDIF () ENDIF ()
ADD_DEFINITIONS(${COMMON_DEFINE} -DMG_ARCH=MG_ARCH_UNIX -DMG_ENABLE_OPENSSL=1) ADD_DEFINITIONS(${COMMON_DEFINE})
IF (USED_HTTP_SVR)
ADD_DEFINITIONS(-DMG_ARCH=MG_ARCH_UNIX -DMG_ENABLE_OPENSSL=1)
ENDIF ()
ADD_LIBRARY(${LIB_PROJECT_TARGET} ${C_SRC} ${C_HEADS}) ADD_LIBRARY(${LIB_PROJECT_TARGET} ${C_SRC} ${C_HEADS})

382
srcs/libs/bitset/bitset.c Normal file
View File

@ -0,0 +1,382 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "bitset/bitset.h"
/* Create a new bitset. Return NULL in case of failure. */
bitset_t *bitset_create() {
bitset_t *bitset = NULL;
/* Allocate the bitset itself. */
if ((bitset = (bitset_t *)malloc(sizeof(bitset_t))) == NULL) {
return NULL;
}
bitset->array = NULL;
bitset->arraysize = 0;
bitset->capacity = 0;
return bitset;
}
/* Create a new bitset able to contain size bits. Return NULL in case of failure. */
bitset_t *bitset_create_with_capacity(size_t size) {
bitset_t *bitset = NULL;
/* Allocate the bitset itself. */
if ((bitset = (bitset_t *)malloc(sizeof(bitset_t))) == NULL) {
return NULL;
}
bitset->arraysize = (size + sizeof(uint64_t) * 8 - 1) / (sizeof(uint64_t) * 8);
bitset->capacity = bitset->arraysize;
if ((bitset->array = (uint64_t *)calloc(bitset->arraysize, sizeof(uint64_t))) == NULL) {
free(bitset);
return NULL;
}
return bitset;
}
/* Create a copy */
bitset_t *bitset_copy(const bitset_t *bitset) {
bitset_t *copy = NULL;
/* Allocate the bitset itself. */
if ((copy = (bitset_t *)malloc(sizeof(bitset_t))) == NULL) {
return NULL;
}
memcpy(copy, bitset, sizeof(bitset_t));
copy->capacity = copy->arraysize;
if ((copy->array = (uint64_t *)malloc(sizeof(uint64_t) * bitset->arraysize)) == NULL) {
free(copy);
return NULL;
}
memcpy(copy->array, bitset->array, sizeof(uint64_t) * bitset->arraysize);
return copy;
}
void bitset_clear(bitset_t *bitset) {
memset(bitset->array, 0, sizeof(uint64_t) * bitset->arraysize);
}
void bitset_shift_left(bitset_t *bitset, size_t s) {
size_t extra_words = s / 64;
int inword_shift = (int)(s % 64);
size_t as = bitset->arraysize;
if (inword_shift == 0) {
bitset_resize(bitset, as + extra_words, FALSE);
// could be done with a memmove
for (size_t i = as + extra_words; i > extra_words; i--) {
bitset->array[i - 1] = bitset->array[i - 1 - extra_words];
}
} else {
bitset_resize(bitset, as + extra_words + 1, TRUE);
bitset->array[as + extra_words] = bitset->array[as - 1] >> (64 - inword_shift);
for (size_t i = as + extra_words; i >= extra_words + 2; i--) {
bitset->array[i - 1] = (bitset->array[i - 1 - extra_words] << inword_shift) |
(bitset->array[i - 2 - extra_words] >> (64 - inword_shift));
}
bitset->array[extra_words] = bitset->array[0] << inword_shift;
}
for (size_t i = 0; i < extra_words; i++) {
bitset->array[i] = 0;
}
}
void bitset_shift_right(bitset_t *bitset, size_t s) {
size_t extra_words = s / 64;
int inword_shift = (int)(s % 64);
size_t as = bitset->arraysize;
if (inword_shift == 0) {
// could be done with a memmove
for (size_t i = 0; i < as - extra_words; i++) {
bitset->array[i] = bitset->array[i + extra_words];
}
bitset_resize(bitset, as - extra_words, FALSE);
} else {
for (size_t i = 0; i + extra_words + 1 < as; i++) {
bitset->array[i] = (bitset->array[i + extra_words] >> inword_shift) |
(bitset->array[i + extra_words + 1] << (64 - inword_shift));
}
bitset->array[as - extra_words - 1] = (bitset->array[as - 1] >> inword_shift);
bitset_resize(bitset, as - extra_words, FALSE);
}
}
/* Free memory. */
void bitset_free(bitset_t *bitset) {
free(bitset->array);
free(bitset);
}
/* Resize the bitset so that it can support newarraysize * 64 bits. Return TRUE in case of success, FALSE for failure. */
int bitset_resize(bitset_t *bitset, size_t newarraysize, int padwithzeroes) {
size_t smallest = newarraysize < bitset->arraysize ? newarraysize : bitset->arraysize;
if (bitset->capacity < newarraysize) {
uint64_t *newarray;
bitset->capacity = newarraysize * 2;
if ((newarray = (uint64_t *)realloc(bitset->array, sizeof(uint64_t) * bitset->capacity)) == NULL) {
free(bitset->array);
return FALSE;
}
bitset->array = newarray;
}
if (padwithzeroes && (newarraysize > smallest)) {
memset(bitset->array + smallest, 0, sizeof(uint64_t) * (newarraysize - smallest));
}
bitset->arraysize = newarraysize;
return TRUE; // success!
}
size_t bitset_count(const bitset_t *bitset) {
size_t card = 0;
size_t k = 0;
// assumes that long long is 8 bytes
for (; k + 7 < bitset->arraysize; k += 8) {
card += __builtin_popcountll(bitset->array[k]);
card += __builtin_popcountll(bitset->array[k + 1]);
card += __builtin_popcountll(bitset->array[k + 2]);
card += __builtin_popcountll(bitset->array[k + 3]);
card += __builtin_popcountll(bitset->array[k + 4]);
card += __builtin_popcountll(bitset->array[k + 5]);
card += __builtin_popcountll(bitset->array[k + 6]);
card += __builtin_popcountll(bitset->array[k + 7]);
}
for (; k + 3 < bitset->arraysize; k += 4) {
card += __builtin_popcountll(bitset->array[k]);
card += __builtin_popcountll(bitset->array[k + 1]);
card += __builtin_popcountll(bitset->array[k + 2]);
card += __builtin_popcountll(bitset->array[k + 3]);
}
for (; k < bitset->arraysize; k++) {
card += __builtin_popcountll(bitset->array[k]);
}
return card;
}
int bitset_inplace_union(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
for (size_t k = 0; k < minlength; ++k) {
b1->array[k] |= b2->array[k];
}
if (b2->arraysize > b1->arraysize) {
size_t oldsize = b1->arraysize;
if (!bitset_resize(b1, b2->arraysize, FALSE)) {
return FALSE;
}
memcpy(b1->array + oldsize, b2->array + oldsize, (b2->arraysize - oldsize) * sizeof(uint64_t));
}
return TRUE;
}
size_t bitset_minimum(const bitset_t *bitset) {
for (size_t k = 0; k < bitset->arraysize; k++) {
uint64_t w = bitset->array[k];
if (w != 0) {
return __builtin_ctzll(w) + k * 64;
}
}
return 0;
}
size_t bitset_maximum(const bitset_t *bitset) {
for (size_t k = bitset->arraysize; k > 0; k--) {
uint64_t w = bitset->array[k - 1];
if (w != 0) {
return 63 - __builtin_clzll(w) + (k - 1) * 64;
}
}
return 0;
}
/* Returns TRUE if bitsets share no common elements, FALSE otherwise.
*
* Performs early-out if common element found. */
int bitsets_disjoint(const bitset_t *b1, const bitset_t *b2) {
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
for (size_t k = 0; k < minlength; k++) {
if ((b1->array[k] & b2->array[k]) != 0) {
return FALSE;
}
}
return TRUE;
}
/* Returns TRUE if bitsets contain at least 1 common element, FALSE if they are
* disjoint.
*
* Performs early-out if common element found. */
int bitsets_intersect(const bitset_t *b1, const bitset_t *b2) {
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
for (size_t k = 0; k < minlength; k++) {
if ((b1->array[k] & b2->array[k]) != 0) {
return TRUE;
}
}
return FALSE;
}
/* Returns TRUE if b has any bits set in or after b->array[starting_loc]. */
static int any_bits_set(const bitset_t *b, size_t starting_loc) {
if (starting_loc >= b->arraysize) {
return FALSE;
}
for (size_t k = starting_loc; k < b->arraysize; k++) {
if (b->array[k] != 0) {
return TRUE;
}
}
return FALSE;
}
/* Returns TRUE if b1 has all of b2's bits set.
*
* Performs early out if a bit is found in b2 that is not found in b1. */
int bitset_contains_all(const bitset_t *b1, const bitset_t *b2) {
for (size_t k = 0; k < b1->arraysize; k++) {
if ((b1->array[k] & b2->array[k]) != b2->array[k]) {
return FALSE;
}
}
if (b2->arraysize > b1->arraysize) {
/* Need to check if b2 has any bits set beyond b1's array */
return !any_bits_set(b2, b1->arraysize);
}
return TRUE;
}
size_t bitset_union_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
size_t answer = 0;
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
for (; k + 3 < minlength; k += 4) {
answer += __builtin_popcountll(b1->array[k] | b2->array[k]);
answer += __builtin_popcountll(b1->array[k + 1] | b2->array[k + 1]);
answer += __builtin_popcountll(b1->array[k + 2] | b2->array[k + 2]);
answer += __builtin_popcountll(b1->array[k + 3] | b2->array[k + 3]);
}
for (; k < minlength; ++k) {
answer += __builtin_popcountll(b1->array[k] | b2->array[k]);
}
if (b2->arraysize > b1->arraysize) {
//k = b1->arraysize;
for (; k + 3 < b2->arraysize; k += 4) {
answer += __builtin_popcountll(b2->array[k]);
answer += __builtin_popcountll(b2->array[k + 1]);
answer += __builtin_popcountll(b2->array[k + 2]);
answer += __builtin_popcountll(b2->array[k + 3]);
}
for (; k < b2->arraysize; ++k) {
answer += __builtin_popcountll(b2->array[k]);
}
} else {
//k = b2->arraysize;
for (; k + 3 < b1->arraysize; k += 4) {
answer += __builtin_popcountll(b1->array[k]);
answer += __builtin_popcountll(b1->array[k + 1]);
answer += __builtin_popcountll(b1->array[k + 2]);
answer += __builtin_popcountll(b1->array[k + 3]);
}
for (; k < b1->arraysize; ++k) {
answer += __builtin_popcountll(b1->array[k]);
}
}
return answer;
}
void bitset_inplace_intersection(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
for (; k < minlength; ++k) {
b1->array[k] &= b2->array[k];
}
for (; k < b1->arraysize; ++k) {
b1->array[k] = 0; // memset could, maybe, be a tiny bit faster
}
}
size_t bitset_intersection_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
size_t answer = 0;
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
for (size_t k = 0; k < minlength; ++k) {
answer += __builtin_popcountll(b1->array[k] & b2->array[k]);
}
return answer;
}
void bitset_inplace_difference(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
for (; k < minlength; ++k) {
b1->array[k] &= ~(b2->array[k]);
}
}
size_t bitset_difference_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
size_t answer = 0;
for (; k < minlength; ++k) {
answer += __builtin_popcountll(b1->array[k] & ~(b2->array[k]));
}
for (; k < b1->arraysize; ++k) {
answer += __builtin_popcountll(b1->array[k]);
}
return answer;
}
int bitset_inplace_symmetric_difference(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
for (; k < minlength; ++k) {
b1->array[k] ^= b2->array[k];
}
if (b2->arraysize > b1->arraysize) {
size_t oldsize = b1->arraysize;
if (!bitset_resize(b1, b2->arraysize, FALSE)) {
return FALSE;
}
memcpy(b1->array + oldsize, b2->array + oldsize, (b2->arraysize - oldsize) * sizeof(uint64_t));
}
return TRUE;
}
size_t bitset_symmetric_difference_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
size_t answer = 0;
for (; k < minlength; ++k) {
answer += __builtin_popcountll(b1->array[k] ^ b2->array[k]);
}
if (b2->arraysize > b1->arraysize) {
for (; k < b2->arraysize; ++k) {
answer += __builtin_popcountll(b2->array[k]);
}
} else {
for (; k < b1->arraysize; ++k) {
answer += __builtin_popcountll(b1->array[k]);
}
}
return answer;
}
int bitset_trim(bitset_t *bitset) {
size_t newsize = bitset->arraysize;
while (newsize > 0) {
if (bitset->array[newsize - 1] == 0) {
newsize -= 1;
} else {
break;
}
}
if (bitset->capacity == newsize) {
return TRUE; // nothing to do
}
bitset->capacity = newsize;
bitset->arraysize = newsize;
uint64_t *newarray;
if ((newarray = (uint64_t *)realloc(bitset->array, sizeof(uint64_t) * bitset->capacity)) == NULL) {
free(bitset->array);
return FALSE;
}
bitset->array = newarray;
return TRUE;
}

View File

@ -0,0 +1,63 @@
//
// Created by xajhuang on 2023/3/29.
//
#ifdef SQLITE_ON
#include <sqlite3.h>
#include <string.h>
#include "zlog_module.h"
#include "user_errno.h"
#include "config.h"
#include "database.h"
static sqlite3 *g_pSqlHandle = NULL;
int db_sqlite3_init() {
int rc;
const char *pDbPath = cfg_get_sqlite_db_name();
if (pDbPath == NULL || strlen(pDbPath) == 0) {
return ERR_SUCCESS;
}
if (g_pSqlHandle == NULL) {
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);
return -ERR_DB_CONNECT;
}
}
LOG_MOD(info, ZLOG_MOD_DB, "Used SQLite3 database: %s\n", pDbPath);
return ERR_SUCCESS;
}
int db_sqlite3_sql_exec(const char *pSqlCmd, void *pCallback, void *pData, 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_exec(g_pSqlHandle, pSqlCmd, pCallback, pData, 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;
}
}
void db_sqlite3_uninit() {
if (g_pSqlHandle) {
sqlite3_close(g_pSqlHandle);
}
}
#endif

View File

@ -0,0 +1,271 @@
//
// Created by xajhuang on 2023/4/6.
//
#ifndef VCPE_BITSET_H
#define VCPE_BITSET_H
#include <common.h>
#ifdef __cplusplus
extern "C" {
#endif
// For compatibility with MSVC with the use of `restrict`
#if (__STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && defined(__STDC_VERSION__))
#define CBITSET_RESTRICT restrict
#else
#define CBITSET_RESTRICT
#endif // (__STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && defined(__STDC_VERSION__ ))
struct bitset_s {
uint64_t *CBITSET_RESTRICT array;
size_t arraysize;
size_t capacity;
};
typedef struct bitset_s bitset_t;
/* Create a new bitset. Return NULL in case of failure. */
bitset_t *bitset_create(void);
/* Create a new bitset able to contain size bits. Return NULL in case of failure. */
bitset_t *bitset_create_with_capacity(size_t size);
/* Free memory. */
void bitset_free(bitset_t *bitset);
/* Set all bits to zero. */
void bitset_clear(bitset_t *bitset);
/* Create a copy */
bitset_t *bitset_copy(const bitset_t *bitset);
/* Resize the bitset. Return TRUE in case of success, FALSE for failure. Pad with zeroes new buffer areas if requested. */
int bitset_resize(bitset_t *bitset, size_t newarraysize, int padwithzeroes);
/* returns how many bytes of memory the backend buffer uses */
static inline size_t bitset_size_in_bytes(const bitset_t *bitset) {
return bitset->arraysize * sizeof(uint64_t);
}
/* returns how many bits can be accessed */
static inline size_t bitset_size_in_bits(const bitset_t *bitset) {
return bitset->arraysize * 64;
}
/* returns how many words (64-bit) of memory the backend buffer uses */
static inline size_t bitset_size_in_words(const bitset_t *bitset) {
return bitset->arraysize;
}
/* Grow the bitset so that it can support newarraysize * 64 bits with padding. Return TRUE in case of success, FALSE for failure. */
static inline int bitset_grow(bitset_t *bitset, size_t newarraysize) {
if (bitset->capacity < newarraysize) {
uint64_t *newarray;
bitset->capacity = newarraysize * 2;
if ((newarray = (uint64_t *)realloc(bitset->array, sizeof(uint64_t) * bitset->capacity)) == NULL) {
free(bitset->array);
return FALSE;
}
bitset->array = newarray;
}
memset(bitset->array + bitset->arraysize, 0, sizeof(uint64_t) * (newarraysize - bitset->arraysize));
bitset->arraysize = newarraysize;
return TRUE; // success!
}
/* attempts to recover unused memory, return FALSE in case of reallocation failure */
int bitset_trim(bitset_t *bitset);
/* shifts all bits by 's' positions so that the bitset representing values 1,2,10 would represent values 1+s, 2+s, 10+s */
void bitset_shift_left(bitset_t *bitset, size_t s);
/* shifts all bits by 's' positions so that the bitset representing values 1,2,10 would represent values 1-s, 2-s, 10-s, negative values are deleted */
void bitset_shift_right(bitset_t *bitset, size_t s);
/* Set the ith bit. Attempts to resize the bitset if needed (may silently fail) */
static inline void bitset_set(bitset_t *bitset, size_t i) {
size_t shiftedi = i >> 6;
if (shiftedi >= bitset->arraysize) {
if (!bitset_grow(bitset, shiftedi + 1)) {
return;
}
}
bitset->array[shiftedi] |= ((uint64_t)1) << (i % 64);
}
/* Set the ith bit to the specified value. Attempts to resize the bitset if needed (may silently fail) */
static inline void bitset_set_to_value(bitset_t *bitset, size_t i, int flag) {
size_t shiftedi = i >> 6;
uint64_t mask = ((uint64_t)1) << (i % 64);
uint64_t dynmask = ((uint64_t)flag) << (i % 64);
if (shiftedi >= bitset->arraysize) {
if (!bitset_grow(bitset, shiftedi + 1)) {
return;
}
}
uint64_t w = bitset->array[shiftedi];
w &= ~mask;
w |= dynmask;
bitset->array[shiftedi] = w;
}
static inline void bitset_cls_bit(bitset_t *bitset, size_t i) {
bitset_set_to_value(bitset, i, 0);
}
/* Get the value of the ith bit. */
static inline int bitset_get(const bitset_t *bitset, size_t i) {
size_t shiftedi = i >> 6;
if (shiftedi >= bitset->arraysize) {
return FALSE;
}
return (bitset->array[shiftedi] & (((uint64_t)1) << (i % 64))) != 0;
}
/* Count number of bits set. */
size_t bitset_count(const bitset_t *bitset);
/* Find the index of the first bit set. */
size_t bitset_minimum(const bitset_t *bitset);
/* Find the index of the last bit set. */
size_t bitset_maximum(const bitset_t *bitset);
/* compute the union in-place (to b1), returns TRUE if successful, to generate a new bitset first call bitset_copy */
int bitset_inplace_union(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
/* report the size of the union (without materializing it) */
size_t bitset_union_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
/* compute the intersection in-place (to b1), to generate a new bitset first call bitset_copy */
void bitset_inplace_intersection(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
/* report the size of the intersection (without materializing it) */
size_t bitset_intersection_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
/* returns TRUE if the bitsets contain no common elements */
int bitsets_disjoint(const bitset_t *b1, const bitset_t *b2);
/* returns TRUE if the bitsets contain any common elements */
int bitsets_intersect(const bitset_t *b1, const bitset_t *b2);
/* returns TRUE if b1 contains all the set bits of b2 */
int bitset_contains_all(const bitset_t *b1, const bitset_t *b2);
/* compute the difference in-place (to b1), to generate a new bitset first call bitset_copy */
void bitset_inplace_difference(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
/* compute the size of the difference */
size_t bitset_difference_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
/* compute the symmetric difference in-place (to b1), return TRUE if successful, to generate a new bitset first call bitset_copy */
int bitset_inplace_symmetric_difference(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
/* compute the size of the symmetric difference */
size_t bitset_symmetric_difference_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
/* iterate over the set bits
like so :
for(size_t i = 0; nextSetBit(b,&i) ; i++) {
//.....
}
*/
static inline int nextSetBit(const bitset_t *bitset, size_t *i) {
size_t x = *i >> 6;
if (x >= bitset->arraysize) {
return FALSE;
}
uint64_t w = bitset->array[x];
w >>= (*i & 63);
if (w != 0) {
*i += __builtin_ctzll(w);
return TRUE;
}
x++;
while (x < bitset->arraysize) {
w = bitset->array[x];
if (w != 0) {
*i = x * 64 + __builtin_ctzll(w);
return TRUE;
}
x++;
}
return FALSE;
}
/* Iterate over the set bits
like so :
size_t buffer[256];
size_t howmany = 0;
for(size_t startfrom = 0; (howmany = nextSetBits(b,buffer,256, &startfrom)) > 0 ; startfrom++) {
//.....
}
*/
static inline size_t nextSetBits(const bitset_t *bitset, size_t *buffer, size_t capacity, size_t *startfrom) {
if (capacity == 0) {
return 0; // sanity check
}
size_t x = *startfrom >> 6;
if (x >= bitset->arraysize) {
return 0; // nothing more to iterate over
}
uint64_t w = bitset->array[x];
w >>= (*startfrom & 63);
size_t howmany = 0;
size_t base = x << 6;
while (howmany < capacity) {
while (w != 0) {
uint64_t t = w & (~w + 1);
int r = __builtin_ctzll(w);
buffer[howmany++] = r + base;
if (howmany == capacity) {
goto end;
}
w ^= t;
}
x += 1;
if (x == bitset->arraysize) {
break;
}
base += 64;
w = bitset->array[x];
}
end:
if (howmany > 0) {
*startfrom = buffer[howmany - 1];
}
return howmany;
}
typedef int (*bitset_iterator)(size_t value, void *param);
// return TRUE if uninterrupted
static inline int bitset_for_each(const bitset_t *b, bitset_iterator iterator, void *ptr) {
size_t base = 0;
for (size_t i = 0; i < b->arraysize; ++i) {
uint64_t w = b->array[i];
while (w != 0) {
uint64_t t = w & (~w + 1);
int r = __builtin_ctzll(w);
if (!iterator(r + base, ptr)) {
return FALSE;
}
w ^= t;
}
base += 64;
}
return TRUE;
}
//static inline void bitset_print(const bitset_t *b) {
// printf("{");
// for (size_t i = 0; nextSetBit(b, &i); i++) {
// printf("%zu, ", i);
// }
// printf("}");
//}
#ifdef __cplusplus
}
#endif
#endif //VCPE_BITSET_H

View File

@ -11,6 +11,26 @@ extern "C" {
#define _STR(s) #s #define _STR(s) #s
#define STR(s) _STR(s) #define STR(s) _STR(s)
#ifndef MIN
#define MIN(a, b) \
({ \
typeof(a) __min1__ = (a); \
typeof(b) __min2__ = (b); \
(void)(&__min1__ == &__min2__); \
__min1__ < __min2__ ? __min1__ : __min2__; \
})
#endif
#ifndef MAX
#define MAX(a, b) \
({ \
typeof(a) __max1__ = (a); \
typeof(b) __max2__ = (b); \
(void)(&__max1__ == &__max2__); \
__max1__ < __max2__ ? __max1__ : __max2__; \
})
#endif
#ifndef ARRAY_SIZE #ifndef ARRAY_SIZE
//#ifdef __cplusplus //#ifdef __cplusplus
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
@ -48,7 +68,6 @@ typedef unsigned char U8;
typedef unsigned short U16; typedef unsigned short U16;
typedef unsigned int U32; typedef unsigned int U32;
typedef unsigned long long U64; typedef unsigned long long U64;
typedef char S8; typedef char S8;
typedef short S16; typedef short S16;
typedef int S32; typedef int S32;

View File

@ -8,10 +8,9 @@
extern "C" { extern "C" {
#endif #endif
int db_redis_init(void); int db_sqlite3_init();
int db_mysql_init(void); void db_sqlite3_uninit();
void *get_mysql_handle(); int db_sqlite3_sql_exec(const char *pSqlCmd, void *pCallback, void *pData, char **pErr);
void db_mysql_uninit();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -4,10 +4,13 @@
#ifndef VCPE_IPADDR_H #ifndef VCPE_IPADDR_H
#define VCPE_IPADDR_H #define VCPE_IPADDR_H
#include "common.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
U32 ipv4_get_network_addr(U32 ipAddr, U32 netmask);
U32 ipv4_get_boardcast_addr(U32 ipAddr, U32 netmask);
U32 ipv4_network_total_addr(U32 netmask);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -9,66 +9,70 @@ extern "C" {
#endif #endif
#define DEF_ERR_CODE(ERR_CODE) \ #define DEF_ERR_CODE(ERR_CODE) \
ERR_CODE(ERR_SUCCESS, 0, "成功") \ ERR_CODE(ERR_SUCCESS, "成功") \
ERR_CODE(ERR_INPUT_PARAMS, 1, "输入参数错误") \ ERR_CODE(ERR_INPUT_PARAMS, "输入参数错误") \
ERR_CODE(ERR_UN_SUPPORT, 2, "不支持的操作") \ ERR_CODE(ERR_UN_SUPPORT, "不支持的操作") \
ERR_CODE(ERR_CALL_SHELL, 3, "调用Shell命令失败") \ ERR_CODE(ERR_CALL_SHELL, "调用Shell命令失败") \
ERR_CODE(ERR_ITEM_EXISTS, 4, "该内容已经存在") \ ERR_CODE(ERR_ITEM_EXISTS, "该内容已经存在") \
ERR_CODE(ERR_ITEM_UNEXISTS, 5, "该内容不存在") \ ERR_CODE(ERR_ITEM_UNEXISTS, "该内容不存在") \
ERR_CODE(ERR_SYS_INIT, 6, "系统中断") \ ERR_CODE(ERR_SYS_INIT, "系统中断") \
ERR_CODE(ERR_SYS_CALL, 7, "系统调用") \ ERR_CODE(ERR_SYS_CALL, "系统调用") \
ERR_CODE(ERR_OPEN_FILE, 8, "打开文件失败") \ ERR_CODE(ERR_OPEN_FILE, "打开文件失败") \
ERR_CODE(ERR_READ_FILE, 9, "读取文件失败") \ ERR_CODE(ERR_READ_FILE, "读取文件失败") \
ERR_CODE(ERR_FILE_NOT_EXISTS, 10, "文件不存在") \ ERR_CODE(ERR_FILE_NOT_EXISTS, "文件不存在") \
ERR_CODE(ERR_FILE_LOCKED, 11, "文件被锁定") \ ERR_CODE(ERR_FILE_LOCKED, "文件被锁定") \
ERR_CODE(ERR_GET_FILE_SIZE, 12, "获取文件大小失败") \ ERR_CODE(ERR_GET_FILE_SIZE, "获取文件大小失败") \
ERR_CODE(ERR_COPY_FILE, 13, "复制文件失败") \ ERR_CODE(ERR_COPY_FILE, "复制文件失败") \
ERR_CODE(ERR_MALLOC_MEMORY, 14, "分配内存失败") \ ERR_CODE(ERR_MALLOC_MEMORY, "分配内存失败") \
ERR_CODE(ERR_MMAP_MEMORY, 15, "共享内存失败") \ ERR_CODE(ERR_MMAP_MEMORY, "共享内存失败") \
ERR_CODE(ERR_EVP_KEY_SIZE, 16, "秘钥大小不正确") \ ERR_CODE(ERR_EVP_KEY_SIZE, "秘钥大小不正确") \
ERR_CODE(ERR_UNSUP_EVP_TYPE, 17, "不支持的加解密算法") \ ERR_CODE(ERR_UNSUP_EVP_TYPE, "不支持的加解密算法") \
ERR_CODE(ERR_EVP_INIT_KEY, 18, "初始化秘钥失败") \ ERR_CODE(ERR_EVP_INIT_KEY, "初始化秘钥失败") \
ERR_CODE(ERR_EVP_UPDATE, 19, "加解密数据失败") \ ERR_CODE(ERR_EVP_UPDATE, "加解密数据失败") \
ERR_CODE(ERR_EVP_FINALE, 20, "错误的加解密结果") \ ERR_CODE(ERR_EVP_FINALE, "错误的加解密结果") \
ERR_CODE(ERR_EVP_CREATE_CTX, 21, "初始化加解密失败") \ ERR_CODE(ERR_EVP_CREATE_CTX, "初始化加解密失败") \
ERR_CODE(ERR_AES_KEYGEN, 22, "AES秘钥失败") \ ERR_CODE(ERR_AES_KEYGEN, "AES秘钥失败") \
ERR_CODE(ERR_EVP_ENCRYPTION, 23, "加密失败") \ ERR_CODE(ERR_EVP_ENCRYPTION, "加密失败") \
ERR_CODE(ERR_EVP_DECRYPTION, 24, "解密失败") \ ERR_CODE(ERR_EVP_DECRYPTION, "解密失败") \
ERR_CODE(ERR_CONFIG_INIT, 25, "配置文件初始化失败") \ ERR_CODE(ERR_CONFIG_INIT, "配置文件初始化失败") \
ERR_CODE(ERR_UNCOMPATIBILITY_TYPE, 26, "未兼容的类型") \ ERR_CODE(ERR_UNCOMPATIBILITY_TYPE, "未兼容的类型") \
ERR_CODE(ERR_STRING_TO_NUMBER, 27, "字符串转数字失败") \ ERR_CODE(ERR_STRING_TO_NUMBER, "字符串转数字失败") \
ERR_CODE(ERR_UNKNOWN_CFG_ID, 28, "未识别的配置项") \ ERR_CODE(ERR_UNKNOWN_CFG_ID, "未识别的配置项") \
ERR_CODE(ERR_ZLOG_INIT, 29, "日志系统初始化失败") \ ERR_CODE(ERR_ZLOG_INIT, "日志系统初始化失败") \
ERR_CODE(ERR_SYS_GET_CPU_INFO, 30, "获取CPU信息失败") \ ERR_CODE(ERR_SYS_GET_CPU_INFO, "获取CPU信息失败") \
ERR_CODE(ERR_SYS_NOT_FOUND_CPU, 31, "找不到CPU信息") \ ERR_CODE(ERR_SYS_NOT_FOUND_CPU, "找不到CPU信息") \
ERR_CODE(ERR_SYS_DISK_GET_INFO, 32, "获取磁盘空间占用信息失败") \ ERR_CODE(ERR_SYS_DISK_GET_INFO, "获取磁盘空间占用信息失败") \
ERR_CODE(ERR_SYS_IPMI_UNSUP, 33, "服务器IPMI接口不支持") \ ERR_CODE(ERR_SYS_IPMI_UNSUP, "服务器IPMI接口不支持") \
ERR_CODE(ERR_SYS_SENSOR_GET_INFO, 34, "获取传感器信息失败") \ ERR_CODE(ERR_SYS_SENSOR_GET_INFO, "获取传感器信息失败") \
ERR_CODE(ERR_DB_CONNECT, 35, "数据库连接失败") \ ERR_CODE(ERR_DB_UNINIT, "数据库未连接") \
ERR_CODE(ERR_MQ_CREATE_MQ, 36, "创建消息队列失败") \ ERR_CODE(ERR_DB_CONNECT, "数据库连接失败") \
ERR_CODE(ERR_MQ_CREATE_REP, 37, "创建REP消息队列失败") \ ERR_CODE(ERR_DB_SQL_EXEC, "数据库SQL命令执行失败") \
ERR_CODE(ERR_MQ_BIND_SOCKET, 38, "消息队列BIND Socket失败") \ ERR_CODE(ERR_MQ_CREATE_MQ, "创建消息队列失败") \
ERR_CODE(ERR_MQ_CONN_SERVER, 39, "消息队列连接服务器失败") \ ERR_CODE(ERR_MQ_CREATE_REP, "创建REP消息队列失败") \
ERR_CODE(ERR_MQ_SEND_MSG, 40, "消息队列发送消息失败") \ ERR_CODE(ERR_MQ_BIND_SOCKET, "消息队列BIND Socket失败") \
ERR_CODE(ERR_JSON_CREAT_OBJ, 41, "创建JSON对象失败") \ ERR_CODE(ERR_MQ_CONN_SERVER, "消息队列连接服务器失败") \
ERR_CODE(ERR_JSON_PARSE_OBJ, 42, "解析JSON对象失败") \ ERR_CODE(ERR_MQ_SEND_MSG, "消息队列发送消息失败") \
ERR_CODE(ERR_JSON_VALID_SCH, 43, "JSON数据验证失败") \ ERR_CODE(ERR_JSON_CREAT_OBJ, "创建JSON对象失败") \
ERR_CODE(ERR_CREATE_NETIF, 44, "创建网络接口失败") \ ERR_CODE(ERR_JSON_PARSE_OBJ, "解析JSON对象失败") \
ERR_CODE(ERR_CREATE_PPPOE_NETIF, 45, "创建PPPoE网络接口失败") \ ERR_CODE(ERR_JSON_VALID_SCH, "JSON数据验证失败") \
ERR_CODE(ERR_CREATE_PPP_SESSION, 46, "创建PPP连接失败") \ ERR_CODE(ERR_CREATE_NETIF, "创建网络接口失败") \
ERR_CODE(ERR_MISC_GET_IPADDR, 47, "获取网卡IP地址失败") \ ERR_CODE(ERR_CREATE_PPPOE_NETIF, "创建PPPoE网络接口失败") \
ERR_CODE(ERR_MISC_GET_NETMASK, 48, "获取网卡子网掩码失败") \ ERR_CODE(ERR_CREATE_PPP_SESSION, "创建PPP连接失败") \
ERR_CODE(ERR_MISC_GET_GATEWAY, 49, "获取网卡网关地址失败") \ ERR_CODE(ERR_MISC_GET_IPADDR, "获取网卡IP地址失败") \
ERR_CODE(ERR_MISC_GET_MACADDR, 50, "获取网卡MAC地址失败") \ ERR_CODE(ERR_MISC_GET_NETMASK, "获取网卡子网掩码失败") \
ERR_CODE(ERR_MENU_EXIT, 51, "菜单执行完后自动退出") \ ERR_CODE(ERR_MISC_GET_GATEWAY, "获取网卡网关地址失败") \
ERR_CODE(ERR_HTTP_UNSUP_METHOD, 52, "不支持的 HTTP 请求方法") \ ERR_CODE(ERR_MISC_GET_MACADDR, "获取网卡MAC地址失败") \
ERR_CODE(ERR_HTTP_UNSUP_PAGE, 53, "找不到 HTTP 服务") \ ERR_CODE(ERR_MENU_EXIT, "菜单执行完后自动退出") \
ERR_CODE(ERR_PROTO_DECODE, 54, "HTTP 协议解析失败") \ ERR_CODE(ERR_HTTP_UNSUP_METHOD, "不支持的 HTTP 请求方法") \
ERR_CODE(ERR_MSG_CONTENT, 55, "msgContent内容不正确") \ ERR_CODE(ERR_HTTP_UNSUP_PAGE, "找不到 HTTP 服务") \
ERR_CODE(ERR_SOCK_CREATE, 56, "创建套接字失败") \ ERR_CODE(ERR_PROTO_DECODE, "HTTP 协议解析失败") \
ERR_CODE(ERR_SOCK_SETOPT, 57, "设置套接字参数失败") ERR_CODE(ERR_MSG_CONTENT, "msgContent内容不正确") \
ERR_CODE(ERR_DHCP_NO_POOL, "找不到可用地址池") \
ERR_CODE(ERR_DHCP_NO_ADDR, "找不到可用IP地址") \
ERR_CODE(ERR_SOCK_CREATE, "创建套接字失败") \
ERR_CODE(ERR_SOCK_SETOPT, "设置套接字参数失败")
#define GENERATE_ENUM(ENUM, no, x) ENUM, #define GENERATE_ENUM(ENUM, x) ENUM,
typedef enum { typedef enum {
DEF_ERR_CODE(GENERATE_ENUM) DEF_ERR_CODE(GENERATE_ENUM)

View File

@ -7,6 +7,7 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include <zlog.h> #include <zlog.h>
enum { enum {
@ -30,6 +31,7 @@ typedef enum {
ZLOG_MOD(ZLOG_MOD_MISC, ZLOG_LEVEL_DEBUG, "MISC") \ ZLOG_MOD(ZLOG_MOD_MISC, ZLOG_LEVEL_DEBUG, "MISC") \
ZLOG_MOD(ZLOG_MOD_WATCH, ZLOG_LEVEL_DEBUG, "WATCH") \ ZLOG_MOD(ZLOG_MOD_WATCH, ZLOG_LEVEL_DEBUG, "WATCH") \
ZLOG_MOD(ZLOG_MOD_CONFIG, ZLOG_LEVEL_DEBUG, "CONFIG") \ ZLOG_MOD(ZLOG_MOD_CONFIG, ZLOG_LEVEL_DEBUG, "CONFIG") \
ZLOG_MOD(ZLOG_MOD_DB, ZLOG_LEVEL_DEBUG, "DB") \
ZLOG_MOD(ZLOG_MOD_NET, ZLOG_LEVEL_DEBUG, "NET") \ ZLOG_MOD(ZLOG_MOD_NET, ZLOG_LEVEL_DEBUG, "NET") \
ZLOG_MOD(ZLOG_MOD_CRYPTO, ZLOG_LEVEL_DEBUG, "CRYPTO") \ ZLOG_MOD(ZLOG_MOD_CRYPTO, ZLOG_LEVEL_DEBUG, "CRYPTO") \
ZLOG_MOD(ZLOG_MOD_MQ, ZLOG_LEVEL_DEBUG, "MQ") \ ZLOG_MOD(ZLOG_MOD_MQ, ZLOG_LEVEL_DEBUG, "MQ") \
@ -88,8 +90,11 @@ typedef enum {
} while (0) } while (0)
zlog_category_t *zlog_get_mod_cat(ZLOG_MOD_NAME logMod); zlog_category_t *zlog_get_mod_cat(ZLOG_MOD_NAME logMod);
int zlog_verify_level(int level, ZLOG_MOD_NAME logMod); int zlog_verify_level(int level, ZLOG_MOD_NAME logMod);
const char *zlog_vni_tag_get(); const char *zlog_vni_tag_get();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -19,6 +19,9 @@
#include "lib_config.h" #include "lib_config.h"
#include "prj_config.h" #include "prj_config.h"
#include "zlog_module.h" #include "zlog_module.h"
#ifdef SQLITE_ON
#include "database.h"
#endif
#ifdef ZEROMQ_ON #ifdef ZEROMQ_ON
#include "msg_queue.h" #include "msg_queue.h"
#endif #endif
@ -137,6 +140,10 @@ int user_init(const char *pAppCfgFile, const char *pCfgDirectory, const char *pK
if (cfg_get_hardware_watch_enable()) { if (cfg_get_hardware_watch_enable()) {
init_hardware(); init_hardware();
} }
#ifdef SQLITE_ON
db_sqlite3_init();
#endif
#ifdef ZEROMQ_ON #ifdef ZEROMQ_ON
if ((ret = mq_init()) != ERR_SUCCESS) { if ((ret = mq_init()) != ERR_SUCCESS) {
LOG_MOD(error, ZLOG_MOD_INIT, "Message queue init error: %d\n", ret); LOG_MOD(error, ZLOG_MOD_INIT, "Message queue init error: %d\n", ret);
@ -157,6 +164,9 @@ int user_init(const char *pAppCfgFile, const char *pCfgDirectory, const char *pK
void user_uninit() { void user_uninit() {
if (g_isInited) { if (g_isInited) {
task_manager_exit(); task_manager_exit();
#ifdef SQLITE_ON
db_sqlite3_uninit();
#endif
#ifdef HTTPSERVER_ON #ifdef HTTPSERVER_ON
http_svr_uinit(); http_svr_uinit();
#endif #endif

View File

@ -2,3 +2,15 @@
// Created by xajhuang on 2023/3/21. // Created by xajhuang on 2023/3/21.
// //
#include "ipaddr.h" #include "ipaddr.h"
U32 ipv4_get_network_addr(U32 ipAddr, U32 netmask) {
return (ipAddr & netmask);
}
U32 ipv4_get_boardcast_addr(U32 ipAddr, U32 netmask) {
return (ipAddr | netmask);
}
U32 ipv4_network_total_addr(U32 netmask) {
return (~netmask) + 1;
}

View File

@ -5,7 +5,7 @@
#include "common.h" #include "common.h"
#define MAX_DESC_LENGTH (256) #define MAX_DESC_LENGTH (256)
#define GENERATE_STRING(STRING, no, desc) {#STRING, desc}, #define GENERATE_STRING(STRING, desc) {#STRING, desc},
static const char *g_enumStrVal[][MAX_DESC_LENGTH] = { static const char *g_enumStrVal[][MAX_DESC_LENGTH] = {
DEF_ERR_CODE(GENERATE_STRING) {"ERR_UNKNOWN", "未知错误"}, DEF_ERR_CODE(GENERATE_STRING) {"ERR_UNKNOWN", "未知错误"},

View File

@ -141,6 +141,24 @@ void dhcp_option_cfg_init() {
} }
} }
void dhcp_add_number_option(U8 *pBegin, int opt, U8 value, U8 nSize) {
*pBegin = opt;
pBegin++;
*pBegin = nSize;
pBegin++;
memcpy(pBegin, &value, nSize);
pBegin += nSize;
}
void dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize) {
*pBegin = opt;
pBegin++;
*pBegin = nSize;
pBegin++;
memcpy(pBegin, buf, nSize);
pBegin += nSize;
}
int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal) { int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal) {
U8 *p = pOptData; U8 *p = pOptData;

View File

@ -18,18 +18,26 @@
#include "network/vlan.h" #include "network/vlan.h"
#include "dhcp_options.h" #include "dhcp_options.h"
#include "config.h" #include "config.h"
#include "ip_pool.h" #include "misc.h"
#include "user_mgr.h" #include "user_mgr.h"
#define PKG_MMAP_BLOCKSIZ (1 << 22) #define PKG_MMAP_BLOCKSIZ (1 << 22)
#define PKG_MMAP_FRAMESIZ (1 << 11) #define PKG_MMAP_FRAMESIZ (1 << 11)
#define PKG_MMAP_BLOCKNUM (64) #define PKG_MMAP_BLOCKNUM (64)
#define MAX_DHCP_PKG_SIZE (512)
#define MIN_IPADDR (0xC0A80202) #define MAC_TO_STR(mac, str) sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
#define DHCP_NETMASK (0xFFFF0000)
#define GW_IPADDR (0xC0A80201) typedef struct {
#define MASTER_DNS (0x08080808) U8 unicast;
#define SALVE_DNS (0x72727272) U8 cliMac[ETH_ALEN];
U32 xid;
U32 reqIpAddr;
U32 leaseTime;
char clientId[256];
char vendorClassId[256];
char hostName[256];
} DHCP_REQ, *PDHCP_REQ;
typedef struct { typedef struct {
struct iovec *rd; struct iovec *rd;
@ -37,6 +45,14 @@ typedef struct {
struct tpacket_req3 req; struct tpacket_req3 req;
} PACKET_MMAP_RING, *PPACKET_MMAP_RING; } PACKET_MMAP_RING, *PPACKET_MMAP_RING;
typedef struct {
char *pIfName;
U32 ipAddr;
U32 netmask;
U8 macAddr[ETH_ALEN];
S8 hostname[MAX_PATH];
} NIC_INFO, *PNIC_INFO;
struct block_desc { struct block_desc {
uint32_t version; uint32_t version;
uint32_t offset_to_priv; uint32_t offset_to_priv;
@ -63,6 +79,7 @@ typedef struct {
} PKG_MSG, *PPKG_MSG; } PKG_MSG, *PPKG_MSG;
#pragma pack() #pragma pack()
/* /*
TORs (Top of Rack switch) at Facebook run DHCP relayers, these relayers are TORs (Top of Rack switch) at Facebook run DHCP relayers, these relayers are
responsible for relaying broadcast DHCP traffic (DISCOVERY and SOLICIT responsible for relaying broadcast DHCP traffic (DISCOVERY and SOLICIT
@ -70,7 +87,8 @@ messages) originating within their racks to anycast VIPs, one DHCPv4 and one
for DHCPv6. for DHCPv6.
*/ */
static struct sock_filter g_filterCode[] = { static struct sock_filter g_filterCode[] = {
#ifdef UDP_DHCP_FILTER // create by: tcpdump "udp and port 67 and port 68" -dd #ifdef UDP_DHCP_FILTER
// create by: tcpdump "udp and port 67 and port 68" -dd
{0x28, 0, 0, 0x0000000c}, {0x28, 0, 0, 0x0000000c},
{0x15, 0, 9, 0x000086dd}, {0x15, 0, 9, 0x000086dd},
{0x30, 0, 0, 0x00000014}, {0x30, 0, 0, 0x00000014},
@ -182,6 +200,7 @@ static struct sock_filter g_filterCode[] = {
}; };
static PACKET_MMAP_RING g_pkgRing; static PACKET_MMAP_RING g_pkgRing;
static NIC_INFO g_nicInfo;
#define VLAN_VNI_ID(x) ntohs((x)) #define VLAN_VNI_ID(x) ntohs((x))
#define DHCP_XID(x) ntohl((x)) #define DHCP_XID(x) ntohl((x))
@ -191,17 +210,110 @@ static struct sock_fprog bpf = {
.filter = g_filterCode, .filter = g_filterCode,
}; };
typedef struct { static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) {
U8 unicast; PDHCP_PACKAGE pRsp = (PDHCP_PACKAGE)malloc(MAX_DHCP_PKG_SIZE);
U8 cliMac[ETH_ALEN]; U8 *pOpt = pRsp->dhcp.options;
U32 xid;
U32 reqIpAddr; if (pRsp == NULL) {
U32 leaseTime; LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE);
char *clientId; return -ERR_MALLOC_MEMORY;
char *vendorClassId; }
} DHCP_REQ, *PDHCP_REQ;
memset(pRsp, 0, MAX_DHCP_PKG_SIZE);
// 二层头
// 目的IP地址
memset(pRsp->vlan_hdr.eth.h_dest, 0xFF, ETH_ALEN);
// 源 IP 地址
memcpy(pRsp->vlan_hdr.eth.h_source, g_nicInfo.macAddr, ETH_ALEN);
// protol
pRsp->vlan_hdr.eth.h_proto = pReq->vlan_hdr.eth.h_proto;
// QinQ 隧道
pRsp->vlan_hdr.vlan.id = pReq->vlan_hdr.vlan.id;
pRsp->vlan_hdr.vlan.type = pReq->vlan_hdr.vlan.type;
// TODO 可能的二层QinQ隧道
// IP 头
memcpy(&pRsp->vlan_hdr.ip, &pReq->vlan_hdr.ip, sizeof(struct iphdr));
// 更新源IP
pRsp->vlan_hdr.ip.saddr = htonl(g_nicInfo.ipAddr);
// 更新目的IP地址广播255.255.255.255
pRsp->vlan_hdr.ip.daddr = 0xFFFFFFFF;
// UDP 头
// 目的端口
pRsp->vlan_hdr.udp.dest = pReq->vlan_hdr.udp.source;
// 源端口
pRsp->vlan_hdr.udp.source = pReq->vlan_hdr.udp.dest;
//DHCP 协议
// 返回类型
pRsp->dhcp.op = BOOTP_REPLY;
// 地址类型长度
pRsp->dhcp.htype = pReq->dhcp.htype;
// 地址长度
pRsp->dhcp.hlen = pReq->dhcp.hlen;
// xid
pRsp->dhcp.xid = pReq->dhcp.xid;
// 分配的 IP 地址
pRsp->dhcp.yiaddr = htonl(ip);
// 客户端 MAC 地址
memcpy(pRsp->dhcp.chaddr, pReq->dhcp.chaddr, ETH_ALEN);
// DHCP服务端主机名
memcpy(pRsp->dhcp.sname, g_nicInfo.hostname, MIN(64, strlen(g_nicInfo.hostname)));
// Magic Cookie: DHCP
memcpy(&pRsp->dhcp.cookie, "DHCP", 4);
pRsp->dhcp.hops = 0;
pRsp->dhcp.secs = 0;
pRsp->dhcp.flags = 0;
pRsp->dhcp.ciaddr = 0;
pRsp->dhcp.siaddr = 0;
pRsp->dhcp.giaddr = 0;
// DHCP Options
// DHCP 消息类型
dhcp_add_number_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_OFFER, 1);
pOpt += 3;
// 子网掩码
dhcp_add_number_option(pOpt, OPT_NETMASK, pIpInfo->netMask, 4);
pOpt += 6;
// 租约
dhcp_add_number_option(pOpt, OPT_IPADDRLEASE, htonl(pIpInfo->leaseTime), 4);
pOpt += 6;
// DHCP Server
dhcp_add_number_option(pOpt, OPT_SERVERID, g_nicInfo.ipAddr, 4);
pOpt += 6;
// DNS
if (pIpInfo->primeDNS != 0) {
if (pIpInfo->salveDNS == 0) {
dhcp_add_number_option(pOpt, OPT_DNS, pIpInfo->primeDNS, 4);
pOpt += 6;
} else {
dhcp_add_buf_option(pOpt, OPT_DNS, (U8 *)&pIpInfo->primeDNS, 8);
pOpt += 10;
}
}
// 网关
if (pIpInfo->gwAddr != 0) {
dhcp_add_number_option(pOpt, OPT_ROUTER, pIpInfo->gwAddr, 4);
pOpt += 6;
}
// DHCP 主机名
dhcp_add_buf_option(pOpt, OPT_DOMAINNAME, (U8 *)g_nicInfo.hostname, strlen(g_nicInfo.hostname));
pOpt += strlen(g_nicInfo.hostname) + 2;
*pOpt = OPT_END;
LOG_MSG_HEX(debug, pRsp, 256);
return ERR_SUCCESS;
}
static void on_sock_recv(uv_work_t *req) { static void on_sock_recv(uv_work_t *req) {
char macStr[20] = {0};
U32 ip;
PIPPOOL_INFO pIpInfo;
DHCP_REQ reqDhcp; DHCP_REQ reqDhcp;
DHCP_OPT optMsg, opt; DHCP_OPT optMsg, opt;
int ret; int ret;
@ -209,6 +321,8 @@ static void on_sock_recv(uv_work_t *req) {
PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pWork->pPkgBase; PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pWork->pPkgBase;
U32 optSize = pWork->nSize - sizeof(DHCP_PACKAGE); U32 optSize = pWork->nSize - sizeof(DHCP_PACKAGE);
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", macStr[0], macStr[1], macStr[2], macStr[3], macStr[4], macStr[5]);
// Check op flag // Check op flag
if (pkg->dhcp.op != BOOTP_REQUEST) { if (pkg->dhcp.op != BOOTP_REQUEST) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Error message op code %d\n", pkg->dhcp.op); LOG_MOD(error, ZLOG_MOD_DHCPD, "Error message op code %d\n", pkg->dhcp.op);
@ -241,12 +355,33 @@ static void on_sock_recv(uv_work_t *req) {
ret = dhcp_get_option(OPT_CLIENTID, pkg->dhcp.options, optSize, &opt); ret = dhcp_get_option(OPT_CLIENTID, pkg->dhcp.options, optSize, &opt);
if (ret == ERR_SUCCESS) { if (ret == ERR_SUCCESS) {
reqDhcp.clientId = (char *)opt.pValue; strncpy(reqDhcp.clientId, (char *)opt.pValue, MIN((int)opt.len, 256));
} }
ret = dhcp_get_option(OPT_VENDORCLASSID, pkg->dhcp.options, optSize, &opt); ret = dhcp_get_option(OPT_VENDORCLASSID, pkg->dhcp.options, optSize, &opt);
if (ret == ERR_SUCCESS) { if (ret == ERR_SUCCESS) {
reqDhcp.vendorClassId = (char *)opt.pValue; strncpy(reqDhcp.vendorClassId, (char *)opt.pValue, MIN((int)opt.len, 256));
}
ret = dhcp_get_option(OPT_HOSTNAME, pkg->dhcp.options, optSize, &opt);
if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256));
}
MAC_TO_STR(reqDhcp.cliMac, macStr);
ret = pre_alloc_dhcp_res(VLAN_VNI_ID(pkg->vlan_hdr.vlan.id), macStr, &ip, &pIpInfo);
if (ret == ERR_SUCCESS) {
LOG_MOD(trace,
ZLOG_MOD_DHCPD,
"DHCP prepare assign ipaddress: [%s(%s)] --> %s\n",
macStr,
reqDhcp.hostName,
u32_to_str_ip(ntohl(ip)));
ret = dhcp_resp_offer(pkg, pIpInfo, ip);
} else {
//LOG_MOD(error, ZLOG_MOD_DHCPD, );
} }
break; break;
case DHCP_MSG_REQUEST: case DHCP_MSG_REQUEST:
@ -417,7 +552,7 @@ static int create_udp_socket() {
#endif #endif
// 6. bind socket // 6. bind socket
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sll_ifindex = (int)if_nametoindex(config_get_dhcp_nic_name()); addr.sll_ifindex = (int)if_nametoindex(g_nicInfo.pIfName);
addr.sll_family = AF_PACKET; addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(ETH_P_ALL); addr.sll_protocol = htons(ETH_P_ALL);
addr.sll_hatype = 0; addr.sll_hatype = 0;
@ -435,8 +570,16 @@ static int create_udp_socket() {
int dhcpd_init() { int dhcpd_init() {
static uv_udp_t uvRaw; static uv_udp_t uvRaw;
static uv_poll_t uvSocket; static uv_poll_t uvSocket;
int sock;
size_t size = MAX_PATH;
int sock = create_udp_socket(); memset(&g_nicInfo, 0, sizeof(NIC_INFO));
g_nicInfo.pIfName = (char *)config_get_dhcp_nic_name();
uv_os_gethostname(g_nicInfo.hostname, &size);
get_nic_info(g_nicInfo.pIfName, &g_nicInfo.ipAddr, &g_nicInfo.netmask, NULL, g_nicInfo.macAddr);
sock = create_udp_socket();
if (sock <= 0) { if (sock <= 0) {
return sock; return sock;
@ -444,6 +587,7 @@ int dhcpd_init() {
dhcp_user_mgr_init(); dhcp_user_mgr_init();
dhcp_option_cfg_init(); dhcp_option_cfg_init();
dhcp_lease_init();
uv_udp_init(get_task_manager(), &uvRaw); uv_udp_init(get_task_manager(), &uvRaw);
uv_udp_open(&uvRaw, sock); uv_udp_open(&uvRaw, sock);

View File

@ -141,6 +141,8 @@ typedef struct {
U8 len; U8 len;
} DHCP_OPT, *PDHCP_OPT; } DHCP_OPT, *PDHCP_OPT;
void dhcp_add_number_option(U8 *pBegin, int opt, U8 value, U8 nSize);
void dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize);
int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal); int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal);
void dhcp_option_cfg_init(); void dhcp_option_cfg_init();
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -6,6 +6,8 @@
#define VCPE_IP_POOL_H #define VCPE_IP_POOL_H
#include <uthash/uthash.h> #include <uthash/uthash.h>
#include <common.h> #include <common.h>
#include <bitset/bitset.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -18,7 +20,7 @@ extern "C" {
#define MAX_POOL_HASH_KEY (18) #define MAX_POOL_HASH_KEY (18)
typedef struct { typedef struct {
S8 poolKey[MAX_POOL_HASH_KEY]; U32 poolKey;
U32 minAddr; U32 minAddr;
U32 maxAddr; U32 maxAddr;
U32 netMask; U32 netMask;
@ -26,6 +28,7 @@ typedef struct {
U32 primeDNS; U32 primeDNS;
U32 salveDNS; U32 salveDNS;
U32 leaseTime; U32 leaseTime;
bitset_t *assignPool;
UT_hash_handle hh; UT_hash_handle hh;
} IPPOOL_INFO, *PIPPOOL_INFO; } IPPOOL_INFO, *PIPPOOL_INFO;

View File

@ -7,6 +7,7 @@
#include <uthash/uthash.h> #include <uthash/uthash.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <common.h> #include <common.h>
#include "ip_pool.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -24,6 +25,8 @@ typedef struct {
U32 express; U32 express;
} LEASE_CACHE, *PLEASE_CACHE; } LEASE_CACHE, *PLEASE_CACHE;
int dhcp_lease_init();
int pre_alloc_dhcp_res(U32 uid, const char *pMac, U32 *pOutIp, PIPPOOL_INFO *pOutPool);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -22,6 +22,7 @@ typedef struct {
int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool); int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool);
int dhcp_user_mgr_init(); int dhcp_user_mgr_init();
PIPPOOL_INFO user_get_pool(U32 uId);
#ifdef HTTPSERVER_ON #ifdef HTTPSERVER_ON
int user_init_httpd(); int user_init_httpd();
#endif #endif

View File

@ -8,8 +8,7 @@
#include "user_errno.h" #include "user_errno.h"
#include "zlog_module.h" #include "zlog_module.h"
#include "user_mgr.h" #include "user_mgr.h"
#include "ipaddr.h"
#define GEN_IP_POOL_HASH_KEY(p) (sprintf((p)->poolKey, "%08X-%08X", (p)->minAddr, (p)->maxAddr))
static PIPPOOL_INFO g_defPool = NULL; static PIPPOOL_INFO g_defPool = NULL;
@ -34,6 +33,8 @@ void init_default_pool() {
continue; continue;
} }
memset(p, 0, sizeof(IPPOOL_INFO));
if (strlen(pRange->rangAddr) == 0) { if (strlen(pRange->rangAddr) == 0) {
LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Error ip pool configure of address\n"); LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Error ip pool configure of address\n");
free(p); free(p);
@ -61,7 +62,7 @@ void init_default_pool() {
free(p); free(p);
continue; continue;
} else { } else {
p->minAddr = addr.s_addr; p->minAddr = ntohl(addr.s_addr);
} }
if (inet_aton(pSecIp, &addr) == 0) { if (inet_aton(pSecIp, &addr) == 0) {
@ -69,13 +70,39 @@ void init_default_pool() {
free(p); free(p);
continue; continue;
} else { } else {
p->maxAddr = addr.s_addr; p->maxAddr = ntohl(addr.s_addr);
}
} else {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Bad DHCP range format: %s\n", tmpStr);
free(p);
continue;
}
if (strlen(pRange->subnet) > 0) {
if (inet_aton(pRange->subnet, &addr) == 0) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s\n", pRange->subnet);
} else {
p->netMask = ntohl(addr.s_addr);
}
} else {
// 当前网络默认IP地址池
if (inet_aton("255.255.255.0", &addr) == 0) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s\n", pRange->subnet);
} else {
p->netMask = ntohl(addr.s_addr);
}
} }
// 填充POOL Hash Key // 填充POOL Hash Key
GEN_IP_POOL_HASH_KEY(p); p->poolKey = ipv4_get_network_addr(p->minAddr, p->netMask);
} else { p->assignPool = bitset_create_with_capacity(ipv4_network_total_addr(p->netMask));
LOG_MOD(error, ZLOG_MOD_DHCPD, "Bad DHCP range format: %s\n", tmpStr);
if (!p->assignPool) {
LOG_MOD(error,
ZLOG_MOD_DHCPD,
"Create address pool bitset ERROR: 0x%08X total address %u\n",
htonl(p->netMask),
ipv4_network_total_addr(p->netMask));
free(p); free(p);
continue; continue;
} }
@ -84,15 +111,7 @@ void init_default_pool() {
if (inet_aton(pRange->gateway, &addr) == 0) { if (inet_aton(pRange->gateway, &addr) == 0) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s\n", pRange->gateway); LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s\n", pRange->gateway);
} else { } else {
p->gwAddr = addr.s_addr; p->gwAddr = ntohl(addr.s_addr);
}
}
if (strlen(pRange->subnet) > 0) {
if (inet_aton(pRange->subnet, &addr) == 0) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s\n", pRange->subnet);
} else {
p->netMask = addr.s_addr;
} }
} }
@ -109,19 +128,19 @@ void init_default_pool() {
if (inet_aton(tmpStr, &addr) == 0) { if (inet_aton(tmpStr, &addr) == 0) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", tmpStr, pRange->dnsSvr); LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", tmpStr, pRange->dnsSvr);
} else { } else {
p->primeDNS = addr.s_addr; p->primeDNS = ntohl(addr.s_addr);
} }
if (inet_aton(pSecIp, &addr) == 0) { if (inet_aton(pSecIp, &addr) == 0) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", pSecIp, pRange->dnsSvr); LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", pSecIp, pRange->dnsSvr);
} else { } else {
p->salveDNS = addr.s_addr; p->salveDNS = ntohl(addr.s_addr);
} }
} else { } else {
if (inet_aton(pRange->dnsSvr, &addr) == 0) { if (inet_aton(pRange->dnsSvr, &addr) == 0) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", tmpStr, pRange->dnsSvr); LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", tmpStr, pRange->dnsSvr);
} else { } else {
p->primeDNS = addr.s_addr; p->primeDNS = ntohl(addr.s_addr);
} }
} }
} }

View File

@ -2,7 +2,162 @@
// Created by xajhuang on 2023/3/23. // Created by xajhuang on 2023/3/23.
// //
#include <time.h>
#include "lease.h" #include "lease.h"
#include "user_errno.h"
#include "zlog_module.h"
#include "database.h"
#include "user_mgr.h"
static PMAC_FILTER g_allowTbl = NULL; #define LEASE_DB_NAME ("lease")
static PMAC_FILTER g_blackListTbl = NULL; #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;
#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," \
" 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;
}
int dhcp_lease_init() {
int rc = 0;
rc = db_sqlite3_sql_exec(CREATE_LEASE_TABLE(LEASE_DB_NAME), NULL, NULL, NULL);
if (rc != ERR_SUCCESS) {
return rc;
}
return ERR_SUCCESS;
}

View File

@ -176,6 +176,7 @@ int user_init_httpd() {
return ERR_SUCCESS; return ERR_SUCCESS;
} }
// endregion // endregion
#endif #endif
@ -196,7 +197,30 @@ int user_alloc_addr(U32 uId, U8 mac[ETH_ALEN], U32 *pAddr) {
return ERR_SUCCESS; return ERR_SUCCESS;
} }
PIPPOOL_INFO user_get_pool(U32 uId) {
PDHCP_USER_INFO pUser;
HASH_FIND_INT(g_dhcpUsrCfg, &uId, pUser);
if (pUser == NULL) {
U32 id = 0;
HASH_FIND_INT(g_dhcpUsrCfg, &id, pUser);
if (pUser == NULL) {
return NULL;
}
return pUser->pPoolMgr;
}
return NULL;
}
int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool) { int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool) {
U32 k;
U32 begin;
U32 end;
PIPPOOL_INFO pPoolCfg; PIPPOOL_INFO pPoolCfg;
PDHCP_USER_INFO pUserCfg, pTemp; PDHCP_USER_INFO pUserCfg, pTemp;
@ -207,15 +231,24 @@ int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool) {
return ERR_SUCCESS; return ERR_SUCCESS;
} }
HASH_FIND_STR(pUserCfg->pPoolMgr, pPool->poolKey, pPoolCfg); HASH_FIND_INT(pUserCfg->pPoolMgr, &pPool->poolKey, pPoolCfg);
// 改地址池已经存在,提示错误 // 改地址池已经存在,提示错误
if (pPoolCfg != NULL) { if (pPoolCfg != NULL) {
return -ERR_ITEM_EXISTS; free(pPool);
} else {
// 添加新地址池当前用户配置项中
HASH_ADD_INT(pUserCfg->pPoolMgr, poolKey, pPool);
pPoolCfg = pPool;
} }
// 添加到当前用户配置项中 // 计算可用的IP
HASH_ADD_STR(pUserCfg->pPoolMgr, poolKey, pPool); begin = ntohl(pPoolCfg->minAddr) & ntohl(~pPoolCfg->netMask);
end = ntohl(pPoolCfg->maxAddr) & ntohl(~pPoolCfg->netMask);
for (k = MAX(begin, 1U); k <= MIN(end, ntohl(~pPoolCfg->netMask) - 1); k++) {
bitset_set(pPoolCfg->assignPool, k);
}
return ERR_SUCCESS; return ERR_SUCCESS;
} }