From ff887e21e32825f934e9b8eddb483aeb3c019bbd Mon Sep 17 00:00:00 2001 From: huangxin Date: Thu, 20 Apr 2023 16:46:20 +0800 Subject: [PATCH] =?UTF-8?q?OCT=201.=20=E6=8B=86=E5=88=86DHCP=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E4=BB=A3=E7=A0=81=EF=BC=8C=E4=BE=9B=E5=85=B6=E5=AE=83?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- depend/system_libs.cmake | 4 +- srcs/libs/include/misc.h | 1 + srcs/libs/misc/misc.c | 30 +++- srcs/service/dhcpd/dhcp_option.c | 1 - srcs/service/dhcpd/dhcpd_network.c | 167 +++++++++------------- srcs/service/dhcpd/include/dhcp_network.h | 84 +++++++++++ srcs/service/dhcpd/include/dhcp_options.h | 1 + srcs/service/dhcpd/include/rfc2131.h | 35 +++++ 8 files changed, 219 insertions(+), 104 deletions(-) create mode 100644 srcs/service/dhcpd/include/dhcp_network.h create mode 100644 srcs/service/dhcpd/include/rfc2131.h diff --git a/depend/system_libs.cmake b/depend/system_libs.cmake index 648dd15..d8549ab 100644 --- a/depend/system_libs.cmake +++ b/depend/system_libs.cmake @@ -19,9 +19,9 @@ FUNCTION(LINUX_INSTALL_SYSTEM_PACKAGE) MESSAGE("Run this command to install system(${OS_DISTRIB_NAME}) dependencies libraries:") IF (${OS_DISTRIB_NAME} MATCHES "CentOS") - MESSAGE(FATAL_ERROR "$sudo yum -y install libcurl-devel czmq-devel openssl-devel") + MESSAGE(FATAL_ERROR "$sudo yum -y install libcurl-devel czmq-devel openssl-devel libjson-c-devel") ELSEIF (${OS_DISTRIB_NAME} MATCHES "Ubuntu") - MESSAGE(FATAL_ERROR "$sudo apt -y install libcurl4-openssl-dev libczmq-dev libssl-dev") + MESSAGE(FATAL_ERROR "$sudo apt -y install libcurl4-openssl-dev libczmq-dev libssl-dev libjson-c-dev") ENDIF () ELSE () MESSAGE(FATAL_ERROR "Run command to install system dependencies libraries [libcurl,libssl,libcrypto,libzmq] by yourself") diff --git a/srcs/libs/include/misc.h b/srcs/libs/include/misc.h index 6bd4c66..b791689 100644 --- a/srcs/libs/include/misc.h +++ b/srcs/libs/include/misc.h @@ -44,6 +44,7 @@ int get_all_network_info(PSYS_NIC_INFO pInfo); const char *u32_to_str_ip(unsigned int ip); unsigned short udp_checksum(unsigned int saddr, unsigned int daddr, unsigned char *pUdp); unsigned short ip_checksum(unsigned char *pIp); +int string_mac_to_bytes(const char *pStrMac, unsigned char macByte[6]); #ifdef __cplusplus } #endif diff --git a/srcs/libs/misc/misc.c b/srcs/libs/misc/misc.c index 303e269..e61cfdb 100644 --- a/srcs/libs/misc/misc.c +++ b/srcs/libs/misc/misc.c @@ -18,6 +18,7 @@ #include "misc.h" #include "zlog_module.h" #include "common.h" +#include "sds/sds.h" PSYS_NIC_INFO g_sysNicInfo = NULL; @@ -309,7 +310,7 @@ int get_all_network_info(PSYS_NIC_INFO pInfo) { return -ERR_MALLOC_MEMORY; } - LOG_MOD(info, ZLOG_MOD_MISC, "Malloc memory size: %lu * %lu\n", sizeof(NIC_CTX), nicCnt); + LOG_MOD(trace, ZLOG_MOD_MISC, "Malloc memory size: %lu * %lu\n", sizeof(NIC_CTX), nicCnt); memset(pNicInfo->pNicCtx, 0, sizeof(NIC_CTX) * nicCnt); @@ -415,4 +416,31 @@ unsigned short udp_checksum(unsigned int saddr, unsigned int daddr, unsigned cha csum = ((csum & 0xFFFF0000) >> 16) + (csum & 0xFFFF); return (unsigned short)(~csum); +} + +int string_mac_to_bytes(const char *pStrMac, unsigned char macByte[6]) { + sds *tokens; + int i, nCnt; + + if (pStrMac == NULL || strlen(pStrMac) != strlen("00:00:00:00:00:00")) { + LOG_MOD(error, ZLOG_MOD_MISC, "Input params error\n"); + return -ERR_INPUT_PARAMS; + } + + tokens = sdssplitlen(pStrMac, (int)strlen(pStrMac), ":", 1, &nCnt); + + if (nCnt != 6) { + LOG_MOD(error, ZLOG_MOD_MISC, "Input MAC[%s] error: %d\n", pStrMac, nCnt); + return -ERR_INPUT_PARAMS; + } + + for (i = 0; i < nCnt; i++) { + macByte[i] = strtoul(tokens[i], NULL, 16); + } + + if (tokens) { + sdsfreesplitres(tokens, nCnt); + } + + return ERR_SUCCESS; } \ No newline at end of file diff --git a/srcs/service/dhcpd/dhcp_option.c b/srcs/service/dhcpd/dhcp_option.c index 6c24088..bd60423 100644 --- a/srcs/service/dhcpd/dhcp_option.c +++ b/srcs/service/dhcpd/dhcp_option.c @@ -5,7 +5,6 @@ #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 diff --git a/srcs/service/dhcpd/dhcpd_network.c b/srcs/service/dhcpd/dhcpd_network.c index 8d4cf50..c28abf7 100644 --- a/srcs/service/dhcpd/dhcpd_network.c +++ b/srcs/service/dhcpd/dhcpd_network.c @@ -1,96 +1,27 @@ // // Created by xajhuang on 2023/3/16. // -#include #include #include - #include -#include #include #include #include #include +#include -#include "service/dhcpd.h" #include "user_errno.h" #include "task_manager.h" #include "zlog_module.h" -#include "network/vlan.h" + #include "dhcp_options.h" #include "config.h" #include "misc.h" #include "user_mgr.h" +#include "rfc2131.h" +#include "dhcp_network.h" -#define DHCP_COOKIE_VAL (0x63825363) -#define PKG_MMAP_BLOCKSIZ (1 << 22) -#define PKG_MMAP_FRAMESIZ (1 << 11) -#define PKG_MMAP_BLOCKNUM (64) -#define MAX_DHCP_PKG_SIZE (512) -#define VLAN_VNI_ID(x) ntohs((x)) -#define DHCP_XID(x) ntohl((x)) -#define MAXIMUM_SNAPLEN (262144) - -#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]) - -typedef struct { - U8 unicast; - 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 { - int sock; - struct sockaddr_ll addr; - struct iovec *rx; - struct iovec *tx; - uint8_t *map_recv; - uint8_t *map_send; - struct tpacket_req3 recv; - struct tpacket_req3 send; - unsigned int index; -} 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 { - uint32_t version; - uint32_t offset_to_priv; - struct tpacket_hdr_v1 h1; -}; - -#pragma pack(1) - -typedef struct { - VLAN_PKG_HDR vlan_hdr; - DHCP_PROTO dhcp; -} DHCP_PACKAGE, *PDHCP_PACKAGE; - -typedef struct { - uv_work_t uvWork; - unsigned short nSize; - unsigned char *pPkgBase; - void *pData; -} PKG_PROCESS_INFO, *PPKG_PROCESS_INFO; - -typedef struct { - unsigned int nf; - PPKG_PROCESS_INFO pPkgInfo; -} PKG_MSG, *PPKG_MSG; - -#pragma pack() +#define MAXIMUM_SNAPLEN (262144) /* TORs (Top of Rack switch) at Facebook run DHCP relayers, these relayers are @@ -219,7 +150,7 @@ static PACKET_MMAP_RING g_pkgRing; static NIC_INFO g_nicInfo; static uv_udp_t g_uvRawSockReq; -void *get_pkg_memory() { +void *get_pkg_free_buf() { int i; ssize_t ret; struct tpacket3_hdr *hdr; @@ -250,7 +181,7 @@ static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) { U8 *pOpt; U16 csum; int tolSize; - PDHCP_PACKAGE pRsp = get_pkg_memory(); + PDHCP_PACKAGE pRsp = get_pkg_free_buf(); if (pRsp == NULL) { LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE); @@ -510,6 +441,7 @@ static void after_msg_recv(uv_work_t *req, int status) { void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) { static unsigned int block_num = 0; + PRECV_CB_DATA pCbData = handle->data; if (status >= 0 && (events & UV_READABLE)) { struct block_desc *pbd = (struct block_desc *)g_pkgRing.rx[block_num].iov_base; @@ -546,7 +478,15 @@ void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) { pMsg->pPkgInfo[i].uvWork.data = &pMsg->pPkgInfo[i]; pMsg->pPkgInfo[i].pData = pMsg; - uv_queue_work(get_task_manager(), &(pMsg->pPkgInfo[i].uvWork), on_sock_recv, after_msg_recv); + if (pCbData) { + uv_queue_work(get_task_manager(), + &(pMsg->pPkgInfo[i].uvWork), + pCbData->work_cb ? pCbData->work_cb : on_sock_recv, + pCbData->after_work_cb ? pCbData->after_work_cb : after_msg_recv); + } else { + uv_queue_work(get_task_manager(), &(pMsg->pPkgInfo[i].uvWork), on_sock_recv, after_msg_recv); + } + ppd = (struct tpacket3_hdr *)((uint8_t *)ppd + ppd->tp_next_offset); } } @@ -556,7 +496,7 @@ void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) { } } -static int create_udp_socket() { +int create_udp_raw_socket(const char *pNicName) { struct sockaddr_ll addr; unsigned int size; int i; @@ -660,7 +600,7 @@ static int create_udp_socket() { // 9. bind socket memset(&addr, 0, sizeof(struct sockaddr_ll)); - addr.sll_ifindex = (int)if_nametoindex(g_nicInfo.pIfName); + addr.sll_ifindex = (int)if_nametoindex(pNicName); addr.sll_family = PF_PACKET; addr.sll_protocol = htons(ETH_P_ALL); addr.sll_hatype = 0; @@ -677,7 +617,7 @@ static int create_udp_socket() { return ERR_SUCCESS; } -static void socket_send_task(uv_timer_t *UNUSED(pArg)) { +void socket_send_task(uv_timer_t *UNUSED(pArg)) { int i; struct tpacket3_hdr *hdr; @@ -694,21 +634,20 @@ static void socket_send_task(uv_timer_t *UNUSED(pArg)) { } } -void init_filter() { +void init_filter(const char *pNetFilter) { #ifdef USED_DEFAULT_BPF bpf.len = sizeof(g_filterCode) / (sizeof(struct sock_filter)); bpf.filter = g_filterCode; #else static pcap_t *pd; pd = pcap_open_dead(DLT_EN10MB, MAXIMUM_SNAPLEN); - struct bpf_program fcode; - char *cmd_buf = "vlan and udp and port 67 and port 68"; - pcap_compile(pd, &fcode, cmd_buf, 1, 0); + //char *cmd_buf = "vlan and udp and port 67 and port 68"; + pcap_compile(pd, &fcode, pNetFilter, 1, 0); - struct bpf_insn *insn = fcode.bf_insns; - struct sock_filter *g_filters = (struct sock_filter *)malloc(fcode.bf_len * sizeof (struct sock_filter)); - for (int i = 0; i < fcode.bf_len; ++insn, ++i){ + struct bpf_insn *insn = fcode.bf_insns; + struct sock_filter *g_filters = (struct sock_filter *)malloc(fcode.bf_len * sizeof(struct sock_filter)); + for (int i = 0; i < fcode.bf_len; ++insn, ++i) { g_filters[i].code = insn->code; g_filters[i].jt = insn->jt; g_filters[i].jf = insn->jf; @@ -723,11 +662,28 @@ void init_filter() { #endif } +void init_raw_socket_poll(void *pRecv, void *pClean) { + static RECV_CB_DATA rcData; + static uv_poll_t uvSocket; + static uv_timer_t uvTm; + + uv_udp_init(get_task_manager(), &g_uvRawSockReq); + uv_udp_open(&g_uvRawSockReq, g_pkgRing.sock); + + uv_poll_init_socket(get_task_manager(), &uvSocket, g_pkgRing.sock); + rcData.work_cb = pRecv; + rcData.after_work_cb = pClean; + uvSocket.data = &rcData; + + uv_poll_start(&uvSocket, UV_READABLE, raw_sock_recv_cb); + + uv_timer_init(get_task_manager(), &uvTm); + uv_timer_start(&uvTm, socket_send_task, 3000, 100); +} + int dhcpd_init() { - static uv_poll_t uvSocket; - static uv_timer_t uvTm; - int ret; - size_t size = MAX_PATH; + int ret; + size_t size = MAX_PATH; memset(&g_nicInfo, 0, sizeof(NIC_INFO)); g_nicInfo.pIfName = (char *)config_get_dhcp_nic_name(); @@ -735,11 +691,11 @@ int dhcpd_init() { get_nic_info(g_nicInfo.pIfName, &g_nicInfo.ipAddr, &g_nicInfo.netmask, NULL, g_nicInfo.macAddr); - init_filter(); + init_filter("vlan and udp and port 67 and port 68"); - ret = create_udp_socket(); + ret = create_udp_raw_socket(g_nicInfo.pIfName); if (ret != ERR_SUCCESS) { - LOG_MOD(error, ZLOG_MOD_DHCPD, "Create receive RAW Socket Error\n"); + LOG_MOD(error, ZLOG_MOD_DHCPD, "Create receive RAW Socket Error: %s(%d)\n", getErrorEnumNameString(-ret), ret); return ret; } @@ -747,14 +703,25 @@ int dhcpd_init() { dhcp_option_cfg_init(); dhcp_lease_init(); - uv_udp_init(get_task_manager(), &g_uvRawSockReq); - uv_udp_open(&g_uvRawSockReq, g_pkgRing.sock); + init_raw_socket_poll(NULL, NULL); - uv_poll_init_socket(get_task_manager(), &uvSocket, g_pkgRing.sock); - uv_poll_start(&uvSocket, UV_READABLE, raw_sock_recv_cb); + return ERR_SUCCESS; +} - uv_timer_init(get_task_manager(), &uvTm); - uv_timer_start(&uvTm, socket_send_task, 3000, 100); +int dhcp_uninit() { + unsigned int size = g_pkgRing.recv.tp_block_size * g_pkgRing.recv.tp_block_nr + + g_pkgRing.send.tp_block_size * g_pkgRing.send.tp_block_nr; + close(g_pkgRing.sock); + g_pkgRing.sock = -1; + if (g_pkgRing.tx) { + free(g_pkgRing.tx); + } + + if (g_pkgRing.rx) { + free(g_pkgRing.rx); + } + + munmap(g_pkgRing.map_recv, size); return ERR_SUCCESS; } \ No newline at end of file diff --git a/srcs/service/dhcpd/include/dhcp_network.h b/srcs/service/dhcpd/include/dhcp_network.h new file mode 100644 index 0000000..544ec4d --- /dev/null +++ b/srcs/service/dhcpd/include/dhcp_network.h @@ -0,0 +1,84 @@ +// +// Created by xajhuang on 2023/4/20. +// + +#ifndef VCPE_DHCP_NETWORK_H +#define VCPE_DHCP_NETWORK_H +#include +#include +#include "network/vlan.h" +#include "service/dhcpd.h" +#ifdef __cplusplus +extern "C" { +#endif +#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 PKG_MMAP_BLOCKSIZ (1 << 22) +#define PKG_MMAP_FRAMESIZ (1 << 11) +#define PKG_MMAP_BLOCKNUM (64) + +typedef struct { + int sock; + struct sockaddr_ll addr; + struct iovec *rx; + struct iovec *tx; + uint8_t *map_recv; + uint8_t *map_send; + struct tpacket_req3 recv; + struct tpacket_req3 send; + unsigned int index; +} 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 { + uint32_t version; + uint32_t offset_to_priv; + struct tpacket_hdr_v1 h1; +}; + +typedef struct { + uv_work_cb work_cb; + uv_after_work_cb after_work_cb; +} RECV_CB_DATA, *PRECV_CB_DATA; + +#pragma pack(1) + +typedef struct { + VLAN_PKG_HDR vlan_hdr; + DHCP_PROTO dhcp; +} DHCP_PACKAGE, *PDHCP_PACKAGE; + +typedef struct { + uv_work_t uvWork; + unsigned short nSize; + unsigned char *pPkgBase; + void *pData; +} PKG_PROCESS_INFO, *PPKG_PROCESS_INFO; + +typedef struct { + unsigned int nf; + PPKG_PROCESS_INFO pPkgInfo; +} PKG_MSG, *PPKG_MSG; + +#pragma pack() + +void raw_sock_recv_cb(uv_poll_t *handle, int status, int events); +void socket_send_task(uv_timer_t *UNUSED(pArg)); +void init_raw_socket_poll(void *pRecv, void *pClean); +int create_udp_raw_socket(const char *pNicName); +void init_filter(const char *pNetFilter); +void *get_pkg_free_buf(); +U32 pkg_mmap_tx(U8 *pData, U32 nBytes); +int dhcp_uninit(); +#ifdef __cplusplus +} +#endif +#endif //VCPE_DHCP_NETWORK_H diff --git a/srcs/service/dhcpd/include/dhcp_options.h b/srcs/service/dhcpd/include/dhcp_options.h index d5457ce..9efb73b 100644 --- a/srcs/service/dhcpd/include/dhcp_options.h +++ b/srcs/service/dhcpd/include/dhcp_options.h @@ -4,6 +4,7 @@ #ifndef VCPE_DHCP_OPTIONS_H #define VCPE_DHCP_OPTIONS_H +#include "common.h" #ifdef __cplusplus extern "C" { #endif diff --git a/srcs/service/dhcpd/include/rfc2131.h b/srcs/service/dhcpd/include/rfc2131.h new file mode 100644 index 0000000..99cf2e6 --- /dev/null +++ b/srcs/service/dhcpd/include/rfc2131.h @@ -0,0 +1,35 @@ +// +// Created by xajhuang on 2023/4/20. +// + +#ifndef VCPE_RFC2131_H +#define VCPE_RFC2131_H +#include +#include "common.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define DHCP_COOKIE_VAL (0x63825363) +#define MAX_DHCP_PKG_SIZE (512) +#define VLAN_VNI_ID(x) ntohs((x)) +#define DHCP_XID(x) ntohl((x)) + +#define DHCP_CLI_PORT (68) +#define DHCP_SVR_PORT (67) + +typedef struct { + U8 unicast; + U8 cliMac[ETH_ALEN]; + U32 xid; + U32 reqIpAddr; + U32 leaseTime; + char clientId[256]; + char vendorClassId[256]; + char hostName[256]; +} DHCP_REQ, *PDHCP_REQ; + +#ifdef __cplusplus +} +#endif +#endif //VCPE_RFC2131_H