From 2229b9d5fc60a4681b5d9bb9bae552ee2efc0bdb Mon Sep 17 00:00:00 2001 From: huangxin Date: Wed, 29 Mar 2023 17:02:21 +0800 Subject: [PATCH] =?UTF-8?q?OCT=201.=20=E5=A2=9E=E5=8A=A0=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=AE=A1=E7=90=86=EF=BC=8C=E7=94=A8=E6=88=B7=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E9=A1=B9=E5=8A=A0=E8=BD=BD=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 11 +- config/vcpe.cfg | 3 + depend/third_libs.cmake | 13 +- srcs/include/service/dhcpd.h | 68 +++++++ srcs/libs/CMakeLists.txt | 14 +- srcs/libs/configure/config.c | 12 +- srcs/libs/configure/config_help.c | 10 +- srcs/libs/include/config.h | 11 +- srcs/libs/include/http_svr.h | 14 +- srcs/libs/include/ipaddr.h | 14 ++ srcs/libs/include/misc.h | 17 +- srcs/libs/include/user_errno.h | 103 +++++----- srcs/libs/include/zlog_module.h | 6 +- srcs/libs/ipaddr/ipaddr.c | 4 + srcs/libs/misc/misc.c | 112 ++++++++++- srcs/opendhcp183/query.cpp | 11 -- srcs/service/CMakeLists.txt | 5 +- srcs/service/dhcpd/dhcp_option.c | 171 +++++++++++++++++ srcs/service/dhcpd/dhcpd_network.c | 129 ++++++++++--- srcs/service/dhcpd/include/dhcp_options.h | 149 +++++++++++++++ srcs/service/dhcpd/include/ip_pool.h | 36 ++++ srcs/service/dhcpd/include/lease.h | 30 +++ srcs/service/dhcpd/include/user_mgr.h | 31 +++ srcs/service/dhcpd/ip_pool.c | 132 +++++++++++++ srcs/service/dhcpd/lease.c | 8 + srcs/service/dhcpd/user_mgr.c | 221 ++++++++++++++++++++++ 26 files changed, 1226 insertions(+), 109 deletions(-) create mode 100644 srcs/libs/include/ipaddr.h create mode 100644 srcs/libs/ipaddr/ipaddr.c create mode 100644 srcs/service/dhcpd/dhcp_option.c create mode 100644 srcs/service/dhcpd/include/dhcp_options.h create mode 100644 srcs/service/dhcpd/include/ip_pool.h create mode 100644 srcs/service/dhcpd/include/lease.h create mode 100644 srcs/service/dhcpd/include/user_mgr.h create mode 100644 srcs/service/dhcpd/ip_pool.c create mode 100644 srcs/service/dhcpd/lease.c create mode 100644 srcs/service/dhcpd/user_mgr.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ddcd66..ea4d8d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,10 +11,11 @@ OPTION(BUILD_TESTING "Enable tests" OFF) # 数据库开关 OPTION(USED_REDIS "Add redis database support for vCPE" OFF) OPTION(USED_MYSQL "Add mysql database support for vCPE" OFF) -OPTION(USED_SQLITE "Add sqlite3 database support for vCPE" OFF) -CMAKE_DEPENDENT_OPTION(USED_HTTP_SVR "Build-in http(s) server support" ON "USED_OPENDHCPD OR USED_OPENDHCPDDNS" OFF) -CMAKE_DEPENDENT_OPTION(USED_LWIP "PPPoE of LWIP support for vCPE" ON "VCPE_PPPOE" ON) +OPTION(USED_SQLITE_CRYPTO "Sqlite3 database support crypto" OFF) +CMAKE_DEPENDENT_OPTION(USED_HTTP_SVR "Build-in http(s) server support" ON "USED_OPENDHCPD OR USED_OPENDHCPDDNS" ON) +CMAKE_DEPENDENT_OPTION(USED_LWIP "PPPoE of LWIP support for vCPE" ON "VCPE_PPPOE" OFF) CMAKE_DEPENDENT_OPTION(USED_ZMQ "ZeroMQ support for vCPE" ON "VCPE_PPPOE" OFF) +CMAKE_DEPENDENT_OPTION(USED_SQLITE "Add sqlite3 database support for vCPE" ON "USED_SQLITE_CRYPTO" ON) LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/depend) IF (BUILD_TESTING) @@ -132,6 +133,10 @@ IF (USED_SQLITE) MESSAGE("Select Option USED_SQLITE") ENDIF () +IF (USED_SQLITE_CRYPTO) + MESSAGE("Select Option USED_SQLITE_CRYPTO") +ENDIF () + IF (USED_LWIP OR VCPE_AGENT) ADD_SUBDIRECTORY(srcs/lwip) ENDIF () diff --git a/config/vcpe.cfg b/config/vcpe.cfg index 7292984..2a7bb71 100644 --- a/config/vcpe.cfg +++ b/config/vcpe.cfg @@ -89,6 +89,8 @@ application: # DHCP Server Config dhcp_server: { + # DHCP服务物理网卡名称 + nic = "ens192"; # 全局租约时间 lease_time = 86400; # 监听网卡 @@ -104,6 +106,7 @@ application: domain_server = "114.114.114.114,8.8.8.8"; gateway = "192.168.101.1"; lease_time = 36000; + vni = 123; }, { dhcp_range = "10.10.0.2-10.10.0.100"; subnet_mask = "255.255.0.0"; diff --git a/depend/third_libs.cmake b/depend/third_libs.cmake index 7dd46b0..2ad7b2a 100644 --- a/depend/third_libs.cmake +++ b/depend/third_libs.cmake @@ -1,9 +1,14 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.14 FATAL_ERROR) INCLUDE(FetchContent) -PKG_SEARCH_MODULE(LIBCURL QUIET libcurl) -PKG_SEARCH_MODULE(LIBSSL QUIET libssl) -PKG_SEARCH_MODULE(LIBCRYPTO QUIET libcrypto) +PKG_SEARCH_MODULE(LIBCURL REQUIRED libcurl) +PKG_SEARCH_MODULE(LIBSSL REQUIRED libssl) +PKG_SEARCH_MODULE(LIBCRYPTO REQUIRED libcrypto) + +IF (USED_SQLITE AND (NOT USED_SQLITE_CRYPTO)) + PKG_SEARCH_MODULE(LIBSQLITE3 REQUIRED sqlite3) +ENDIF () + IF (USED_ZMQ) PKG_SEARCH_MODULE(LIBZMQ QUIET libzmq) IF (NOT LIBZMQ_FOUND) @@ -14,7 +19,7 @@ IF ((NOT LIBCRYPTO_FOUND) OR (NOT LIBSSL_FOUND) OR (NOT LIBCURL_FOUND)) LINUX_INSTALL_SYSTEM_PACKAGE() ENDIF () -LIST(APPEND COMMON_LIBS "${LIBCURL_LDFLAGS} ${LIBSSL_LDFLAGS} ${LIBCRYPTO_LDFLAGS}") +LIST(APPEND COMMON_LIBS "${LIBCURL_LDFLAGS} ${LIBSSL_LDFLAGS} ${LIBCRYPTO_LDFLAGS} ${LIBSQLITE3_LDFLAGS}") LIST(APPEND COMMON_LIBS "${LIBZMQ_LDFLAGS}") LIST(APPEND COMMON_LIBS "-lm -lpthread") diff --git a/srcs/include/service/dhcpd.h b/srcs/include/service/dhcpd.h index 7ccb24d..3d5094b 100644 --- a/srcs/include/service/dhcpd.h +++ b/srcs/include/service/dhcpd.h @@ -9,6 +9,70 @@ extern "C" { #endif +/** + * Message op code / message type + * Request Message + */ +#define BOOTP_REQUEST 1 +/** + * Message op code / message type + * Response Message + */ +#define BOOTP_REPLY 2 + +#define DHCP_MSG_NONE 0 +/** + * DHCP客户端在请求IP地址时并不知道DHCP服务器的位置, + * 因此DHCP客户端会在本地网络内以广播方式发送Discover请求报文,以发现网络中的DHCP服务器。 + * 所有收到Discover报文的DHCP服务器都会发送应答报文, + * DHCP客户端据此可以知道网络中存在的DHCP服务器的位置 + */ +#define DHCP_MSG_DISCOVER 1 +/** + * DHCP服务器收到Discover报文后,就会在所配置的地址池中查找一个合适的IP地址, + * 加上相应的租约期限和其他配置信息(如网关、DNS服务器等),构造一个Offer报文, + * 发送给DHCP客户端,告知用户本服务器可以为其提供IP地址。但这个报文只是告诉DHCP客户端可以提供IP地址, + * 最终还需要客户端通过ARP来检测该IP地址是否重复 + */ +#define DHCP_MSG_OFFER 2 +/** + * DHCP客户端可能会收到很多Offer请求报文,所以必须在这些应答中选择一个。 + * 通常是选择第一个Offer应答报文的服务器作为自己的目标服务器, + * 并向该服务器发送一个广播的Request请求报文,通告选择的服务器,希望获得所分配的IP地址。 + * 另外,DHCP客户端在成功获取IP地址后,在地址使用租期达到50%时, + * 会向DHCP服务器发送单播Request请求报文请求续延租约, + * 如果没有收到ACK报文,在租期达到87.5%时,会再次发送广播的Request请求报文以请求续延租约 + */ +#define DHCP_MSG_REQUEST 3 +/** + * DHCP客户端收到DHCP服务器ACK应答报文后, + * 通过地址冲突检测发现服务器分配的地址冲突或者由于其他原因导致不能使用, + * 则会向DHCP服务器发送Decline请求报文,通知服务器所分配的IP地址不可用,以期获得新的IP地址 + */ +#define DHCP_MSG_DECLINE 4 +/** + * DHCP服务器收到Request请求报文后,根据Request报文中携带的用户MAC来查找有没有相应的租约记录, + * 如果有则发送ACK应答报文,通知用户可以使用分配的IP地址 + */ +#define DHCP_MSG_ACK 5 +/** + * 如果DHCP服务器收到Request请求报文后,没有发现有相应的租约记录或者由于某些原因无法正常分配IP地址, + * 则向DHCP客户端发送NAK应答报文,通知用户无法分配合适的IP地址 + */ +#define DHCP_MSG_NAK 6 +/** + * 当DHCP客户端不再需要使用分配IP地址时(一般出现在客户端关机、下线等状况) + * 就会主动向DHCP服务器发送RELEASE请求报文,告知服务器用户不再需要分配IP地址, + * 请求DHCP服务器释放对应的IP地址 + */ +#define DHCP_MSG_RELEASE 7 +/** + * DHCP客户端如果需要从DHCP服务器端获取更为详细的配置信息, + * 则向DHCP服务器发送Inform请求报文;DHCP服务器在收到该报文后, + * 将根据租约进行查找到相应的配置信息后,向DHCP客户端发送ACK应答报文。目前基本上不用了 + */ +#define DHCP_MSG_INFORM 8 + #pragma pack(push) #pragma pack(1) @@ -40,6 +104,8 @@ extern "C" { +---------------------------------------------------------------+ | | | file (128) | + +---------------+---------------+---------------+---------------+ + | cookie (4) | +---------------------------------------------------------------+ | | | options (variable) | @@ -77,6 +143,8 @@ typedef struct { U8 sname[64]; ///< DHCP服务器为DHCP客户端指定的启动配置文件名称及路径信息。仅在DHCP Offer报文中显示,其他报文中显示为空 U8 file[128]; + ///< 缓存数据 + U32 cookie; ///< 可选项字段,长度可变,格式为"代码+长度+数据" U8 options[0]; } DHCP_PROTO, *PDHCP_PROTO; diff --git a/srcs/libs/CMakeLists.txt b/srcs/libs/CMakeLists.txt index 6b14d7b..b805af6 100644 --- a/srcs/libs/CMakeLists.txt +++ b/srcs/libs/CMakeLists.txt @@ -5,6 +5,10 @@ PROJECT(${LIB_PROJECT_TARGET} VERSION 1.1.0) STRING(REPLACE ";" ", " BUILD_CONFIG_INFO "${COMMON_DEFINE}") CONFIGURE_FILE(lib_config.h.in lib_config.h) +IF (USED_SQLITE_CRYPTO) + INCLUDE_DIRECTORIES(include/sqlite3) +ENDIF () + INCLUDE_DIRECTORIES(include ../opendhcp183 mongoose ./ ./include ../lwip/src/include ../lwip/src/arch_linux/include ../include) FILE(GLOB C_HEADS ./include/network/*.h include/*.h include/uthash/*.h include/s2j/*.h vector/*.h ${CMAKE_BINARY_DIR}/*.h ${PROJECT_BINARY_DIR}/*.h) @@ -17,6 +21,7 @@ AUX_SOURCE_DIRECTORY(banner C_SRC) AUX_SOURCE_DIRECTORY(configure C_SRC) AUX_SOURCE_DIRECTORY(network C_SRC) AUX_SOURCE_DIRECTORY(task C_SRC) +AUX_SOURCE_DIRECTORY(ipaddr C_SRC) IF (USED_ZMQ) AUX_SOURCE_DIRECTORY(mq C_SRC) ENDIF () @@ -40,8 +45,11 @@ IF (USED_REDIS) ENDIF () IF (USED_SQLITE) - ADD_DEFINITIONS(-DUSED_SQLITE) - AUX_SOURCE_DIRECTORY(database/sqlite3 C_SRC) + ADD_DEFINITIONS(-DSQLITE_ON) + IF (SQLITE_CRYPTO_ON) + ADD_DEFINITIONS(-DSQLITE_CRYPTO_ON) + AUX_SOURCE_DIRECTORY(database/sqlite3 C_SRC) + ENDIF () ENDIF () IF (USED_MYSQL) @@ -53,7 +61,7 @@ SET(CMAKE_C_STANDARD 99) SET_SOURCE_FILES_PROPERTIES(misc/zvector.c PROPERTIES COMPILE_FLAGS "-Wall -Wextra -flto") SET_SOURCE_FILES_PROPERTIES(mongoose/mongoose.c PROPERTIES COMPILE_FLAGS "-Wall -Wextra -w") -IF (USED_SQLITE) +IF (USED_SQLITE_CRYPTO) SET_SOURCE_FILES_PROPERTIES(database/sqlite3/sqlite3.c PROPERTIES COMPILE_FLAGS "-DSQLITE_HAS_CODEC \ -DSQLCIPHER_CRYPTO_OPENSSL -DSQLITE_OS_UNIX=1 \ diff --git a/srcs/libs/configure/config.c b/srcs/libs/configure/config.c index 725c7b2..bf73858 100644 --- a/srcs/libs/configure/config.c +++ b/srcs/libs/configure/config.c @@ -90,9 +90,11 @@ static CFG_ITEM g_cfgItem[] = { DEF_CFG_ITEM(CFG_DB_MYSQL_DB_NAME, "database.mysql_database", VAL_STR, ".main", "MySQL database used"), #endif /* SQLite3配置 */ -#ifdef USED_SQLITE +#ifdef SQLITE_ON DEF_CFG_ITEM(CFG_DB_SQLITE_DB_NAME, "database.sqlite_dbname", VAL_STR, "", "SQLite3 database file name"), - DEF_CFG_ITEM(CFG_DB_SQLITE_PASSWD, "database.sqlite_passwd", VAL_STR, ".main", "SQLite3 database password"), +#ifdef SQLITE_CRYPTO_ON + DEF_CFG_ITEM(CFG_DB_SQLITE_PASSWD, "database.sqlite_passwd", VAL_STR, "", "SQLite3 database password"), +#endif #endif #ifdef ZEROMQ_ON /* 消息队列相配置 */ @@ -119,6 +121,7 @@ static CFG_ITEM g_cfgItem[] = { DEF_CFG_ITEM(CFG_DHCP_REPLICATION_SVR, "dhcp_server.replication", VAL_ARRAY_STR, "", "DHCP replication server configure"), DEF_CFG_ITEM(CFG_DHCP_RANGE_SET, "dhcp_server.range_set", VAL_ARRAY_OBJ, "", "DHCP IP pool"), DEF_CFG_ITEM(CFG_DHCP_MAC_FILTER, "dhcp_server.mac_filter", VAL_ARRAY_STR, "", "DHCP client MAC address black list"), + DEF_CFG_ITEM(CFG_DHCP_NIC_NAME, "dhcp_server.nic", VAL_STR, "ens192", "DHCP server network interface name"), #endif }; // clang-format on @@ -282,6 +285,10 @@ static int load_array_obj(const char *pKeyName, PCONFIG_ITEM pValue) { v.lease = 0xFFFFFFFF; } + if (!config_setting_lookup_int(pObj, "vni", (int *)&v.vni)) { + v.vni = 0; + } + if (!vect_bsearch(pValue->value.array, &v, cmp_dhcp_obj, &idx)) { memcpy(&k, &v, sizeof(OBJ_DHCP_RNG)); vect_push(pValue->value.array, &k); @@ -584,6 +591,7 @@ const char *config_item_dump_fmt(const char *titleMessage) { keyGateway = sdscatprintf(keyGateway, "\"%s\"", p->gateway); s = sdscatprintf(s, "|%4d | %-25s | %-45s | %-64s |\n", pItem->cfgId, tmp2, title, ""); + s = sdscatprintf(s, "| | %-25s | %-45s | %-64u |\n", "", " .vni", p->vni); s = sdscatprintf(s, "| | %-25s | %-45s | %-64s |\n", "", " .dhcp_range", keyRang); s = sdscatprintf(s, "| | %-25s | %-45s | %-64s |\n", "", " .subnet_mask", keySubnet); s = sdscatprintf(s, "| | %-25s | %-45s | %-64s |\n", "", " .domain_server", keyDns); diff --git a/srcs/libs/configure/config_help.c b/srcs/libs/configure/config_help.c index 1f7c22a..99547ff 100644 --- a/srcs/libs/configure/config_help.c +++ b/srcs/libs/configure/config_help.c @@ -29,7 +29,7 @@ const char *config_get_proto_crypto_key() { return cfg_get_string_value(CFG_PROTO_CRYPTO_KEY); } -#ifdef OPENDHCPD_ON +#if OPENDHCPD_ON unsigned int config_get_dhcp_server_lease_time() { return cfg_get_integral_value(CFG_DHCP_LEASE_TIME); } @@ -49,6 +49,10 @@ c_vector config_get_dhcp_replication_svr() { c_vector config_get_dhcp_mac_filter() { return cfg_get_vector(CFG_DHCP_MAC_FILTER); } + +const char *config_get_dhcp_nic_name() { + return cfg_get_string_value(CFG_DHCP_NIC_NAME); +} #endif const char *config_get_agent_iptv_report_url() { @@ -121,15 +125,17 @@ int cfg_get_watch_sensor() { return cfg_get_bool_value(CFG_WATCH_SENSOR); } -#ifdef USED_SQLITE +#ifdef SQLITE_ON const char *cfg_get_sqlite_db_name() { return cfg_get_string_value(CFG_DB_SQLITE_DB_NAME); } +#ifdef SQLITE_CRYPTO_ON const char *cfg_get_sqlite_passwd() { return cfg_get_string_value(CFG_DB_SQLITE_PASSWD); } #endif +#endif #ifdef USED_REDIS const char *cfg_get_redis_server() { diff --git a/srcs/libs/include/config.h b/srcs/libs/include/config.h index 687e981..b78ba35 100644 --- a/srcs/libs/include/config.h +++ b/srcs/libs/include/config.h @@ -18,6 +18,7 @@ typedef struct { char dnsSvr[256]; char gateway[20]; unsigned int lease; + unsigned int vni; } OBJ_DHCP_RNG, *POBJ_DHCP_RNG; typedef enum { @@ -53,10 +54,12 @@ typedef enum { CFG_DB_MYSQL_PASSWD, CFG_DB_MYSQL_DB_NAME, #endif -#ifdef USED_SQLITE +#ifdef SQLITE_ON CFG_DB_SQLITE_DB_NAME, +#ifdef SQLITE_CRYPTO_ON CFG_DB_SQLITE_PASSWD, #endif +#endif #ifdef ZEROMQ_ON CFG_MQ_SVR_PORT, CFG_MQ_DATA_PATH, @@ -77,6 +80,7 @@ typedef enum { CFG_DHCP_REPLICATION_SVR, CFG_DHCP_RANGE_SET, CFG_DHCP_MAC_FILTER, + CFG_DHCP_NIC_NAME, #endif CONFIG_ITEM_ID_MAX } CONFIG_ITEM_ID; @@ -102,10 +106,12 @@ const char *cfg_get_mysql_user(); const char *cfg_get_mysql_passwd(); const char *cfg_get_mysql_database(); #endif -#ifdef USED_SQLITE +#ifdef SQLITE_ON const char *cfg_get_sqlite_db_name(); +#ifdef SQLITE_CRYPTO_ON const char *cfg_get_sqlite_passwd(); #endif +#endif #ifdef ZEROMQ_ON int cfg_get_zero_mq_port(); const char *cfg_get_zero_mq_data_path(); @@ -146,6 +152,7 @@ c_vector config_get_dhcp_server_range_set(); c_vector config_get_dhcp_listen_on(); c_vector config_get_dhcp_replication_svr(); c_vector config_get_dhcp_mac_filter(); +const char *config_get_dhcp_nic_name(); #endif #ifdef __cplusplus diff --git a/srcs/libs/include/http_svr.h b/srcs/libs/include/http_svr.h index 80bb3cb..6682e00 100644 --- a/srcs/libs/include/http_svr.h +++ b/srcs/libs/include/http_svr.h @@ -10,7 +10,9 @@ extern "C" { #ifdef HTTPSERVER_ON #include "mongoose.h" -#define MAX_URI (1024) +#define HTTP_HEAD_CONTENT_TYPE_JSON "Content-Type: application/json\r\n" +#define HTTP_HEAD_CONTENT_TYPE_HTML "Content-Type: text/html\r\n" +#define MAX_URI (1024) typedef enum { PRI_LOWEASE = 0, @@ -40,12 +42,20 @@ typedef enum { typedef struct { int httpCode; int errCode; - const char* pRspHeads; + const char *pRspHeads; void *pRspData; } HTTP_RSP_CTX, *PHTTP_RSP_CTX; typedef void (*HTTP_REQUEST_CB)(struct mg_http_message *, void *, PHTTP_RSP_CTX); +typedef struct { + char routeName[MAX_URI]; + HTTP_METHOD method; + HTTP_ROUTE_PRIORITY priority; + HTTP_REQUEST_CB cb; + void *pUserData; +} HTTP_ROUTE_INFO, *PHTTP_ROUTE_INFO; + int http_svr_init(); int http_svr_uinit(); int http_add_route(const char *path, diff --git a/srcs/libs/include/ipaddr.h b/srcs/libs/include/ipaddr.h new file mode 100644 index 0000000..6ec499c --- /dev/null +++ b/srcs/libs/include/ipaddr.h @@ -0,0 +1,14 @@ +// +// Created by xajhuang on 2023/3/21. +// + +#ifndef VCPE_IPADDR_H +#define VCPE_IPADDR_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif +#endif //VCPE_IPADDR_H diff --git a/srcs/libs/include/misc.h b/srcs/libs/include/misc.h index 67f87f1..902237b 100644 --- a/srcs/libs/include/misc.h +++ b/srcs/libs/include/misc.h @@ -8,6 +8,19 @@ extern "C" { #endif +typedef struct { + char ethName[16]; + unsigned char mac[6]; + unsigned int ipv4Addr; + unsigned int ipv4Mask; + unsigned int ipv4Boardcast; +} NIC_CTX, *PNIC_CTX; + +typedef struct { + PNIC_CTX pNicCtx; + unsigned int nicCnt; +} SYS_NIC_INFO, *PSYS_NIC_INFO; + const char *get_cur_process_dir(); const char *get_cur_process_name(); int file_exists(const char *pPath); @@ -21,12 +34,14 @@ int str_to_mac(const char *str, unsigned char mac[6]); int get_nic_info(const char *pName, unsigned int *pIp, unsigned int *pNetmask, - unsigned int *pGateway, + unsigned int *pBoardcast, unsigned char *pMac); int str_to_ipaddr(const char *pIp, unsigned int *ipAddr); unsigned long long get_current_time_ms(); 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); #ifdef __cplusplus } #endif diff --git a/srcs/libs/include/user_errno.h b/srcs/libs/include/user_errno.h index 7ef0fd8..c552535 100644 --- a/srcs/libs/include/user_errno.h +++ b/srcs/libs/include/user_errno.h @@ -16,56 +16,57 @@ extern "C" { ERR_CODE(ERR_ITEM_EXISTS, 4, "该内容已经存在") \ ERR_CODE(ERR_ITEM_UNEXISTS, 5, "该内容不存在") \ ERR_CODE(ERR_SYS_INIT, 6, "系统中断") \ - ERR_CODE(ERR_OPEN_FILE, 7, "打开文件失败") \ - ERR_CODE(ERR_READ_FILE, 8, "读取文件失败") \ - ERR_CODE(ERR_FILE_NOT_EXISTS, 9, "文件不存在") \ - ERR_CODE(ERR_FILE_LOCKED, 10, "文件被锁定") \ - ERR_CODE(ERR_GET_FILE_SIZE, 11, "获取文件大小失败") \ - ERR_CODE(ERR_COPY_FILE, 12, "复制文件失败") \ - ERR_CODE(ERR_MALLOC_MEMORY, 13, "分配内存失败") \ - ERR_CODE(ERR_MMAP_MEMORY, 14, "共享内存失败") \ - ERR_CODE(ERR_EVP_KEY_SIZE, 15, "秘钥大小不正确") \ - ERR_CODE(ERR_UNSUP_EVP_TYPE, 16, "不支持的加解密算法") \ - ERR_CODE(ERR_EVP_INIT_KEY, 17, "初始化秘钥失败") \ - ERR_CODE(ERR_EVP_UPDATE, 18, "加解密数据失败") \ - ERR_CODE(ERR_EVP_FINALE, 19, "错误的加解密结果") \ - ERR_CODE(ERR_EVP_CREATE_CTX, 20, "初始化加解密失败") \ - ERR_CODE(ERR_AES_KEYGEN, 21, "AES秘钥失败") \ - ERR_CODE(ERR_EVP_ENCRYPTION, 22, "加密失败") \ - ERR_CODE(ERR_EVP_DECRYPTION, 23, "解密失败") \ - ERR_CODE(ERR_CONFIG_INIT, 24, "配置文件初始化失败") \ - ERR_CODE(ERR_UNCOMPATIBILITY_TYPE, 25, "未兼容的类型") \ - ERR_CODE(ERR_STRING_TO_NUMBER, 26, "字符串转数字失败") \ - ERR_CODE(ERR_UNKNOWN_CFG_ID, 27, "未识别的配置项") \ - ERR_CODE(ERR_ZLOG_INIT, 28, "日志系统初始化失败") \ - ERR_CODE(ERR_SYS_GET_CPU_INFO, 29, "获取CPU信息失败") \ - ERR_CODE(ERR_SYS_NOT_FOUND_CPU, 30, "找不到CPU信息") \ - ERR_CODE(ERR_SYS_DISK_GET_INFO, 31, "获取磁盘空间占用信息失败") \ - ERR_CODE(ERR_SYS_IPMI_UNSUP, 32, "服务器IPMI接口不支持") \ - ERR_CODE(ERR_SYS_SENSOR_GET_INFO, 33, "获取传感器信息失败") \ - ERR_CODE(ERR_DB_CONNECT, 34, "数据库连接失败") \ - ERR_CODE(ERR_MQ_CREATE_MQ, 35, "创建消息队列失败") \ - ERR_CODE(ERR_MQ_CREATE_REP, 36, "创建REP消息队列失败") \ - ERR_CODE(ERR_MQ_BIND_SOCKET, 37, "消息队列BIND Socket失败") \ - ERR_CODE(ERR_MQ_CONN_SERVER, 38, "消息队列连接服务器失败") \ - ERR_CODE(ERR_MQ_SEND_MSG, 39, "消息队列发送消息失败") \ - ERR_CODE(ERR_JSON_CREAT_OBJ, 40, "创建JSON对象失败") \ - ERR_CODE(ERR_JSON_PARSE_OBJ, 41, "解析JSON对象失败") \ - ERR_CODE(ERR_JSON_VALID_SCH, 42, "JSON数据验证失败") \ - ERR_CODE(ERR_CREATE_NETIF, 43, "创建网络接口失败") \ - ERR_CODE(ERR_CREATE_PPPOE_NETIF, 44, "创建PPPoE网络接口失败") \ - ERR_CODE(ERR_CREATE_PPP_SESSION, 45, "创建PPP连接失败") \ - ERR_CODE(ERR_MISC_GET_IPADDR, 46, "获取网卡IP地址失败") \ - ERR_CODE(ERR_MISC_GET_NETMASK, 47, "获取网卡子网掩码失败") \ - ERR_CODE(ERR_MISC_GET_GATEWAY, 48, "获取网卡网关地址失败") \ - ERR_CODE(ERR_MISC_GET_MACADDR, 49, "获取网卡MAC地址失败") \ - ERR_CODE(ERR_MENU_EXIT, 50, "菜单执行完后自动退出") \ - ERR_CODE(ERR_HTTP_UNSUP_METHOD, 51, "不支持的 HTTP 请求方法") \ - ERR_CODE(ERR_HTTP_UNSUP_PAGE, 52, "找不到 HTTP 服务") \ - ERR_CODE(ERR_PROTO_DECODE, 53, "HTTP 协议解析失败") \ - ERR_CODE(ERR_MSG_CONTENT, 54, "msgContent内容不正确") \ - ERR_CODE(ERR_SOCK_CREATE, 55, "创建套接字失败") \ - ERR_CODE(ERR_SOCK_SETOPT, 56, "设置套接字参数失败") + ERR_CODE(ERR_SYS_CALL, 7, "系统调用") \ + ERR_CODE(ERR_OPEN_FILE, 8, "打开文件失败") \ + ERR_CODE(ERR_READ_FILE, 9, "读取文件失败") \ + ERR_CODE(ERR_FILE_NOT_EXISTS, 10, "文件不存在") \ + ERR_CODE(ERR_FILE_LOCKED, 11, "文件被锁定") \ + ERR_CODE(ERR_GET_FILE_SIZE, 12, "获取文件大小失败") \ + ERR_CODE(ERR_COPY_FILE, 13, "复制文件失败") \ + ERR_CODE(ERR_MALLOC_MEMORY, 14, "分配内存失败") \ + ERR_CODE(ERR_MMAP_MEMORY, 15, "共享内存失败") \ + ERR_CODE(ERR_EVP_KEY_SIZE, 16, "秘钥大小不正确") \ + ERR_CODE(ERR_UNSUP_EVP_TYPE, 17, "不支持的加解密算法") \ + ERR_CODE(ERR_EVP_INIT_KEY, 18, "初始化秘钥失败") \ + ERR_CODE(ERR_EVP_UPDATE, 19, "加解密数据失败") \ + ERR_CODE(ERR_EVP_FINALE, 20, "错误的加解密结果") \ + ERR_CODE(ERR_EVP_CREATE_CTX, 21, "初始化加解密失败") \ + ERR_CODE(ERR_AES_KEYGEN, 22, "AES秘钥失败") \ + ERR_CODE(ERR_EVP_ENCRYPTION, 23, "加密失败") \ + ERR_CODE(ERR_EVP_DECRYPTION, 24, "解密失败") \ + ERR_CODE(ERR_CONFIG_INIT, 25, "配置文件初始化失败") \ + ERR_CODE(ERR_UNCOMPATIBILITY_TYPE, 26, "未兼容的类型") \ + ERR_CODE(ERR_STRING_TO_NUMBER, 27, "字符串转数字失败") \ + ERR_CODE(ERR_UNKNOWN_CFG_ID, 28, "未识别的配置项") \ + ERR_CODE(ERR_ZLOG_INIT, 29, "日志系统初始化失败") \ + ERR_CODE(ERR_SYS_GET_CPU_INFO, 30, "获取CPU信息失败") \ + ERR_CODE(ERR_SYS_NOT_FOUND_CPU, 31, "找不到CPU信息") \ + ERR_CODE(ERR_SYS_DISK_GET_INFO, 32, "获取磁盘空间占用信息失败") \ + ERR_CODE(ERR_SYS_IPMI_UNSUP, 33, "服务器IPMI接口不支持") \ + ERR_CODE(ERR_SYS_SENSOR_GET_INFO, 34, "获取传感器信息失败") \ + ERR_CODE(ERR_DB_CONNECT, 35, "数据库连接失败") \ + ERR_CODE(ERR_MQ_CREATE_MQ, 36, "创建消息队列失败") \ + ERR_CODE(ERR_MQ_CREATE_REP, 37, "创建REP消息队列失败") \ + ERR_CODE(ERR_MQ_BIND_SOCKET, 38, "消息队列BIND Socket失败") \ + ERR_CODE(ERR_MQ_CONN_SERVER, 39, "消息队列连接服务器失败") \ + ERR_CODE(ERR_MQ_SEND_MSG, 40, "消息队列发送消息失败") \ + ERR_CODE(ERR_JSON_CREAT_OBJ, 41, "创建JSON对象失败") \ + ERR_CODE(ERR_JSON_PARSE_OBJ, 42, "解析JSON对象失败") \ + ERR_CODE(ERR_JSON_VALID_SCH, 43, "JSON数据验证失败") \ + ERR_CODE(ERR_CREATE_NETIF, 44, "创建网络接口失败") \ + ERR_CODE(ERR_CREATE_PPPOE_NETIF, 45, "创建PPPoE网络接口失败") \ + ERR_CODE(ERR_CREATE_PPP_SESSION, 46, "创建PPP连接失败") \ + ERR_CODE(ERR_MISC_GET_IPADDR, 47, "获取网卡IP地址失败") \ + ERR_CODE(ERR_MISC_GET_NETMASK, 48, "获取网卡子网掩码失败") \ + ERR_CODE(ERR_MISC_GET_GATEWAY, 49, "获取网卡网关地址失败") \ + ERR_CODE(ERR_MISC_GET_MACADDR, 50, "获取网卡MAC地址失败") \ + ERR_CODE(ERR_MENU_EXIT, 51, "菜单执行完后自动退出") \ + ERR_CODE(ERR_HTTP_UNSUP_METHOD, 52, "不支持的 HTTP 请求方法") \ + ERR_CODE(ERR_HTTP_UNSUP_PAGE, 53, "找不到 HTTP 服务") \ + ERR_CODE(ERR_PROTO_DECODE, 54, "HTTP 协议解析失败") \ + ERR_CODE(ERR_MSG_CONTENT, 55, "msgContent内容不正确") \ + ERR_CODE(ERR_SOCK_CREATE, 56, "创建套接字失败") \ + ERR_CODE(ERR_SOCK_SETOPT, 57, "设置套接字参数失败") #define GENERATE_ENUM(ENUM, no, x) ENUM, @@ -149,7 +150,7 @@ typedef enum { // //} USER_ERRNO; -const char *getErrorEnumString(int errCode); +const char *getErrorEnumNameString(int errCode); const char *getErrorEnumDesc(int errCode); #ifdef __cplusplus } diff --git a/srcs/libs/include/zlog_module.h b/srcs/libs/include/zlog_module.h index 423eb4f..de9e6a7 100644 --- a/srcs/libs/include/zlog_module.h +++ b/srcs/libs/include/zlog_module.h @@ -40,7 +40,8 @@ typedef enum { ZLOG_MOD(ZLOG_MOD_PPPOE, ZLOG_LEVEL_DEBUG, "PPPOE") \ ZLOG_MOD(ZLOG_MOD_VXLAN, ZLOG_LEVEL_DEBUG, "VXLAN") \ ZLOG_MOD(ZLOG_MOD_LWIP, ZLOG_LEVEL_DEBUG, "LWIP") \ - ZLOG_MOD(ZLOG_MOD_OPENDHCPD, ZLOG_LEVEL_DEBUG, "DHCPD") + ZLOG_MOD(ZLOG_MOD_DHCPD, ZLOG_LEVEL_DEBUG, "DHCPD") \ + ZLOG_MOD(ZLOG_MOD_OPENDHCPD, ZLOG_LEVEL_DEBUG, "ODHCPD") #define GENERATE_ZLOG_MOD_ENUM(ENUM, lv, x) ENUM, @@ -48,6 +49,9 @@ typedef enum { DEF_ZLOG_MOD(GENERATE_ZLOG_MOD_ENUM) } ZLOG_MOD_NAME; +#define hzlog_trace(cat, buf, buf_len) \ + hzlog(cat, __FILE__, sizeof(__FILE__) - 1, __func__, sizeof(__func__) - 1, __LINE__, ZLOG_LEVEL_DEBUG, buf, buf_len) + #define zlog_trace(cat, format, ...) \ zlog(cat, \ __FILE__, \ diff --git a/srcs/libs/ipaddr/ipaddr.c b/srcs/libs/ipaddr/ipaddr.c new file mode 100644 index 0000000..885bb03 --- /dev/null +++ b/srcs/libs/ipaddr/ipaddr.c @@ -0,0 +1,4 @@ +// +// Created by xajhuang on 2023/3/21. +// +#include "ipaddr.h" \ No newline at end of file diff --git a/srcs/libs/misc/misc.c b/srcs/libs/misc/misc.c index a6620b5..78fb9a7 100644 --- a/srcs/libs/misc/misc.c +++ b/srcs/libs/misc/misc.c @@ -16,6 +16,9 @@ #include "misc.h" #include "zlog_module.h" #include "common.h" +#include "uthash/uthash.h" + +PSYS_NIC_INFO g_sysNicInfo = NULL; const char *basename_v2(const char *path) { const char *tail = strrchr(path, '/'); @@ -194,7 +197,7 @@ int str_to_ipaddr(const char *pIp, unsigned int *ipAddr) { int get_nic_info(const char *pName, unsigned int *pIp, unsigned int *pNetmask, - unsigned int *pGateway, + unsigned int *pBoardcast, unsigned char *pMac) { int sock; struct ifreq ifr; @@ -225,9 +228,9 @@ int get_nic_info(const char *pName, } } - if (pGateway) { + if (pBoardcast) { if (ioctl(sock, SIOCGIFBRDADDR, &ifr) == 0) { - *pGateway = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; + *pBoardcast = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; } else { err = ERR_MISC_GET_GATEWAY; } @@ -245,6 +248,109 @@ int get_nic_info(const char *pName, return err; } +const char *u32_to_str_ip(unsigned int ip) { + struct in_addr s = {.s_addr = ip}; + return inet_ntoa(s); +} + +int get_all_network_info(PSYS_NIC_INFO pInfo) { + int i; + unsigned long nicCnt; + struct ifreq buf[4096]; + struct ifconf ifc; + PSYS_NIC_INFO pNicInfo; + PNIC_CTX pNic; + + if (pInfo == NULL) { + LOG_MOD(error, ZLOG_MOD_MISC, "Malloc memory failed, size: %lu\n", sizeof(SYS_NIC_INFO)); + return -ERR_INPUT_PARAMS; + } + + if (g_sysNicInfo != NULL) { + pInfo->nicCnt = g_sysNicInfo->nicCnt; + pInfo->pNicCtx = g_sysNicInfo->pNicCtx; + return ERR_SUCCESS; + } + + pNicInfo = (PSYS_NIC_INFO)malloc(sizeof(SYS_NIC_INFO)); + + if (pNicInfo == NULL) { + LOG_MOD(error, ZLOG_MOD_MISC, "Malloc memory failed, size: %lu\n", sizeof(SYS_NIC_INFO)); + return -ERR_MALLOC_MEMORY; + } + + memset(pNicInfo, 0, sizeof(SYS_NIC_INFO)); + + int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sock == -1) { + LOG_MOD(error, ZLOG_MOD_MISC, "Create socket failed\n"); + free(pNicInfo); + return -ERR_SOCK_CREATE; + } + memset(&ifc, 0, sizeof(struct ifconf)); + ifc.ifc_len = sizeof(struct ifreq) * 4096; + ifc.ifc_buf = (char *)buf; + + if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) { + close(sock); + free(pNicInfo); + LOG_MOD(error, ZLOG_MOD_MISC, "IOCTL SIOCGIFCONF socket failed\n"); + return -ERR_SYS_CALL; + } + + nicCnt = ifc.ifc_len / sizeof(struct ifreq); + pNicInfo->pNicCtx = (PNIC_CTX)malloc(sizeof(NIC_CTX) * nicCnt); + + if (pNicInfo->pNicCtx == NULL) { + LOG_MOD(error, ZLOG_MOD_MISC, "Malloc memory failed, size: %lu * %lu\n", sizeof(NIC_CTX), nicCnt); + free(pNicInfo); + close(sock); + return -ERR_MALLOC_MEMORY; + } + + LOG_MOD(info, ZLOG_MOD_MISC, "Malloc memory size: %lu * %lu\n", sizeof(NIC_CTX), nicCnt); + + memset(pNicInfo->pNicCtx, 0, sizeof(NIC_CTX) * nicCnt); + + pNic = &pNicInfo->pNicCtx[0]; + for (i = 0; i < nicCnt; i++) { + U32 ipAddr; + U32 netmaskAddr; + U32 bcAddr; + U8 mac[ETH_ALEN]; + int ret = get_nic_info(buf[i].ifr_name, &ipAddr, &netmaskAddr, &bcAddr, mac); + + if (ret == ERR_SUCCESS) { + strcpy(pNic->ethName, buf[i].ifr_name); + pNic->ipv4Addr = ipAddr; + pNic->ipv4Mask = netmaskAddr; + pNic->ipv4Boardcast = bcAddr; + memcpy(pNic->mac, mac, ETH_ALEN); + + LOG_MOD(trace, ZLOG_MOD_MISC, "Network intreface(%d): %s\n", pNicInfo->nicCnt, pNic->ethName); + LOG_MOD(trace, ZLOG_MOD_MISC, "\t\tIP Address\t:%s\n", u32_to_str_ip(ipAddr)); + LOG_MOD(trace, ZLOG_MOD_MISC, "\t\tNetmask Address\t:%s\n", u32_to_str_ip(netmaskAddr)); + LOG_MOD(trace, ZLOG_MOD_MISC, "\t\tBoardcast Address\t:%s\n", u32_to_str_ip(bcAddr)); + + pNicInfo->nicCnt++; + pNic++; + } else { + LOG_MOD(warn, + ZLOG_MOD_MISC, + "Get system nic(%s) information error:%s(%d)\n", + buf[i].ifr_name, + getErrorEnumNameString(ret), + ret); + } + } + close(sock); + + g_sysNicInfo = pNicInfo; + pInfo->nicCnt = g_sysNicInfo->nicCnt; + pInfo->pNicCtx = g_sysNicInfo->pNicCtx; + return ERR_SUCCESS; +} + const char *get_cur_process_name() { static char g_exeName[1024] = {0}; diff --git a/srcs/opendhcp183/query.cpp b/srcs/opendhcp183/query.cpp index 97ec775..7a50aa6 100644 --- a/srcs/opendhcp183/query.cpp +++ b/srcs/opendhcp183/query.cpp @@ -866,9 +866,6 @@ void iptvCacheCb(uv_timer_t *UNUSED(pArg)) { * 增加 DHCP Server HTTP服务接口 */ #ifdef HTTPSERVER_ON -#define HTTP_HEAD_CONTENT_TYPE_JSON "Content-Type: application/json\r\n" -#define HTTP_HEAD_CONTENT_TYPE_HTML "Content-Type: text/html\r\n" - static void on_get_userinfo(struct mg_http_message *h, void *user_data, PHTTP_RSP_CTX pCtx) { pCtx->pRspHeads = HTTP_HEAD_CONTENT_TYPE_JSON; @@ -962,14 +959,6 @@ static void on_get_alluser(struct mg_http_message *h, void *user_data, PHTTP_RSP pCtx->httpCode = 200; } -typedef struct HTTP_ROUTE_INFO { - char routeName[MAX_URI]; - HTTP_METHOD method; - HTTP_ROUTE_PRIORITY priority; - HTTP_REQUEST_CB cb; - void *pUserData; -} HTTP_ROUTE_INFO, *PHTTP_ROUTE_INFO; - static HTTP_ROUTE_INFO g_routeTable[] = { {"/", GET, PRI_LOWEASE, on_dhcpd_info, nullptr}, {"/dhcp/info/getuser", POST, PRI_NORMAL, on_get_userinfo, nullptr}, diff --git a/srcs/service/CMakeLists.txt b/srcs/service/CMakeLists.txt index 3610a95..d3dcbae 100644 --- a/srcs/service/CMakeLists.txt +++ b/srcs/service/CMakeLists.txt @@ -1,6 +1,9 @@ -INCLUDE_DIRECTORIES(. ../include ../libs/include) +INCLUDE_DIRECTORIES(. ../include ../libs/include ./dhcpd/include ../libs/mongoose) 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 diff --git a/srcs/service/dhcpd/dhcp_option.c b/srcs/service/dhcpd/dhcp_option.c new file mode 100644 index 0000000..e80840b --- /dev/null +++ b/srcs/service/dhcpd/dhcp_option.c @@ -0,0 +1,171 @@ +// +// Created by xajhuang on 2023/3/21. +// +#include +#include "common.h" +#include "dhcp_options.h" +#include "user_errno.h" +#include "zlog_module.h" + +static const DHCP_OPTION_CFG g_opCfg[] = { + // region DHCP optinos configure table + {"SubnetMask", OPT_NETMASK, 3, TRUE }, + {"TimeOffset", OPT_TIMEOFFSET, 4, TRUE }, + {"Router", OPT_ROUTER, 3, TRUE }, + {"TimeServer", OPT_TIMESERVER, 3, TRUE }, + {"NameServer", OPT_NAMESERVER, 3, TRUE }, + {"DomainServer", OPT_DNS, 3, TRUE }, + {"LogServer", OPT_LOGSERVER, 3, TRUE }, + {"QuotesServer", OPT_COOKIESERVER, 3, TRUE }, + {"LPRServer", OPT_LPRSERVER, 3, TRUE }, + {"ImpressServer", OPT_IMPRESSSERVER, 3, TRUE }, + {"RLPServer", OPT_RESLOCSERVER, 3, TRUE }, + {"Hostname", OPT_HOSTNAME, 1, TRUE }, + {"BootFileSize", OPT_BOOTFILESIZE, 5, TRUE }, + {"MeritDumpFile", OPT_MERITDUMP, 1, TRUE }, + {"DomainName", OPT_DOMAINNAME, 1, TRUE }, + {"SwapServer", OPT_SWAPSERVER, 3, TRUE }, + {"RootPath", OPT_ROOTPATH, 1, TRUE }, + {"ExtensionFile", OPT_EXTSPATH, 1, TRUE }, + {"ForwardOn/Off", OPT_IPFORWARD, 7, TRUE }, + {"SrcRteOn/Off", OPT_NONLOCALSR, 7, TRUE }, + {"PolicyFilter", OPT_POLICYFILTER, 8, TRUE }, + {"MaxDGAssembly", OPT_MAXREASSEMBLE, 5, TRUE }, + {"DefaultIPTTL", OPT_IPTTL, 6, TRUE }, + {"MTUTimeout", OPT_PATHMTUAGING, 4, TRUE }, + {"MTUPlateau", OPT_PATHMTUPLATEAU, 2, TRUE }, + {"MTUInterface", OPT_INTERFACEMTU, 5, TRUE }, + {"MTUSubnet", OPT_SUBNETSLOCAL, 7, TRUE }, + {"BroadcastAddress", OPT_BCASTADDRESS, 3, TRUE }, + {"MaskDiscovery", OPT_MASKDISCOVERY, 7, TRUE }, + {"MaskSupplier", OPT_MASKSUPPLIER, 7, TRUE }, + {"RouterDiscovery", OPT_ROUTERDISCOVERY, 7, TRUE }, + {"RouterRequest", OPT_ROUTERSOLIC, 3, TRUE }, + {"StaticRoute", OPT_STATICROUTE, 8, TRUE }, + {"Trailers", OPT_TRAILERENCAPS, 7, TRUE }, + {"ARPTimeout", OPT_ARPTIMEOUT, 4, TRUE }, + {"Ethernet", OPT_ETHERNETENCAPS, 7, TRUE }, + {"DefaultTCPTTL", OPT_TCPTTL, 6, TRUE }, + {"KeepaliveTime", OPT_TCPKEEPALIVEINT, 4, TRUE }, + {"KeepaliveData", OPT_TCPKEEPALIVEGRBG, 7, TRUE }, + {"NISDomain", OPT_NISDOMAIN, 1, TRUE }, + {"NISServers", OPT_NISSERVERS, 3, TRUE }, + {"NTPServers", OPT_NTPSERVERS, 3, TRUE }, + {"VendorSpecificInf", OPT_VENDORSPECIFIC, 2, FALSE}, + {"NETBIOSNameSrv", OPT_NETBIOSNAMESERV, 3, TRUE }, + {"NETBIOSDistSrv", OPT_NETBIOSDGDIST, 3, TRUE }, + {"NETBIOSNodeType", OPT_NETBIOSNODETYPE, 6, TRUE }, + {"NETBIOSScope", OPT_NETBIOSSCOPE, 1, TRUE }, + {"XWindowFont", OPT_X11FONTS, 1, TRUE }, + {"XWindowManager", OPT_X11DISPLAYMNGR, 3, TRUE }, + {"AddressRequest", OPT_REQUESTEDIPADDR, 3, TRUE }, + {"AddressTime", OPT_IPADDRLEASE, 4, TRUE }, + {"OverLoad", OPT_OVERLOAD, 7, FALSE}, + {"DHCPMsgType", OPT_MESSAGETYPE, 6, TRUE }, + {"DHCPServerId", OPT_SERVERID, 3, FALSE}, + {"ParameterList", OPT_PARAMREQLIST, 2, TRUE }, + {"DHCPMessage", OPT_MESSAGE, 1, FALSE}, + {"DHCPMaxMsgSize", OPT_MAXDHCPMSGSIZE, 5, FALSE}, + {"RenewalTime", OPT_RENEWALTIME, 4, TRUE }, + {"RebindingTime", OPT_REBINDINGTIME, 4, TRUE }, + {"ClassId", OPT_VENDORCLASSID, 1, TRUE }, + {"ClientId", OPT_CLIENTID, 2, FALSE}, + {"NetWareIPDomain", OPT_NETWARE_IPDOMAIN, 1, TRUE }, + {"NetWareIPOption", OPT_NETWARE_IPOPTION, 2, TRUE }, + {"NISDomainName", OPT_NISPLUSDOMAIN, 1, TRUE }, + {"NISServerAddr", OPT_NISPLUSSERVERS, 3, TRUE }, + {"TFTPServerName", OPT_TFTPSERVER, 1, TRUE }, + {"BootFileOption", OPT_BOOTFILE, 1, TRUE }, + {"HomeAgentAddrs", OPT_MOBILEIPHOME, 3, TRUE }, + {"SMTPServer", OPT_SMTPSERVER, 3, TRUE }, + {"POP3Server", OPT_POP3SERVER, 3, TRUE }, + {"NNTPServer", OPT_NNTPSERVER, 3, TRUE }, + {"WWWServer", OPT_WWWSERVER, 3, TRUE }, + {"FingerServer", OPT_FINGERSERVER, 3, TRUE }, + {"IRCServer", OPT_IRCSERVER, 3, TRUE }, + {"StreetTalkServer", OPT_STSERVER, 3, TRUE }, + {"STDAServer", OPT_STDASERVER, 3, TRUE }, + {"UserClass", OPT_USERCLASS, 1, FALSE}, + {"DirectoryAgent", OPT_SLPDIRAGENT, 1, TRUE }, + {"ServiceScope", OPT_SLPDIRSCOPE, 1, TRUE }, + {"RapidCommit", OPT_RAPIDCOMMIT, 2, FALSE}, + {"ClientFQDN", OPT_CLIENTFQDN, 2, FALSE}, + {"RelayAgentInformation", OPT_RELAYAGENTINFO, 2, FALSE}, + {"iSNS", OPT_I_SNS, 1, TRUE }, + {"NDSServers", OPT_NDSSERVERS, 3, TRUE }, + {"NDSTreeName", OPT_NDSTREENAME, 1, TRUE }, + {"NDSContext", OPT_NDSCONTEXT, 1, TRUE }, + {"LDAP", OPT_LDAP, 1, TRUE }, + {"PCode", OPT_P_CODE, 1, TRUE }, + {"TCode", OPT_T_CODE, 1, TRUE }, + {"NetInfoAddress", OPT_NETINFOADDRESS, 3, TRUE }, + {"NetInfoTag", OPT_NETINFOTAG, 1, TRUE }, + {"URL", OPT_URL, 1, TRUE }, + {"AutoConfig", OPT_AUTO_CONFIG, 7, TRUE }, + {"NameServiceSearch", OPT_NAMESERVICESEARCH, 2, TRUE }, + {"SubnetSelectionOption", OPT_SUBNETSELECTION, 3, TRUE }, + {"DomainSearch", OPT_DOMAINSEARCH, 1, TRUE }, + {"SIPServersDHCPOption", OPT_SIPSERVERSDHCP, 1, TRUE }, + {"CCC", OPT_CCC, 1, TRUE }, + {"TFTPServerIPaddress", OPT_TFPTSERVERIPADDRESS, 3, TRUE }, + {"CallServerIPaddress", OPT_CALLSERVERIPADDRESS, 3, TRUE }, + {"DiscriminationString", OPT_DISCRIMINATIONSTRING, 1, TRUE }, + {"RemoteStatisticsServerIPAddress", OPT_REMOTESTATISTICSSERVER, 3, TRUE }, + {"HTTPProxyPhone", OPT_HTTPPROXYFORPHONE_SPEC, 3, TRUE }, + {"OPTION_CAPWAP_AC_V4", 138, 1, TRUE }, + {"OPTIONIPv4_AddressMoS", 139, 1, TRUE }, + {"OPTIONIPv4_FQDNMoS", 140, 1, TRUE }, + {"SIPUAServiceDomains", 141, 1, TRUE }, + {"OPTIONIPv4_AddressANDSF", 142, 1, TRUE }, + {"IPTelephone", 176, 1, TRUE }, + {"ConfigurationFile", 209, 1, TRUE }, + {"PathPrefix", 210, 1, TRUE }, + {"RebootTime", 211, 4, TRUE }, + {"OPTION_6RD", 212, 1, TRUE }, + {"OPTION_V4_ACCESS_DOMAIN", 213, 1, TRUE }, + {"BootFileName", OPT_BP_FILE, 1, TRUE }, + {"NextServer", OPT_NEXTSERVER, 3, TRUE }, + // endregion +}; + +static DHCP_OPTION_CFG g_optRuntime[256]; + +void dhcp_option_cfg_init() { + int i; + memset(g_optRuntime, 0, sizeof(g_optRuntime)); + + for (i = 0; i < ARRAY_SIZE(g_opCfg); i++) { + if (g_opCfg[i].enable) { + memcpy(&g_optRuntime[g_opCfg[i].opTag], &g_opCfg[i], sizeof(DHCP_OPTION_CFG)); + } + } +} + +int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal) { + U8 *p = pOptData; + + if (!pVal || !pOptData) { + return -ERR_INPUT_PARAMS; + } + + while (p < (pOptData + nSize)) { + U8 id = *p; + U8 len = *(p + 1); + + if (id == 0xFF) { + return -ERR_ITEM_UNEXISTS; + } + + if (g_optRuntime[id].enable && id == opt) { + pVal->len = len; + pVal->pValue = p + 2; + + printf("++++ %d size %d\n", id, len); + return ERR_SUCCESS; + } + + p = p + len + 2; + } + + return -ERR_ITEM_UNEXISTS; +} \ No newline at end of file diff --git a/srcs/service/dhcpd/dhcpd_network.c b/srcs/service/dhcpd/dhcpd_network.c index 226f319..53896a6 100644 --- a/srcs/service/dhcpd/dhcpd_network.c +++ b/srcs/service/dhcpd/dhcpd_network.c @@ -16,11 +16,21 @@ #include "task_manager.h" #include "zlog_module.h" #include "network/vlan.h" +#include "dhcp_options.h" +#include "config.h" +#include "ip_pool.h" +#include "user_mgr.h" #define PKG_MMAP_BLOCKSIZ (1 << 22) #define PKG_MMAP_FRAMESIZ (1 << 11) #define PKG_MMAP_BLOCKNUM (64) +#define MIN_IPADDR (0xC0A80202) +#define DHCP_NETMASK (0xFFFF0000) +#define GW_IPADDR (0xC0A80201) +#define MASTER_DNS (0x08080808) +#define SALVE_DNS (0x72727272) + typedef struct { struct iovec *rd; uint8_t *map; @@ -97,6 +107,7 @@ static struct sock_filter g_filterCode[] = { {0x6, 0, 0, 0x00040000}, {0x6, 0, 0, 0x00000000}, #endif + // region BPF code // create by: tcpdump "vlan and udp and port 67 and port 68" -dd {0x0, 0, 0, 0x00000000}, {0x2, 0, 0, 0x00000000}, @@ -167,23 +178,98 @@ static struct sock_filter g_filterCode[] = { {0x15, 0, 1, 0x00000043}, {0x6, 0, 0, 0x00040000}, {0x6, 0, 0, 0x00000000}, + // endregion }; static PACKET_MMAP_RING g_pkgRing; +#define VLAN_VNI_ID(x) ntohs((x)) +#define DHCP_XID(x) ntohl((x)) + static struct sock_fprog bpf = { .len = sizeof(g_filterCode) / (sizeof(struct sock_filter)), .filter = g_filterCode, }; -static void on_sock_recv(uv_work_t *req) { - PPKG_PROCESS_INFO pWork = (PPKG_PROCESS_INFO)req->data; - PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pWork->pPkgBase; +typedef struct { + U8 unicast; + U8 cliMac[ETH_ALEN]; + U32 xid; + U32 reqIpAddr; + U32 leaseTime; + char *clientId; + char *vendorClassId; +} DHCP_REQ, *PDHCP_REQ; + +static void on_sock_recv(uv_work_t *req) { + DHCP_REQ reqDhcp; + DHCP_OPT optMsg, opt; + int ret; + PPKG_PROCESS_INFO pWork = (PPKG_PROCESS_INFO)req->data; + PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pWork->pPkgBase; + U32 optSize = pWork->nSize - sizeof(DHCP_PACKAGE); + + // Check op flag + if (pkg->dhcp.op != BOOTP_REQUEST) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Error message op code %d\n", pkg->dhcp.op); + return; + } + + // 获取消息类型 + ret = dhcp_get_option(OPT_MESSAGETYPE, pkg->dhcp.options, optSize, &optMsg); + if (ret != ERR_SUCCESS) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Get \'message type\' option error %d\n", ret); + return; + } + + memset(&reqDhcp, 0, sizeof(DHCP_REQ)); + reqDhcp.unicast = pkg->dhcp.flags != 0 ? TRUE : FALSE; + reqDhcp.xid = DHCP_XID(pkg->dhcp.xid); + memcpy(reqDhcp.cliMac, pkg->dhcp.chaddr, ETH_ALEN); + + switch (*optMsg.pValue) { + case DHCP_MSG_DISCOVER: + ret = dhcp_get_option(OPT_REQUESTEDIPADDR, pkg->dhcp.options, optSize, &opt); + if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) { + reqDhcp.reqIpAddr = ntohl(*((U32 *)opt.pValue)); + } + + ret = dhcp_get_option(OPT_IPADDRLEASE, pkg->dhcp.options, optSize, &opt); + if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) { + reqDhcp.leaseTime = ntohl(*((U32 *)opt.pValue)); + } + + ret = dhcp_get_option(OPT_CLIENTID, pkg->dhcp.options, optSize, &opt); + if (ret == ERR_SUCCESS) { + reqDhcp.clientId = (char *)opt.pValue; + } + + ret = dhcp_get_option(OPT_VENDORCLASSID, pkg->dhcp.options, optSize, &opt); + if (ret == ERR_SUCCESS) { + reqDhcp.vendorClassId = (char *)opt.pValue; + } + break; + case DHCP_MSG_REQUEST: + break; + case DHCP_MSG_RELEASE: + break; + case DHCP_MSG_INFORM: + break; + case DHCP_MSG_DECLINE: + break; + default: + LOG_MOD(error, ZLOG_MOD_DHCPD, "Unkonwn DHCP message type: %d\n", *optMsg.pValue); + LOG_MSG_HEX(trace, pkg, pWork->nSize); + break; + } + + //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_HEX(debug, pkg, pWork->nSize); - LOG_MSG(info, "xid: 0x%08X\n", ntohl(pkg->dhcp.xid)); #if 0 - LOG_MOD(info, ZLOG_MOD_OPENDHCPD, "vlan = %u\n", VXLAN_VIN_ID_PACK(pkg->vlan_hdr.vlan.id)); + LOG_MOD(info, ZLOG_MOD_DHCPD, "vlan = %u\n", VXLAN_VIN_ID_PACK(pkg->vlan_hdr.vlan.id)); LOG_MSG(info, "xid: 0x%08X\n", ntohl(pkg->dhcp.xid)); LOG_MSG(info, "dest mac: %02X:%02X:%02X:%02X:%02X:%02X\n", @@ -210,7 +296,7 @@ static void after_msg_recv(uv_work_t *req, int status) { pMsg->nf -= 1; if (pMsg->nf == 0) { - LOG_MOD(trace, ZLOG_MOD_OPENDHCPD, "---Free resources: %p\n", pMsg); + LOG_MOD(trace, ZLOG_MOD_DHCPD, "---Free resources: %p\n", pMsg); free(pMsg->pPkgInfo); free(pMsg); } @@ -229,17 +315,17 @@ void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) { PPKG_MSG pMsg = (PPKG_MSG)malloc(sizeof(PKG_MSG)); if (pMsg == NULL) { - LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Malloc memory error: %lu\n", sizeof(PKG_MSG)); + LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %lu\n", sizeof(PKG_MSG)); return; } - LOG_MOD(trace, ZLOG_MOD_OPENDHCPD, "++++Malloc resources: %p\n", pMsg); + LOG_MOD(trace, ZLOG_MOD_DHCPD, "++++Malloc resources: %p\n", pMsg); memset(pMsg, 0, sizeof(PKG_MSG)); pMsg->pPkgInfo = (PPKG_PROCESS_INFO)malloc(memSize); if (pMsg->pPkgInfo == NULL) { - LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Malloc memory error: %u\n", memSize); + LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %u\n", memSize); free(pMsg); return; } @@ -274,19 +360,19 @@ static int create_udp_socket() { // 1. create socket int sock_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock_fd < 0) { - LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Socket created failure\n"); + LOG_MOD(error, ZLOG_MOD_DHCPD, "Socket created failure\n"); return -ERR_SOCK_CREATE; } // 2. attach filter (no need to call bind) if ((err = setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))) < 0) { - LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Attaching filter failed: %d\n", err); + LOG_MOD(error, ZLOG_MOD_DHCPD, "Attaching filter failed: %d\n", err); return -ERR_SOCK_SETOPT; } #if 1 // 3. set PACKET_MMAP version if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_VERSION, &v, sizeof(v))) < 0) { - LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Set PACKET_VERSION option failed: %d\n", err); + LOG_MOD(error, ZLOG_MOD_DHCPD, "Set PACKET_VERSION option failed: %d\n", err); return -ERR_SOCK_SETOPT; } @@ -300,7 +386,7 @@ static int create_udp_socket() { g_pkgRing.req.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH; if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_RX_RING, &g_pkgRing.req, sizeof(g_pkgRing.req))) < 0) { - LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Set PACKET_RX_RING option failed: %d\n", err); + LOG_MOD(error, ZLOG_MOD_DHCPD, "Set PACKET_RX_RING option failed: %d\n", err); return -ERR_SOCK_SETOPT; } @@ -312,7 +398,7 @@ static int create_udp_socket() { 0); if (g_pkgRing.map == MAP_FAILED) { - LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "MMAP socket ring failed\n"); + LOG_MOD(error, ZLOG_MOD_DHCPD, "MMAP socket ring failed\n"); return -ERR_MMAP_MEMORY; } @@ -320,10 +406,7 @@ static int create_udp_socket() { g_pkgRing.rd = malloc(g_pkgRing.req.tp_block_nr * sizeof(struct iovec)); if (g_pkgRing.rd == NULL) { - LOG_MOD(error, - ZLOG_MOD_OPENDHCPD, - "Malloc memory failed: %lu\n", - g_pkgRing.req.tp_block_nr * sizeof(struct iovec)); + LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory failed: %lu\n", g_pkgRing.req.tp_block_nr * sizeof(struct iovec)); return -ERR_MMAP_MEMORY; } @@ -333,9 +416,8 @@ static int create_udp_socket() { } #endif // 6. bind socket - const char *iface_name = "ens192"; memset(&addr, 0, sizeof(addr)); - addr.sll_ifindex = (int)if_nametoindex(iface_name); + addr.sll_ifindex = (int)if_nametoindex(config_get_dhcp_nic_name()); addr.sll_family = AF_PACKET; addr.sll_protocol = htons(ETH_P_ALL); addr.sll_hatype = 0; @@ -343,7 +425,7 @@ static int create_udp_socket() { addr.sll_halen = 0; if ((err = bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr))) < 0) { - LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Bind raw socket failed: %d\n", err); + LOG_MOD(error, ZLOG_MOD_DHCPD, "Bind raw socket failed: %d\n", err); return -ERR_SOCK_SETOPT; } @@ -360,7 +442,8 @@ int dhcpd_init() { return sock; } - //LOG_MSG(info, "sizeof DHCP_PACKAGE = %lu\n", sizeof(DHCP_PACKAGE)); + dhcp_user_mgr_init(); + dhcp_option_cfg_init(); uv_udp_init(get_task_manager(), &uvRaw); uv_udp_open(&uvRaw, sock); diff --git a/srcs/service/dhcpd/include/dhcp_options.h b/srcs/service/dhcpd/include/dhcp_options.h new file mode 100644 index 0000000..1c5633e --- /dev/null +++ b/srcs/service/dhcpd/include/dhcp_options.h @@ -0,0 +1,149 @@ +// +// Created by xajhuang on 2023/3/21. +// + +#ifndef VCPE_DHCP_OPTIONS_H +#define VCPE_DHCP_OPTIONS_H +#ifdef __cplusplus +extern "C" { +#endif +// DHCP OPTIONS +#define OPT_PAD 0 +#define OPT_NETMASK 1 +#define OPT_TIMEOFFSET 2 +#define OPT_ROUTER 3 +#define OPT_TIMESERVER 4 +#define OPT_NAMESERVER 5 +#define OPT_DNS 6 +#define OPT_LOGSERVER 7 +#define OPT_COOKIESERVER 8 +#define OPT_LPRSERVER 9 +#define OPT_IMPRESSSERVER 10 +#define OPT_RESLOCSERVER 11 +#define OPT_HOSTNAME 12 +#define OPT_BOOTFILESIZE 13 +#define OPT_MERITDUMP 14 +#define OPT_DOMAINNAME 15 +#define OPT_SWAPSERVER 16 +#define OPT_ROOTPATH 17 +#define OPT_EXTSPATH 18 +#define OPT_IPFORWARD 19 +#define OPT_NONLOCALSR 20 +#define OPT_POLICYFILTER 21 +#define OPT_MAXREASSEMBLE 22 +#define OPT_IPTTL 23 +#define OPT_PATHMTUAGING 24 +#define OPT_PATHMTUPLATEAU 25 +#define OPT_INTERFACEMTU 26 +#define OPT_SUBNETSLOCAL 27 +#define OPT_BCASTADDRESS 28 +#define OPT_MASKDISCOVERY 29 +#define OPT_MASKSUPPLIER 30 +#define OPT_ROUTERDISCOVERY 31 +#define OPT_ROUTERSOLIC 32 +#define OPT_STATICROUTE 33 +#define OPT_TRAILERENCAPS 34 +#define OPT_ARPTIMEOUT 35 +#define OPT_ETHERNETENCAPS 36 +#define OPT_TCPTTL 37 +#define OPT_TCPKEEPALIVEINT 38 +#define OPT_TCPKEEPALIVEGRBG 39 +#define OPT_NISDOMAIN 40 +#define OPT_NISSERVERS 41 +#define OPT_NTPSERVERS 42 +#define OPT_VENDORSPECIFIC 43 +#define OPT_NETBIOSNAMESERV 44 +#define OPT_NETBIOSDGDIST 45 +#define OPT_NETBIOSNODETYPE 46 +#define OPT_NETBIOSSCOPE 47 +#define OPT_X11FONTS 48 +#define OPT_X11DISPLAYMNGR 49 +#define OPT_REQUESTEDIPADDR 50 +#define OPT_IPADDRLEASE 51 +#define OPT_OVERLOAD 52 +#define OPT_MESSAGETYPE 53 +#define OPT_SERVERID 54 +#define OPT_PARAMREQLIST 55 +#define OPT_MESSAGE 56 +#define OPT_MAXDHCPMSGSIZE 57 +#define OPT_RENEWALTIME 58 +#define OPT_REBINDINGTIME 59 +#define OPT_VENDORCLASSID 60 +#define OPT_CLIENTID 61 +#define OPT_NETWARE_IPDOMAIN 62 +#define OPT_NETWARE_IPOPTION 63 +#define OPT_NISPLUSDOMAIN 64 +#define OPT_NISPLUSSERVERS 65 +#define OPT_TFTPSERVER 66 +#define OPT_BOOTFILE 67 +#define OPT_MOBILEIPHOME 68 +#define OPT_SMTPSERVER 69 +#define OPT_POP3SERVER 70 +#define OPT_NNTPSERVER 71 +#define OPT_WWWSERVER 72 +#define OPT_FINGERSERVER 73 +#define OPT_IRCSERVER 74 +#define OPT_STSERVER 75 +#define OPT_STDASERVER 76 +#define OPT_USERCLASS 77 +#define OPT_SLPDIRAGENT 78 +#define OPT_SLPDIRSCOPE 79 +#define OPT_RAPIDCOMMIT 80 +#define OPT_CLIENTFQDN 81 +#define OPT_RELAYAGENTINFO 82 +#define OPT_I_SNS 83 +#define OPT_NDSSERVERS 85 +#define OPT_NDSTREENAME 86 +#define OPT_NDSCONTEXT 87 +#define OPT_AUTHENTICATION 90 +#define OPT_CLIENTSYSTEM 93 +#define OPT_CLIENTNDI 94 +#define OPT_LDAP 95 +#define OPT_UUID_GUID 97 +#define OPT_USER_AUTH 98 +#define OPT_P_CODE 100 +#define OPT_T_CODE 101 +#define OPT_NETINFOADDRESS 112 +#define OPT_NETINFOTAG 113 +#define OPT_URL 114 +#define OPT_AUTO_CONFIG 116 +#define OPT_NAMESERVICESEARCH 117 +#define OPT_SUBNETSELECTION 118 +#define OPT_DOMAINSEARCH 119 +#define OPT_SIPSERVERSDHCP 120 +#define OPT_CLASSLESSSTATICROUTE 121 +#define OPT_CCC 122 +#define OPT_GEOCONF 123 +#define OPT_V_IVENDORCLASS 124 +#define OPT_V_IVENDOR_SPECIFIC 125 +#define OPT_TFPTSERVERIPADDRESS 128 +#define OPT_CALLSERVERIPADDRESS 129 +#define OPT_DISCRIMINATIONSTRING 130 +#define OPT_REMOTESTATISTICSSERVER 131 +#define OPT_802_1PVLANID 132 +#define OPT_802_1QL2PRIORITY 133 +#define OPT_DIFFSERVCODEPOINT 134 +#define OPT_HTTPPROXYFORPHONE_SPEC 135 +#define OPT_SERIAL 252 +#define OPT_BP_FILE 253 +#define OPT_NEXTSERVER 254 +#define OPT_END 255 + +typedef struct { + S8 opName[40]; + U8 opTag; + U8 opType; + U8 enable; +} DHCP_OPTION_CFG, *PDHCP_OPTION_CFG; + +typedef struct { + U8 *pValue; + U8 len; +} DHCP_OPT, *PDHCP_OPT; + +int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal); +void dhcp_option_cfg_init(); +#ifdef __cplusplus +} +#endif +#endif //VCPE_DHCP_OPTIONS_H diff --git a/srcs/service/dhcpd/include/ip_pool.h b/srcs/service/dhcpd/include/ip_pool.h new file mode 100644 index 0000000..57cfdab --- /dev/null +++ b/srcs/service/dhcpd/include/ip_pool.h @@ -0,0 +1,36 @@ +// +// Created by xajhuang on 2023/3/23. +// + +#ifndef VCPE_IP_POOL_H +#define VCPE_IP_POOL_H +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + * key format FFFFFFF-FFFFFFF + * minAddr-maxAddr + * Hex format string + */ +#define MAX_POOL_HASH_KEY (18) + +typedef struct { + S8 poolKey[MAX_POOL_HASH_KEY]; + U32 minAddr; + U32 maxAddr; + U32 netMask; + U32 gwAddr; + U32 primeDNS; + U32 salveDNS; + U32 leaseTime; + UT_hash_handle hh; +} IPPOOL_INFO, *PIPPOOL_INFO; + +void init_default_pool(); +#ifdef __cplusplus +} +#endif +#endif //VCPE_IP_POOL_H diff --git a/srcs/service/dhcpd/include/lease.h b/srcs/service/dhcpd/include/lease.h new file mode 100644 index 0000000..1220ff3 --- /dev/null +++ b/srcs/service/dhcpd/include/lease.h @@ -0,0 +1,30 @@ +// +// Created by xajhuang on 2023/3/23. +// + +#ifndef VCPE_LEASE_H +#define VCPE_LEASE_H +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + U8 macAddr[ETH_ALEN]; + U32 ipAddr; + UT_hash_handle hh; +} MAC_FILTER, *PMAC_FILTER; + +typedef struct { + U32 uId; + U8 macAddr[ETH_ALEN]; + U32 ipAddr; + U32 express; +} LEASE_CACHE, *PLEASE_CACHE; + +#ifdef __cplusplus +} +#endif +#endif //VCPE_LEASE_H diff --git a/srcs/service/dhcpd/include/user_mgr.h b/srcs/service/dhcpd/include/user_mgr.h new file mode 100644 index 0000000..663108f --- /dev/null +++ b/srcs/service/dhcpd/include/user_mgr.h @@ -0,0 +1,31 @@ +// +// Created by xajhuang on 2023/3/23. +// + +#ifndef VCPE_USER_MGR_H +#define VCPE_USER_MGR_H +#include +#include +#include "ip_pool.h" +#include "lease.h" +#ifdef __cplusplus +extern "C" { +#endif +typedef struct { + unsigned int uid; + + PIPPOOL_INFO pPoolMgr; + PMAC_FILTER pAllowTbl; + PMAC_FILTER pDenyTbl; + UT_hash_handle hh; +} DHCP_USER_INFO, *PDHCP_USER_INFO; + +int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool); +int dhcp_user_mgr_init(); +#ifdef HTTPSERVER_ON +int user_init_httpd(); +#endif +#ifdef __cplusplus +} +#endif +#endif //VCPE_USER_MGR_H diff --git a/srcs/service/dhcpd/ip_pool.c b/srcs/service/dhcpd/ip_pool.c new file mode 100644 index 0000000..766c423 --- /dev/null +++ b/srcs/service/dhcpd/ip_pool.c @@ -0,0 +1,132 @@ +// +// Created by xajhuang on 2023/3/23. +// +#include +#include "ip_pool.h" +#include "zvector/zvector.h" +#include "config.h" +#include "user_errno.h" +#include "zlog_module.h" +#include "user_mgr.h" + +#define GEN_IP_POOL_HASH_KEY(p) (sprintf((p)->poolKey, "%08X-%08X", (p)->minAddr, (p)->maxAddr)) + +static PIPPOOL_INFO g_defPool = NULL; + +U32 get_ip_pool_addr(U32 defAddr) { + return 0; +} + +void init_default_pool() { + c_vector pool = (c_vector)config_get_dhcp_server_range_set(); + + for (int i = 0; (pool && i < vect_size(pool)); i++) { + char *pConnChar; + char tmpStr[64]; + POBJ_DHCP_RNG pRange = (POBJ_DHCP_RNG)vect_get_at(pool, i); + + if (pRange) { + struct in_addr addr; + PIPPOOL_INFO p = (PIPPOOL_INFO)malloc(sizeof(IPPOOL_INFO)); + + if (!p) { + LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Malloc memory error: %lu\n", sizeof(IPPOOL_INFO)); + continue; + } + + if (strlen(pRange->rangAddr) == 0) { + LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Error ip pool configure of address\n"); + free(p); + continue; + } + + if (pRange->lease > config_get_dhcp_server_lease_time()) { + p->leaseTime = 0; + } else { + p->leaseTime = pRange->lease; + } + + memset(tmpStr, 0, 64); + strcpy(tmpStr, pRange->rangAddr); + + pConnChar = strchr(tmpStr, '-'); + + // '-' 连接IP地址类型 + if (pConnChar) { + char *pSecIp = pConnChar + 1; + pConnChar[0] = 0; + + if (inet_aton(tmpStr, &addr) == 0) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", tmpStr, pRange->rangAddr); + free(p); + continue; + } else { + p->minAddr = addr.s_addr; + } + + if (inet_aton(pSecIp, &addr) == 0) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", pSecIp, pRange->rangAddr); + free(p); + continue; + } else { + p->maxAddr = addr.s_addr; + } + + // 填充POOL Hash Key + GEN_IP_POOL_HASH_KEY(p); + } else { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Bad DHCP range format: %s\n", tmpStr); + free(p); + continue; + } + + if (strlen(pRange->gateway) > 0) { + if (inet_aton(pRange->gateway, &addr) == 0) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s\n", pRange->gateway); + } else { + p->gwAddr = 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; + } + } + + if (strlen(pRange->dnsSvr) > 0) { + memset(tmpStr, 0, 64); + strcpy(tmpStr, pRange->dnsSvr); + + pConnChar = strchr(tmpStr, ','); + + if (pConnChar) { + char *pSecIp = pConnChar + 1; + pConnChar[0] = 0; + + if (inet_aton(tmpStr, &addr) == 0) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", tmpStr, pRange->dnsSvr); + } else { + p->primeDNS = addr.s_addr; + } + + if (inet_aton(pSecIp, &addr) == 0) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", pSecIp, pRange->dnsSvr); + } else { + p->salveDNS = addr.s_addr; + } + } else { + if (inet_aton(pRange->dnsSvr, &addr) == 0) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", tmpStr, pRange->dnsSvr); + } else { + p->primeDNS = addr.s_addr; + } + } + } + + user_add_ip_pool(pRange->vni, p); + } + } +} \ No newline at end of file diff --git a/srcs/service/dhcpd/lease.c b/srcs/service/dhcpd/lease.c new file mode 100644 index 0000000..2f7a822 --- /dev/null +++ b/srcs/service/dhcpd/lease.c @@ -0,0 +1,8 @@ +// +// Created by xajhuang on 2023/3/23. +// + +#include "lease.h" + +static PMAC_FILTER g_allowTbl = NULL; +static PMAC_FILTER g_blackListTbl = NULL; \ No newline at end of file diff --git a/srcs/service/dhcpd/user_mgr.c b/srcs/service/dhcpd/user_mgr.c new file mode 100644 index 0000000..b6248a8 --- /dev/null +++ b/srcs/service/dhcpd/user_mgr.c @@ -0,0 +1,221 @@ +// +// Created by xajhuang on 2023/3/21. +// +#include "user_mgr.h" +#include "user_errno.h" +#include "zlog_module.h" +#ifdef HTTPSERVER_ON +#include "http_svr.h" +#include "s2j/cJSON.h" +#include "proto.h" +#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); \ + } \ + } while (0) + +// endregion + +#ifdef HTTPSERVER_ON +// region 用户管理接口 +static int get_user_pool_cfg(const char **pRsp, const char *pRequest) { + char logBuff[512]; + const char *pStrContent; + cJSON *pRspRoot, *pRoot, *pUidSet, *pPoolCfgs; + int i, errCode = 0; + + if (pRequest == NULL || strlen(pRequest) == 0) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Misson POST json params\n"); + return ERR_INPUT_PARAMS; + } + + pStrContent = proto_decode_context(pRequest, NULL, NULL, &errCode); + + if (pStrContent == NULL) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Request Json error %s\n", pRequest); + return ERR_PROTO_DECODE; + } + + pRoot = cJSON_Parse(pStrContent); + free((void *)pStrContent); + + if (!pRoot) { + return ERR_JSON_PARSE_OBJ; + } + + pUidSet = cJSON_GetObjectItem(pRoot, "uid"); + pRspRoot = cJSON_CreateObject(); + + pRspRoot = cJSON_CreateObject(); + pPoolCfgs = cJSON_CreateArray(); + cJSON_AddItemToObject(pRspRoot, "poolSet", pPoolCfgs); + + if (cJSON_GetArraySize(pUidSet) == 0) { + PDHCP_USER_INFO pInfo, pTemp; + + HASH_ITER(hh, g_dhcpUsrCfg, pInfo, pTemp) { + cJSON *pUid = cJSON_CreateObject(); + cJSON *pPoolSet = cJSON_CreateArray(); + cJSON_AddItemToArray(pPoolCfgs, pUid); + cJSON_AddNumberToObject(pUid, "uid", pInfo->uid); + cJSON_AddItemToObject(pUid, "poolSet", pPoolSet); + + if (pInfo->pPoolMgr) { + PIPPOOL_INFO pPool, pTmp; + + HASH_ITER(hh, pInfo->pPoolMgr, pPool, pTmp) { + char buf[256]; + cJSON *pItem = cJSON_CreateObject(); + + memset(buf, 0, 256); + sprintf(buf, "%s-%s", u32_to_str_ip(pPool->minAddr), u32_to_str_ip(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)); + + memset(buf, 0, 256); + sprintf(buf, "%s,", u32_to_str_ip(pPool->primeDNS)); + strcat(buf, u32_to_str_ip(pPool->salveDNS)); + + cJSON_AddStringToObject(pItem, "domain_server", buf); + cJSON_AddNumberToObject(pItem, "lease", pPool->leaseTime); + + cJSON_AddItemToArray(pPoolSet, pItem); + } + } + } + } else { + for (i = 0; i < cJSON_GetArraySize(pUidSet); i++) { + PDHCP_USER_INFO pInfo; + cJSON *pId = cJSON_GetArrayItem(pUidSet, i); + cJSON *pUid = cJSON_CreateObject(); + + cJSON_AddItemToArray(pPoolCfgs, pUid); + cJSON_AddNumberToObject(pUid, "uid", pId->valueint); + + HASH_FIND_INT(g_dhcpUsrCfg, &pId->valueint, pInfo); + + if (pInfo) { + cJSON *pPoolSet = cJSON_CreateArray(); + cJSON_AddItemToObject(pUid, "poolSet", pPoolSet); + + if (pInfo->pPoolMgr) { + PIPPOOL_INFO pPool, pTmp; + + HASH_ITER(hh, pInfo->pPoolMgr, pPool, pTmp) { + char buf[256]; + cJSON *pItem = cJSON_CreateObject(); + + memset(buf, 0, 256); + sprintf(buf, "%s-%s", u32_to_str_ip(pPool->minAddr), u32_to_str_ip(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)); + + memset(buf, 0, 256); + sprintf(buf, "%s,", u32_to_str_ip(pPool->primeDNS)); + strcat(buf, u32_to_str_ip(pPool->salveDNS)); + cJSON_AddStringToObject(pItem, "domain_server", buf); + cJSON_AddNumberToObject(pItem, "lease", pPool->leaseTime); + + cJSON_AddItemToArray(pPoolSet, pItem); + } + } + } else { + cJSON_AddNumberToObject(pUid, "status", ERR_ITEM_UNEXISTS); + cJSON_AddStringToObject(pUid, "message", getErrorEnumDesc(ERR_ITEM_UNEXISTS)); + } + } + } + + *pRsp = proto_create_new(pRspRoot, 200); + cJSON_Delete(pRoot); + + return ERR_SUCCESS; +} + +static void on_get_user_pool(struct mg_http_message *h, void *user_data, PHTTP_RSP_CTX pCtx) { + pCtx->pRspHeads = HTTP_HEAD_CONTENT_TYPE_JSON; + + pCtx->errCode = get_user_pool_cfg((const char **)&pCtx->pRspData, h->body.ptr); + if (pCtx->errCode != ERR_SUCCESS) { + pCtx->httpCode = 500; + free(pCtx->pRspData); + return; + } + + pCtx->httpCode = 200; +} + +static HTTP_ROUTE_INFO g_usrRouteTable[] = { + {"/user/dhcp/ippool", POST, PRI_NORMAL, on_get_user_pool, NULL}, +}; + +int user_init_httpd() { + int i; + for (i = 0; i < ARRAY_SIZE(g_usrRouteTable); i++) { + PHTTP_ROUTE_INFO p = &g_usrRouteTable[i]; + http_add_route(p->routeName, p->method, p->priority, p->cb, p->pUserData); + } + + return ERR_SUCCESS; +} +// endregion +#endif + +int dhcp_user_mgr_init() { +#ifdef HTTPSERVER_ON + user_init_httpd(); +#endif + + init_default_pool(); + return ERR_SUCCESS; +} + +int user_alloc_addr(U32 uId, U8 mac[ETH_ALEN], U32 *pAddr) { + PDHCP_USER_INFO pUserCfg, pTemp; + + INIT_DHCP_USER(uId); + + return ERR_SUCCESS; +} + +int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool) { + PIPPOOL_INFO pPoolCfg; + PDHCP_USER_INFO pUserCfg, pTemp; + + INIT_DHCP_USER(uId); + + // 该设备没有地址配置时,直接返回 + if (pPool == NULL) { + return ERR_SUCCESS; + } + + HASH_FIND_STR(pUserCfg->pPoolMgr, pPool->poolKey, pPoolCfg); + + // 改地址池已经存在,提示错误 + if (pPoolCfg != NULL) { + return -ERR_ITEM_EXISTS; + } + + // 添加到当前用户配置项中 + HASH_ADD_STR(pUserCfg->pPoolMgr, poolKey, pPool); + + return ERR_SUCCESS; +}