diff --git a/.clang-format b/.clang-format index e7a61da..f12263a 100644 --- a/.clang-format +++ b/.clang-format @@ -72,7 +72,7 @@ BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 140 +ColumnLimit: 120 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: true ConstructorInitializerAllOnOneLineOrOnePerLine: true diff --git a/srcs/libs/include/misc.h b/srcs/libs/include/misc.h index 902237b..6bd4c66 100644 --- a/srcs/libs/include/misc.h +++ b/srcs/libs/include/misc.h @@ -42,6 +42,8 @@ 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); +unsigned short udp_checksum(unsigned int saddr, unsigned int daddr, unsigned char *pUdp); +unsigned short ip_checksum(unsigned char *pIp); #ifdef __cplusplus } #endif diff --git a/srcs/libs/include/user_errno.h b/srcs/libs/include/user_errno.h index 2caf25d..ae5e5fd 100644 --- a/srcs/libs/include/user_errno.h +++ b/srcs/libs/include/user_errno.h @@ -70,6 +70,7 @@ extern "C" { ERR_CODE(ERR_DHCP_NO_POOL, "找不到可用地址池") \ ERR_CODE(ERR_DHCP_NO_ADDR, "找不到可用IP地址") \ ERR_CODE(ERR_SOCK_CREATE, "创建套接字失败") \ + ERR_CODE(ERR_SOCK_SEND, "套接字发送数据失败") \ ERR_CODE(ERR_SOCK_SETOPT, "设置套接字参数失败") #define GENERATE_ENUM(ENUM, x) ENUM, diff --git a/srcs/libs/misc/misc.c b/srcs/libs/misc/misc.c index 78fb9a7..303e269 100644 --- a/srcs/libs/misc/misc.c +++ b/srcs/libs/misc/misc.c @@ -11,12 +11,13 @@ #include <sys/ioctl.h> #include <linux/if_ether.h> #include <sys/time.h> +#include <netinet/udp.h> +#include <netinet/ip.h> #include "user_errno.h" #include "misc.h" #include "zlog_module.h" #include "common.h" -#include "uthash/uthash.h" PSYS_NIC_INFO g_sysNicInfo = NULL; @@ -364,4 +365,54 @@ const char *get_cur_process_name() { } return basename_v2(g_exeName); +} + +unsigned short calc_checksum(unsigned short *buffer, int size, U32 sum) { + unsigned long cksum = ((sum & 0xFFFF0000) >> 16) + (sum & 0xFFFF); + + while (size > 1) { + cksum += *buffer++; + size -= sizeof(unsigned short); + } + + if (size) { + cksum += *(unsigned short *)buffer; + } + + cksum = (cksum >> 16) + (cksum & 0xffff); + cksum += (cksum >> 16); + + return cksum; + //return (unsigned short)(~cksum); +} + +unsigned short ip_checksum(unsigned char *pIp) { + unsigned int csum; + struct iphdr *pIph = (struct iphdr *)pIp; + pIph->check = 0; + + csum = calc_checksum((unsigned short *)pIp, 20, 0); + + csum = ((csum & 0xFFFF0000) >> 16) + (csum & 0xFFFF); + return (unsigned short)(~csum); +} + +unsigned short udp_checksum(unsigned int saddr, unsigned int daddr, unsigned char *pUdp) { + unsigned char padBuf[12]; + unsigned int csum; + struct udphdr *pUhd = (struct udphdr *)pUdp; + + memcpy(&padBuf[0], &saddr, 4); + memcpy(&padBuf[4], &daddr, 4); + padBuf[8] = 0; + padBuf[9] = 17; + padBuf[10] = pUdp[4]; + padBuf[11] = pUdp[5]; + + pUhd->check = 0; + csum = calc_checksum((unsigned short *)pUdp, ntohs(pUhd->len), 0); + csum = calc_checksum((unsigned short *)padBuf, 12, csum); + + csum = ((csum & 0xFFFF0000) >> 16) + (csum & 0xFFFF); + return (unsigned short)(~csum); } \ No newline at end of file diff --git a/srcs/service/dhcpd/dhcp_option.c b/srcs/service/dhcpd/dhcp_option.c index 497a541..6c24088 100644 --- a/srcs/service/dhcpd/dhcp_option.c +++ b/srcs/service/dhcpd/dhcp_option.c @@ -141,22 +141,39 @@ void dhcp_option_cfg_init() { } } -void dhcp_add_number_option(U8 *pBegin, int opt, U8 value, U8 nSize) { +int dhcp_add_u8_option(U8 *pBegin, int opt, U8 value) { *pBegin = opt; pBegin++; - *pBegin = nSize; + *pBegin = 1; pBegin++; - memcpy(pBegin, &value, nSize); - pBegin += nSize; + *pBegin = value; + + return 3; } -void dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize) { +int dhcp_add_u32_option(U8 *pBegin, int opt, U32 value) { + *pBegin = opt; + pBegin++; + *pBegin = 4; + pBegin++; + memcpy(pBegin, &value, 4); + return 4 + 2; +} + +int dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize) { *pBegin = opt; pBegin++; *pBegin = nSize; pBegin++; memcpy(pBegin, buf, nSize); pBegin += nSize; + + return nSize + 2; +} + +int dhcp_add_string_option(U8 *pBegin, int opt, const char *buf) { + dhcp_add_buf_option(pBegin, opt, (U8 *)buf, strlen(buf) + 1); + return (int)(strlen(buf) + 1 + 2); } int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal) { @@ -177,8 +194,6 @@ int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal) { if (g_optRuntime[id].enable && id == opt) { pVal->len = len; pVal->pValue = p + 2; - - printf("++++ %d size %d\n", id, len); return ERR_SUCCESS; } diff --git a/srcs/service/dhcpd/dhcpd_network.c b/srcs/service/dhcpd/dhcpd_network.c index 3eae98f..c9dc1ef 100644 --- a/srcs/service/dhcpd/dhcpd_network.c +++ b/srcs/service/dhcpd/dhcpd_network.c @@ -21,12 +21,16 @@ #include "misc.h" #include "user_mgr.h" -#define PKG_MMAP_BLOCKSIZ (1 << 22) -#define PKG_MMAP_FRAMESIZ (1 << 11) -#define PKG_MMAP_BLOCKNUM (64) -#define MAX_DHCP_PKG_SIZE (512) +#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 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 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; @@ -40,9 +44,15 @@ typedef struct { } DHCP_REQ, *PDHCP_REQ; typedef struct { - struct iovec *rd; - uint8_t *map; - struct tpacket_req3 req; + 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 { @@ -201,16 +211,39 @@ static struct sock_filter g_filterCode[] = { static PACKET_MMAP_RING g_pkgRing; static NIC_INFO g_nicInfo; - -#define VLAN_VNI_ID(x) ntohs((x)) -#define DHCP_XID(x) ntohl((x)) +static uv_udp_t g_uvRawScokReq; static struct sock_fprog bpf = { .len = sizeof(g_filterCode) / (sizeof(struct sock_filter)), .filter = g_filterCode, }; +U32 pkg_mmap_tx(U8 *pData, U32 nBytes) { + int i; + ssize_t ret; + struct tpacket3_hdr *hdr; + + for (i = 0; i < g_pkgRing.send.tp_frame_nr; i++) { + hdr = (struct tpacket3_hdr *)(g_pkgRing.tx[0].iov_base + (g_pkgRing.send.tp_frame_size * g_pkgRing.index)); + g_pkgRing.index = (g_pkgRing.index + 1) % g_pkgRing.send.tp_frame_nr; + + if (!(hdr->tp_status & (TP_STATUS_SEND_REQUEST | TP_STATUS_SENDING))) { + U8 *p = (U8 *)hdr + TPACKET3_HDRLEN - sizeof(struct sockaddr_ll); + memcpy(p, pData, nBytes); + hdr->tp_next_offset = 0; + hdr->tp_len = nBytes; + hdr->tp_snaplen = nBytes; + hdr->tp_status = TP_STATUS_SEND_REQUEST; + return hdr->tp_len; + } + } + + return 0; +} + static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) { + U16 csum; + int tolSize; PDHCP_PACKAGE pRsp = (PDHCP_PACKAGE)malloc(MAX_DHCP_PKG_SIZE); U8 *pOpt = pRsp->dhcp.options; @@ -236,8 +269,10 @@ static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) { // IP 头 memcpy(&pRsp->vlan_hdr.ip, &pReq->vlan_hdr.ip, sizeof(struct iphdr)); + // TOS + pRsp->vlan_hdr.ip.tos = 0; // 更新源IP - pRsp->vlan_hdr.ip.saddr = htonl(g_nicInfo.ipAddr); + pRsp->vlan_hdr.ip.saddr = g_nicInfo.ipAddr; // 更新目的IP地址,广播255.255.255.255 pRsp->vlan_hdr.ip.daddr = 0xFFFFFFFF; @@ -263,7 +298,10 @@ static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) { // DHCP服务端主机名 memcpy(pRsp->dhcp.sname, g_nicInfo.hostname, MIN(64, strlen(g_nicInfo.hostname))); // Magic Cookie: DHCP - memcpy(&pRsp->dhcp.cookie, "DHCP", 4); + // + // memcpy(&pRsp->dhcp.cookie, DHCP_COOKIE_VAL, 4); + pRsp->dhcp.cookie = htonl(DHCP_COOKIE_VAL); + pRsp->dhcp.hops = 0; pRsp->dhcp.secs = 0; pRsp->dhcp.flags = 0; @@ -273,39 +311,57 @@ static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) { // DHCP Options // DHCP 消息类型 - dhcp_add_number_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_OFFER, 1); - pOpt += 3; + pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_OFFER); // 子网掩码 - dhcp_add_number_option(pOpt, OPT_NETMASK, pIpInfo->netMask, 4); - pOpt += 6; + pOpt += dhcp_add_u32_option(pOpt, OPT_NETMASK, htonl(pIpInfo->netMask)); // 租约 - dhcp_add_number_option(pOpt, OPT_IPADDRLEASE, htonl(pIpInfo->leaseTime), 4); - pOpt += 6; + pOpt += dhcp_add_u32_option(pOpt, OPT_IPADDRLEASE, htonl(pIpInfo->leaseTime)); // DHCP Server - dhcp_add_number_option(pOpt, OPT_SERVERID, g_nicInfo.ipAddr, 4); - pOpt += 6; + pOpt += dhcp_add_u32_option(pOpt, OPT_SERVERID, g_nicInfo.ipAddr); // DNS if (pIpInfo->primeDNS != 0) { if (pIpInfo->salveDNS == 0) { - dhcp_add_number_option(pOpt, OPT_DNS, pIpInfo->primeDNS, 4); - pOpt += 6; + pOpt += dhcp_add_u32_option(pOpt, OPT_DNS, htonl(pIpInfo->primeDNS)); } else { - dhcp_add_buf_option(pOpt, OPT_DNS, (U8 *)&pIpInfo->primeDNS, 8); - pOpt += 10; + U8 buf[8] = {0}; + U32 *pVal = (U32 *)buf; + *pVal++ = htonl(pIpInfo->primeDNS); + *pVal = htonl(pIpInfo->salveDNS); + pOpt += dhcp_add_buf_option(pOpt, OPT_DNS, buf, 8); } } // 网关 if (pIpInfo->gwAddr != 0) { - dhcp_add_number_option(pOpt, OPT_ROUTER, pIpInfo->gwAddr, 4); - pOpt += 6; + pOpt += dhcp_add_u32_option(pOpt, OPT_ROUTER, htonl(pIpInfo->gwAddr)); } // DHCP 主机名 - dhcp_add_buf_option(pOpt, OPT_DOMAINNAME, (U8 *)g_nicInfo.hostname, strlen(g_nicInfo.hostname)); - pOpt += strlen(g_nicInfo.hostname) + 2; + pOpt += dhcp_add_string_option(pOpt, OPT_DOMAINNAME, "workgroup"); + *pOpt = OPT_END; - *pOpt = OPT_END; + // 计算包总长度 + tolSize = (int)((pOpt - pRsp->dhcp.options) + 1 + sizeof(DHCP_PACKAGE)); - LOG_MSG_HEX(debug, pRsp, 256); + // 计算 IP 数据长度 + pRsp->vlan_hdr.ip.tot_len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr)); + // 计算 UDP 数据长度 + pRsp->vlan_hdr.udp.len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr) - sizeof(struct iphdr)); + + // 计算 IP 校验和 + csum = htons(ip_checksum((unsigned char *)&pRsp->vlan_hdr.ip)); + pRsp->vlan_hdr.ip.check = htons(csum); + + // 计算 UDP 校验和 + csum = htons(udp_checksum(pRsp->vlan_hdr.ip.saddr, pRsp->vlan_hdr.ip.daddr, (unsigned char *)&pRsp->vlan_hdr.udp)); + pRsp->vlan_hdr.udp.check = htons(csum); + + LOG_MOD(trace, ZLOG_MOD_DHCPD, "OPTIONS size: %ld\n", (intptr_t)(pOpt - pRsp->dhcp.options) + 1); + LOG_MOD(trace, ZLOG_MOD_DHCPD, "Total size: %d\n", tolSize); + + // 发送数据 + if (pkg_mmap_tx((U8 *)pRsp, tolSize) != tolSize) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Send package(%u bytes) error\n", tolSize); + return -ERR_SOCK_SEND; + } return ERR_SUCCESS; } @@ -380,8 +436,16 @@ static void on_sock_recv(uv_work_t *req) { u32_to_str_ip(ntohl(ip))); ret = dhcp_resp_offer(pkg, pIpInfo, ip); + + if (ret != ERR_SUCCESS) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Send Offer error: %d\n", ret); + } } else { - //LOG_MOD(error, ZLOG_MOD_DHCPD, ); + LOG_MOD(error, + ZLOG_MOD_DHCPD, + "DHCP prepare assign ipaddress error: [%s(%s)]\n", + macStr, + reqDhcp.hostName); } break; case DHCP_MSG_REQUEST: @@ -440,8 +504,8 @@ 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; - if (status >= 0) { - struct block_desc *pbd = (struct block_desc *)g_pkgRing.rd[block_num].iov_base; + if (status >= 0 && (events & UV_READABLE)) { + struct block_desc *pbd = (struct block_desc *)g_pkgRing.rx[block_num].iov_base; if ((pbd->h1.block_status & TP_STATUS_USER) && (pbd->h1.num_pkts > 0)) { int i; @@ -486,14 +550,14 @@ void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) { } static int create_udp_socket() { - int i; - int err; - int v = TPACKET_V3; - struct sockaddr_ll addr; + unsigned int size; + int i; + int err; + int v = TPACKET_V3; // 1. create socket - int sock_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + int sock_fd = socket(PF_PACKET, SOCK_RAW, 0); if (sock_fd < 0) { LOG_MOD(error, ZLOG_MOD_DHCPD, "Socket created failure\n"); return -ERR_SOCK_CREATE; @@ -504,74 +568,130 @@ static int create_udp_socket() { 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_DHCPD, "Set PACKET_VERSION option failed: %d\n", err); return -ERR_SOCK_SETOPT; } - // 4. setup PAKCET_MMAP ring - memset(&g_pkgRing.req, 0, sizeof(g_pkgRing.req)); - g_pkgRing.req.tp_block_size = PKG_MMAP_BLOCKSIZ; - g_pkgRing.req.tp_frame_size = PKG_MMAP_FRAMESIZ; - g_pkgRing.req.tp_block_nr = PKG_MMAP_BLOCKNUM; - g_pkgRing.req.tp_frame_nr = (PKG_MMAP_BLOCKSIZ * PKG_MMAP_BLOCKNUM) / PKG_MMAP_FRAMESIZ; - g_pkgRing.req.tp_retire_blk_tov = 60; - g_pkgRing.req.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH; + // 4. setup PAKCET_MMAP rx ring + memset(&g_pkgRing.recv, 0, sizeof(g_pkgRing.recv)); + g_pkgRing.recv.tp_block_size = PKG_MMAP_BLOCKSIZ; + g_pkgRing.recv.tp_frame_size = PKG_MMAP_FRAMESIZ; + g_pkgRing.recv.tp_block_nr = PKG_MMAP_BLOCKNUM; + g_pkgRing.recv.tp_frame_nr = (PKG_MMAP_BLOCKSIZ * PKG_MMAP_BLOCKNUM) / PKG_MMAP_FRAMESIZ; + g_pkgRing.recv.tp_retire_blk_tov = 60; + g_pkgRing.recv.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) { + if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_RX_RING, &g_pkgRing.recv, sizeof(g_pkgRing.recv))) < 0) { LOG_MOD(error, ZLOG_MOD_DHCPD, "Set PACKET_RX_RING option failed: %d\n", err); return -ERR_SOCK_SETOPT; } - g_pkgRing.map = mmap(NULL, - g_pkgRing.req.tp_block_size * g_pkgRing.req.tp_block_nr, - PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_LOCKED, - sock_fd, - 0); + // 5. setup PACKET_MMAP tx ring + memset(&g_pkgRing.send, 0, sizeof(g_pkgRing.send)); + g_pkgRing.send.tp_block_size = PKG_MMAP_BLOCKSIZ; + g_pkgRing.send.tp_frame_size = PKG_MMAP_FRAMESIZ; + g_pkgRing.send.tp_block_nr = PKG_MMAP_BLOCKNUM; + g_pkgRing.send.tp_frame_nr = (PKG_MMAP_BLOCKSIZ * PKG_MMAP_BLOCKNUM) / PKG_MMAP_FRAMESIZ; - if (g_pkgRing.map == MAP_FAILED) { + if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_TX_RING, &g_pkgRing.send, sizeof(g_pkgRing.recv))) < 0) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Set PACKET_TX_RING option failed: %d\n", err); + return -ERR_SOCK_SETOPT; + } + + // 6. mmap RX/TX ring + 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; + + g_pkgRing.map_recv = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED | MAP_POPULATE, sock_fd, 0); + g_pkgRing.map_send = g_pkgRing.map_recv + g_pkgRing.recv.tp_block_size * g_pkgRing.recv.tp_block_nr; + + if (g_pkgRing.map_recv == MAP_FAILED) { LOG_MOD(error, ZLOG_MOD_DHCPD, "MMAP socket ring failed\n"); + perror("title"); return -ERR_MMAP_MEMORY; } - // 5. malloc read buffer - g_pkgRing.rd = malloc(g_pkgRing.req.tp_block_nr * sizeof(struct iovec)); + LOG_MOD(trace, ZLOG_MOD_DHCPD, "size = %u\n", size); + LOG_MOD(trace, ZLOG_MOD_DHCPD, "MMAP address recv = %p, send = %p\n", g_pkgRing.map_recv, g_pkgRing.map_send); - if (g_pkgRing.rd == NULL) { - LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory failed: %lu\n", g_pkgRing.req.tp_block_nr * sizeof(struct iovec)); + // 7. malloc read buffer + g_pkgRing.rx = malloc(g_pkgRing.recv.tp_block_nr * sizeof(struct iovec)); + if (g_pkgRing.rx == NULL) { + LOG_MOD(error, + ZLOG_MOD_DHCPD, + "Malloc memory failed: %lu\n", + g_pkgRing.recv.tp_block_nr * sizeof(struct iovec)); return -ERR_MMAP_MEMORY; } - for (i = 0; i < g_pkgRing.req.tp_block_nr; ++i) { - g_pkgRing.rd[i].iov_base = g_pkgRing.map + (i * g_pkgRing.req.tp_block_size); - g_pkgRing.rd[i].iov_len = g_pkgRing.req.tp_block_size; + memset(g_pkgRing.rx, 0, g_pkgRing.recv.tp_block_nr * sizeof(struct iovec)); + for (i = 0; i < g_pkgRing.recv.tp_block_nr; ++i) { + g_pkgRing.rx[i].iov_base = g_pkgRing.map_recv + (i * g_pkgRing.recv.tp_block_size); + g_pkgRing.rx[i].iov_len = g_pkgRing.recv.tp_block_size; } -#endif - // 6. bind socket - memset(&addr, 0, sizeof(addr)); + + // 8. malloc send buffer + g_pkgRing.tx = malloc(g_pkgRing.send.tp_block_nr * sizeof(struct iovec)); + if (g_pkgRing.tx == NULL) { + LOG_MOD(error, + ZLOG_MOD_DHCPD, + "Malloc memory failed: %lu\n", + g_pkgRing.send.tp_block_nr * sizeof(struct iovec)); + + munmap(g_pkgRing.map_recv, size * 2); + return -ERR_MMAP_MEMORY; + } + + memset(g_pkgRing.tx, 0, g_pkgRing.send.tp_block_nr * sizeof(struct iovec)); + for (i = 0; i < g_pkgRing.send.tp_block_nr; ++i) { + g_pkgRing.tx[i].iov_base = g_pkgRing.map_send + (i * g_pkgRing.send.tp_block_size); + g_pkgRing.tx[i].iov_len = g_pkgRing.send.tp_block_size; + } + + // 9. bind socket + memset(&addr, 0, sizeof(struct sockaddr_ll)); addr.sll_ifindex = (int)if_nametoindex(g_nicInfo.pIfName); - addr.sll_family = AF_PACKET; + addr.sll_family = PF_PACKET; addr.sll_protocol = htons(ETH_P_ALL); addr.sll_hatype = 0; addr.sll_pkttype = 0; addr.sll_halen = 0; - if ((err = bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr))) < 0) { + if ((err = bind(sock_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_ll))) < 0) { LOG_MOD(error, ZLOG_MOD_DHCPD, "Bind raw socket failed: %d\n", err); return -ERR_SOCK_SETOPT; } - return sock_fd; + g_pkgRing.sock = sock_fd; + + return ERR_SUCCESS; +} + +static void socket_send_task(uv_timer_t *UNUSED(pArg)) { + int i; + struct tpacket3_hdr *hdr; + + for (i = 0; i < g_pkgRing.send.tp_frame_nr && g_pkgRing.sock != 0; i++) { + hdr = (struct tpacket3_hdr *)(g_pkgRing.tx[0].iov_base + (g_pkgRing.send.tp_frame_size * i)); + if ((hdr->tp_status & TP_STATUS_SEND_REQUEST) || (hdr->tp_status & TP_STATUS_SENDING)) { + ssize_t ret = sendto(g_pkgRing.sock, NULL, 0, MSG_DONTWAIT, NULL, sizeof(struct sockaddr_ll)); + + if (ret == -1) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Send pakcet error\n"); + } + break; + } + } } int dhcpd_init() { - static uv_udp_t uvRaw; - static uv_poll_t uvSocket; - int sock; - size_t size = MAX_PATH; + static uv_poll_t uvSocket; + static uv_timer_t uvTm; + int ret; + size_t size = MAX_PATH; memset(&g_nicInfo, 0, sizeof(NIC_INFO)); g_nicInfo.pIfName = (char *)config_get_dhcp_nic_name(); @@ -579,21 +699,24 @@ int dhcpd_init() { get_nic_info(g_nicInfo.pIfName, &g_nicInfo.ipAddr, &g_nicInfo.netmask, NULL, g_nicInfo.macAddr); - sock = create_udp_socket(); - - if (sock <= 0) { - return sock; + ret = create_udp_socket(); + if (ret != ERR_SUCCESS) { + LOG_MOD(error, ZLOG_MOD_DHCPD, "Create receive RAW Socket Error\n"); + return ret; } dhcp_user_mgr_init(); dhcp_option_cfg_init(); dhcp_lease_init(); - uv_udp_init(get_task_manager(), &uvRaw); - uv_udp_open(&uvRaw, sock); + uv_udp_init(get_task_manager(), &g_uvRawScokReq); + uv_udp_open(&g_uvRawScokReq, g_pkgRing.sock); - uv_poll_init_socket(get_task_manager(), &uvSocket, sock); + uv_poll_init_socket(get_task_manager(), &uvSocket, g_pkgRing.sock); 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); + return ERR_SUCCESS; } \ No newline at end of file diff --git a/srcs/service/dhcpd/include/dhcp_options.h b/srcs/service/dhcpd/include/dhcp_options.h index d7e446e..d5457ce 100644 --- a/srcs/service/dhcpd/include/dhcp_options.h +++ b/srcs/service/dhcpd/include/dhcp_options.h @@ -141,8 +141,10 @@ typedef struct { U8 len; } 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_add_u8_option(U8 *pBegin, int opt, U8 value); +int dhcp_add_u32_option(U8 *pBegin, int opt, U32 value); +int dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize); +int dhcp_add_string_option(U8 *pBegin, int opt, const char *buf); int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal); void dhcp_option_cfg_init(); #ifdef __cplusplus