From 958fbab1930bca666eb85ec5ab28d92f51fb338f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=98=95?= Date: Mon, 15 May 2023 15:44:15 +0800 Subject: [PATCH] =?UTF-8?q?OCT=201.=20DHCP=20=E6=9C=8D=E5=8A=A1=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=87=AA=E5=8A=A8=E8=AF=86=E5=88=ABVLAN=E3=80=81?= =?UTF-8?q?=E5=8D=95=E5=B1=82QinQ,=20=E5=8F=8C=E5=B1=82QinQ=E5=A4=B4?= =?UTF-8?q?=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- srcs/libs/include/network/vlan.h | 32 +- srcs/service/dhcpd/db_interface.c | 50 +-- srcs/service/dhcpd/dhcpd_network.c | 373 ++++++++++++++-------- srcs/service/dhcpd/include/dhcp_network.h | 2 +- srcs/service/dhcpd/lease.c | 4 - 5 files changed, 282 insertions(+), 179 deletions(-) diff --git a/srcs/libs/include/network/vlan.h b/srcs/libs/include/network/vlan.h index 4d591b7..0fa08b0 100644 --- a/srcs/libs/include/network/vlan.h +++ b/srcs/libs/include/network/vlan.h @@ -20,6 +20,12 @@ extern "C" { #define VXLAN_VIN_ID_PACK(x) ((ntohs(x)) & 0xFFF) +typedef enum { + VLAN_NONE, + VLAN_LEVEL1, + VLAN_LEVEL2 +} VLAN_TYPE; + typedef struct vlan_hdr { #if VLAN_SUPPORT U16 id; @@ -27,6 +33,21 @@ typedef struct vlan_hdr { #endif } VLAN_HDR, *PVLAN_HDR; +typedef struct vlan_hdr2 { +#if VLAN_SUPPORT + U16 id1; + U16 h_type; + U16 id2; + U16 type; +#endif +} VLAN_HDR2, *PVLAN_HDR2; + +typedef struct { + struct ethhdr eth; + struct iphdr ip; + struct udphdr udp; +} VLAN_PKG_HDR, *PVLAN_PKG_HDR; + typedef struct { struct ethhdr eth; #if VLAN_SUPPORT @@ -34,7 +55,16 @@ typedef struct { #endif struct iphdr ip; struct udphdr udp; -} VLAN_PKG_HDR, *PVLAN_PKG_HDR; +} VLAN_PKG_HDR1, *PVLAN_PKG_HDR1; + +typedef struct { + struct ethhdr eth; +#if VLAN_SUPPORT + struct vlan_hdr2 vlan; +#endif + struct iphdr ip; + struct udphdr udp; +} VLAN_PKG_HDR2, *PVLAN_PKG_HDR2; #pragma pack(pop) #ifdef __cplusplus diff --git a/srcs/service/dhcpd/db_interface.c b/srcs/service/dhcpd/db_interface.c index 1301f9f..8ab3afc 100644 --- a/srcs/service/dhcpd/db_interface.c +++ b/srcs/service/dhcpd/db_interface.c @@ -15,7 +15,7 @@ // 10小时以上清理无效的预分配IP #define DCHP_STEP_CLEANUP_TIMEOUT (36000) -// Discover 预分配IP 和Request 请求间的超时时间 +// Discover 预分配IP 和 Request 请求间的超时时间 #define DCHP_STEP_REQUEST_TIMEOUT (600000) #define CREATE_LEASE_TABLE() \ @@ -114,7 +114,6 @@ #define LEASE_RELEASE_FMT "DELETE FROM lease WHERE uid = %d AND mac = '%s' AND ip = '%s'" - static int lease_add(PDHCP_REQ pReq, const char *ip, const char *netmask, @@ -400,10 +399,11 @@ int db_get_pre_lease(PDHCP_REQ pReq, PPOOL_CTX pAssign) { const char *pIp = u32_to_str_ip_safe(htonl(pAssign->minAddr)); // 删除预分配IP信息 +#if 0 memset(buf, 0, 2048); sprintf(buf, "DELETE FROM pre_assign WHERE id = %llu;", id); db_sqlite3_sql_exec(buf, NULL, NULL, NULL); - +#endif // 添加租约信息到lease数据库 lease_add(pReq, pIp, pNetmask, pGateway, pDns1, pDns2, pAssign->leaseTime); @@ -415,50 +415,6 @@ int db_get_pre_lease(PDHCP_REQ pReq, PPOOL_CTX pAssign) { return ERR_SUCCESS; } return -ERR_ITEM_UNEXISTS; -#if 0 - rc = db_sqlite3_get_rows(buf, &dbResult, &nRow, &nColumn, NULL); - if (rc == ERR_SUCCESS && nRow > 0 && nColumn > 0) { - char *pNetmask = dbResult[nColumn + 3]; - char *pGateway = dbResult[nColumn + 4]; - char *pDns1 = dbResult[nColumn + 5]; - char *pDns2 = dbResult[nColumn + 6]; - - // minAddr 记录可分配的IP - pAssign->minAddr = ntohl(inet_addr(dbResult[nColumn + 1])); - pAssign->leaseTime = strtoul(dbResult[nColumn + 2], NULL, 10); - - if (strlen(pNetmask) > 0) { - pAssign->netMask = ntohl(inet_addr(pNetmask)); - } - - if (strlen(pGateway) > 0) { - pAssign->gwAddr = ntohl(inet_addr(pGateway)); - } - - if (strlen(pDns1) > 0) { - pAssign->primeDNS = ntohl(inet_addr(pDns1)); - } - - if (strlen(pDns2) > 0) { - pAssign->salveDNS = ntohl(inet_addr(pDns2)); - } - - // 删除预分配IP信息 - memset(buf, 0, 2048); - sprintf(buf, "DELETE FROM pre_assign WHERE id = %s;", dbResult[nColumn]); - //db_sqlite3_sql_exec(buf, NULL, NULL, NULL); - - lease_add(pReq, dbResult[nColumn + 1], pNetmask, pGateway, pDns1, pDns2, pAssign->leaseTime); - - sqlite3_free_table(dbResult); - return ERR_SUCCESS; - } else { - LOG_MOD(error, ZM_DHCP_DB, "No previously records: \n%s\n", buf); - } - - sqlite3_free_table(dbResult); - return -ERR_ITEM_UNEXISTS; -#endif } int db_get_pre_assign(U32 uid, const char *mac, const char *hostname, U32 *preAssign) { diff --git a/srcs/service/dhcpd/dhcpd_network.c b/srcs/service/dhcpd/dhcpd_network.c index 4759492..af2bc8b 100644 --- a/srcs/service/dhcpd/dhcpd_network.c +++ b/srcs/service/dhcpd/dhcpd_network.c @@ -24,6 +24,10 @@ #define MAXIMUM_SNAPLEN (262144) +#define IP_HDR_OFFSET (sizeof(struct ethhdr)) +#define UDP_HDR_OFFSET (sizeof(struct ethhdr) + sizeof(struct iphdr)) +#define DHCP_OFFSET (sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr)) + /* TORs (Top of Rack switch) at Facebook run DHCP relayers, these relayers are responsible for relaying broadcast DHCP traffic (DISCOVERY and SOLICIT @@ -152,6 +156,18 @@ static NIC_INFO g_nicInfo; static uv_udp_t g_uvRawSockReq; static DHCP_WORK_MODE g_dhcpMode; +VLAN_TYPE get_package_vlan_type(void *pBuf) { + U8 *p = (U8 *)pBuf; + + if (p[12] == 0x81 && p[13] == 0x00 && p[16] == 0x81 && p[17] == 0x00) { + return VLAN_LEVEL2; + } else if (p[12] == 0x81 && p[13] == 0x00) { + return VLAN_LEVEL1; + } else { + return VLAN_NONE; + } +} + U32 dhcp_get_default_netmask() { return g_nicInfo.netmask; } @@ -182,93 +198,172 @@ U32 pkg_mmap_tx(U8 *pData, U32 nBytes) { return hdr->tp_len; } -static void fill_package(PDHCP_PACKAGE pRsp, PDHCP_PACKAGE pReq) { - memset(pRsp, 0, MAX_DHCP_PKG_SIZE); +static void add_eth_head(U8 *pRsp, struct ethhdr *pEth, int isBst) { + struct ethhdr *p = (struct ethhdr *)pRsp; // 二层头 - // 目的IP地址 - if (pReq->hdr.ip.saddr != 0) { - memcpy(pRsp->hdr.eth.h_dest, pRsp->hdr.eth.h_source, ETH_ALEN); + // 目的 MAC 地址 + if (!isBst) { + memcpy(p->h_dest, pEth->h_source, ETH_ALEN); } else { - memset(pRsp->hdr.eth.h_dest, 0xFF, ETH_ALEN); + memset(p->h_dest, 0xFF, ETH_ALEN); } - // 源 IP 地址 - memcpy(pRsp->hdr.eth.h_source, g_nicInfo.macAddr, ETH_ALEN); + // 源 MAC 地址 + memcpy(p->h_source, g_nicInfo.macAddr, ETH_ALEN); // protol - pRsp->hdr.eth.h_proto = pReq->hdr.eth.h_proto; + p->h_proto = pEth->h_proto; +} + +static void add_vlan_head(U8 *pRsp, PVLAN_PKG_HDR1 pvHdr) { + PVLAN_PKG_HDR1 p = (PVLAN_PKG_HDR1)pRsp; -#if VLAN_SUPPORT // QinQ 隧道 - pRsp->hdr.vlan.id = pReq->hdr.vlan.id; - pRsp->hdr.vlan.type = pReq->hdr.vlan.type; - // TODO 可能的二层QinQ隧道 -#endif - // IP 头 - memcpy(&pRsp->hdr.ip, &pReq->hdr.ip, sizeof(struct iphdr)); - // TOS - pRsp->hdr.ip.tos = 0; - // 更新源IP - pRsp->hdr.ip.saddr = g_nicInfo.ipAddr; - // 更新目的IP地址,广播255.255.255.255 - if (pReq->hdr.ip.saddr == 0) { - pRsp->hdr.ip.daddr = 0xFFFFFFFF; - } else { - pRsp->hdr.ip.daddr = pReq->hdr.ip.saddr; - } + p->vlan.id = pvHdr->vlan.id; + p->vlan.type = pvHdr->vlan.type; +} +static void add_vlan2_head(U8 *pRsp, PVLAN_PKG_HDR2 pvHdr) { + PVLAN_PKG_HDR2 p = (PVLAN_PKG_HDR2)pRsp; + + // QinQ 隧道 + p->vlan.id1 = pvHdr->vlan.id1; + p->vlan.h_type = pvHdr->vlan.h_type; + p->vlan.id2 = pvHdr->vlan.id2; + p->vlan.type = pvHdr->vlan.type; +} + +static void add_ip_head(struct iphdr *p, struct iphdr *pIp) { + // IP 头 + memcpy(p, pIp, sizeof(struct iphdr)); + // TOS + p->tos = 0; + // 更新源IP + p->saddr = g_nicInfo.ipAddr; + // 更新目的IP地址,广播255.255.255.255 + if (pIp->saddr == 0) { + p->daddr = 0xFFFFFFFF; + } else { + p->daddr = pIp->saddr; + } +} + +static void add_udp_head(struct udphdr *p, struct udphdr *pUdp) { // UDP 头 // 目的端口 - pRsp->hdr.udp.dest = pReq->hdr.udp.source; + p->dest = pUdp->source; // 源端口 - pRsp->hdr.udp.source = pReq->hdr.udp.dest; + p->source = pUdp->dest; +} +static void add_dhcp_common(PDHCP_PROTO p, PDHCP_PROTO pDhcp) { //DHCP 协议 // 返回类型 - pRsp->dhcp.op = BOOTP_REPLY; + p->op = BOOTP_REPLY; // 地址类型长度 - pRsp->dhcp.htype = pReq->dhcp.htype; + p->htype = pDhcp->htype; // 地址长度 - pRsp->dhcp.hlen = pReq->dhcp.hlen; + p->hlen = pDhcp->hlen; // xid - pRsp->dhcp.xid = pReq->dhcp.xid; + p->xid = pDhcp->xid; // 客户端 MAC 地址 - memcpy(pRsp->dhcp.chaddr, pReq->dhcp.chaddr, ETH_ALEN); + memcpy(p->chaddr, pDhcp->chaddr, ETH_ALEN); // DHCP服务端主机名 - memcpy(pRsp->dhcp.sname, g_nicInfo.hostname, MIN(64, strlen(g_nicInfo.hostname))); + memcpy(p->sname, g_nicInfo.hostname, MIN(64, strlen(g_nicInfo.hostname))); // Magic Cookie: DHCP // // memcpy(&pRsp->dhcp.cookie, DHCP_COOKIE_VAL, 4); - pRsp->dhcp.cookie = htonl(DHCP_COOKIE_VAL); + p->cookie = htonl(DHCP_COOKIE_VAL); - pRsp->dhcp.hops = 0; - pRsp->dhcp.secs = 0; - pRsp->dhcp.flags = 0; - pRsp->dhcp.ciaddr = 0; - pRsp->dhcp.siaddr = 0; - pRsp->dhcp.giaddr = 0; + p->hops = 0; + p->secs = 0; + p->flags = 0; + p->ciaddr = 0; + p->siaddr = 0; + p->giaddr = 0; } -static int dhcp_prepare_tx(U8 *pOpt, PDHCP_PACKAGE pRsp) { - U16 csum; - int tolSize; - // 计算包总长度 - tolSize = (int)((pOpt - pRsp->dhcp.options) + 1 + sizeof(DHCP_PACKAGE)); +static PDHCP_PROTO fill_pkg(U8 *pRsp, U8 *pReq) { + U8 *p; + struct ethhdr *pEth = (struct ethhdr *)pReq; + struct iphdr *pIp = NULL; + struct udphdr *pUdp = NULL; + PDHCP_PROTO pDhcp = NULL; + + memset(pRsp, 0, MAX_DHCP_PKG_SIZE); + switch (get_package_vlan_type(pReq)) { + default: + pIp = (struct iphdr *)(pReq + IP_HDR_OFFSET); + pUdp = (struct udphdr *)(UDP_HDR_OFFSET); + pDhcp = (PDHCP_PROTO)((U8 *)pReq + DHCP_OFFSET); + p = pRsp + sizeof(struct ethhdr); + break; + case VLAN_LEVEL1: + pIp = (struct iphdr *)(pReq + IP_HDR_OFFSET + sizeof(VLAN_HDR)); + pUdp = (struct udphdr *)(pReq + UDP_HDR_OFFSET + sizeof(VLAN_HDR)); + pDhcp = (PDHCP_PROTO)((U8 *)pReq + DHCP_OFFSET + sizeof(VLAN_HDR)); + add_vlan_head(pRsp, (PVLAN_PKG_HDR1)pReq); + p = pRsp + sizeof(struct ethhdr) + sizeof(VLAN_HDR); + break; + case VLAN_LEVEL2: + pIp = (struct iphdr *)(pReq + IP_HDR_OFFSET + sizeof(VLAN_HDR2)); + pUdp = (struct udphdr *)(pReq + UDP_HDR_OFFSET + sizeof(VLAN_HDR2)); + pDhcp = (PDHCP_PROTO)((U8 *)pReq + DHCP_OFFSET + sizeof(VLAN_HDR2)); + add_vlan2_head(pRsp, (PVLAN_PKG_HDR2)pReq); + p = pRsp + sizeof(struct ethhdr) + sizeof(VLAN_HDR2); + break; + } + + add_eth_head(pRsp, pEth, (pIp->saddr == 0) ? TRUE : FALSE); + add_ip_head((struct iphdr *)p, pIp); + p += sizeof(struct iphdr); + add_udp_head((struct udphdr *)p, pUdp); + p += sizeof(struct udphdr); + add_dhcp_common((PDHCP_PROTO)p, pDhcp); + + return (PDHCP_PROTO)p; +} + +static int dhcp_prepare_tx(U8 *pRsp, U32 optSize) { + struct iphdr *pIp = NULL; + struct udphdr *pUdp = NULL; + U16 csum; + U32 tolSize; + + switch (get_package_vlan_type(pRsp)) { + default: + pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET); + pUdp = (struct udphdr *)(UDP_HDR_OFFSET); + // 计算包总长度 + tolSize = optSize + sizeof(DHCP_PROTO) + DHCP_OFFSET; + break; + case VLAN_LEVEL1: + pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET + sizeof(VLAN_HDR)); + pUdp = (struct udphdr *)(pRsp + UDP_HDR_OFFSET + sizeof(VLAN_HDR)); + // 计算包总长度 + tolSize = optSize + sizeof(DHCP_PROTO) + DHCP_OFFSET + sizeof(VLAN_HDR); + break; + case VLAN_LEVEL2: + pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET + sizeof(VLAN_HDR2)); + pUdp = (struct udphdr *)(pRsp + UDP_HDR_OFFSET + sizeof(VLAN_HDR2)); + // 计算包总长度 + tolSize = optSize + sizeof(DHCP_PROTO) + DHCP_OFFSET + sizeof(VLAN_HDR2); + break; + } // 计算 IP 数据长度 - pRsp->hdr.ip.tot_len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr)); + pIp->tot_len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr)); // 计算 UDP 数据长度 - pRsp->hdr.udp.len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr) - sizeof(struct iphdr)); + pUdp->len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr) - sizeof(struct iphdr)); // 计算 IP 校验和 - csum = htons(ip_checksum((unsigned char *)&pRsp->hdr.ip)); - pRsp->hdr.ip.check = htons(csum); + csum = htons(ip_checksum((unsigned char *)pIp)); + pIp->check = htons(csum); // 计算 UDP 校验和 - csum = htons(udp_checksum(pRsp->hdr.ip.saddr, pRsp->hdr.ip.daddr, (unsigned char *)&pRsp->hdr.udp)); - pRsp->hdr.udp.check = htons(csum); + csum = htons(udp_checksum(pIp->saddr, pIp->daddr, (unsigned char *)pUdp)); + pUdp->check = htons(csum); - LOG_MOD(trace, ZM_DHCP_NET, "OPTIONS size: %ld\n", (intptr_t)(pOpt - pRsp->dhcp.options) + 1); LOG_MOD(trace, ZM_DHCP_NET, "Total size: %d\n", tolSize); // 发送数据 @@ -280,43 +375,45 @@ static int dhcp_prepare_tx(U8 *pOpt, PDHCP_PACKAGE pRsp) { return ERR_SUCCESS; } -static int dhcp_resp_nack(PDHCP_PACKAGE pReq) { - U8 *pOpt; - PDHCP_PACKAGE pRsp = get_pkg_free_buf(); +static int dhcp_resp_nack(void *pReq) { + U8 *pOpt; + PDHCP_PROTO pDhcp = NULL; + U8 *pRsp = get_pkg_free_buf(); if (pRsp == NULL) { LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE); return -ERR_MALLOC_MEMORY; } - fill_package(pRsp, pReq); + pDhcp = fill_pkg(pRsp, (U8 *)pReq); // DHCP Options - pOpt = pRsp->dhcp.options; + pOpt = pDhcp->options; // DHCP 消息类型 pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_NAK); *pOpt = OPT_END; - return dhcp_prepare_tx(pOpt, pRsp); + return dhcp_prepare_tx(pRsp, (int)((pOpt - pDhcp->options) + 1)); } -static int dhcp_resp_ack(PDHCP_PACKAGE pReq, PPOOL_CTX pIpInfo) { - U8 *pOpt; - PDHCP_PACKAGE pRsp = get_pkg_free_buf(); +static int dhcp_resp_ack(void *pReq, PPOOL_CTX pIpInfo) { + U8 *pOpt; + PDHCP_PROTO pDhcp = NULL; + U8 *pRsp = get_pkg_free_buf(); if (pRsp == NULL) { LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE); return -ERR_MALLOC_MEMORY; } - fill_package(pRsp, pReq); + pDhcp = fill_pkg((U8 *)pRsp, (U8 *)pReq); // 分配的 IP 地址 - pRsp->dhcp.yiaddr = htonl(pIpInfo->minAddr); + pDhcp->yiaddr = htonl(pIpInfo->minAddr); // DHCP Options - pOpt = pRsp->dhcp.options; + pOpt = pDhcp->options; // DHCP 消息类型 pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_ACK); @@ -346,24 +443,26 @@ static int dhcp_resp_ack(PDHCP_PACKAGE pReq, PPOOL_CTX pIpInfo) { pOpt += dhcp_add_string_option(pOpt, OPT_DOMAINNAME, "workgroup"); *pOpt = OPT_END; - return dhcp_prepare_tx(pOpt, pRsp); + return dhcp_prepare_tx(pRsp, (int)((pOpt - pDhcp->options) + 1)); } -static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PPOOL_CTX pIpInfo, U32 ip) { - U8 *pOpt; - PDHCP_PACKAGE pRsp = get_pkg_free_buf(); +static int dhcp_resp_offer(void *pReq, PPOOL_CTX pIpInfo, U32 ip) { + U8 *pOpt; + PDHCP_PROTO pDhcp = NULL; + U8 *pRsp = get_pkg_free_buf(); if (pRsp == NULL) { LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE); return -ERR_MALLOC_MEMORY; } - fill_package(pRsp, pReq); + pDhcp = fill_pkg(pRsp, (U8 *)pReq); + // 分配的 IP 地址 - pRsp->dhcp.yiaddr = htonl(ip); + pDhcp->yiaddr = htonl(ip); // DHCP Options - pOpt = pRsp->dhcp.options; + pOpt = pDhcp->options; // DHCP 消息类型 pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_OFFER); @@ -393,73 +492,100 @@ static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PPOOL_CTX pIpInfo, U32 ip) { pOpt += dhcp_add_string_option(pOpt, OPT_DOMAINNAME, "workgroup"); *pOpt = OPT_END; - return dhcp_prepare_tx(pOpt, pRsp); + return dhcp_prepare_tx(pRsp, (int)((pOpt - pDhcp->options) + 1)); +} + +static PDHCP_PROTO get_dhcp_date(void *pBuf, U32 *pOptSize, U32 bufSize) { + U8 *p = (U8 *)pBuf; + U32 hdrCom = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr); + + if (p[12] == 0x81 && p[13] == 0x00 && p[16] == 0x81 && p[17] == 0x00) { + *pOptSize = bufSize - hdrCom - sizeof(DHCP_PROTO) - sizeof(VLAN_HDR2); + return (PDHCP_PROTO)(p + hdrCom + 8); + } else if (p[12] == 0x81 && p[13] == 0x00) { + *pOptSize = bufSize - hdrCom - sizeof(DHCP_PROTO) - sizeof(VLAN_HDR); + return (PDHCP_PROTO)(p + hdrCom + 4); + } else { + *pOptSize = bufSize - hdrCom - sizeof(DHCP_PROTO); + return (PDHCP_PROTO)(p + hdrCom); + } +} + +U32 dhcp_get_uid(void *pBuf) { + U8 *p = (U8 *)pBuf; + PVLAN_HDR pQinQ = (PVLAN_HDR)(p + sizeof(struct ethhdr)); + + if (p[12] == 0x81 && p[13] == 0x00 && p[16] == 0x81 && p[17] == 0x00) { + PVLAN_HDR2 pHdr = (PVLAN_HDR2)pQinQ; + return (pHdr->id1 & 0x0FFF) >> 12 | (pHdr->id2 & 0x0FFF) << 12; + } else if (p[12] == 0x81 && p[13] == 0x00) { + return (pQinQ->id & 0x0FFF); + } else { + return 0; + } } static void on_sock_recv(uv_work_t *req) { + U32 optSize = 0; char macStr[20] = {0}; U32 ip; PPOOL_CTX pIpInfo; 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); + PPKG_PROCESS_INFO pWork = (PPKG_PROCESS_INFO)req->data; + PDHCP_PROTO pkg = get_dhcp_date(pWork->pPkgBase, &optSize, pWork->nSize); + struct iphdr *pIpHdr = (struct iphdr *)((U8 *)pkg - sizeof(struct iphdr) - sizeof(struct udphdr)); //sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", macStr[0], macStr[1], macStr[2], macStr[3], macStr[4], macStr[5]); // Check op flag - if (pkg->dhcp.op != BOOTP_REQUEST) { - LOG_MOD(error, ZM_DHCP_NET, "Error message op code %d\n", pkg->dhcp.op); + if (pkg->op != BOOTP_REQUEST) { + LOG_MOD(error, ZM_DHCP_NET, "Error message op code %d\n", pkg->op); LOG_MSG_HEX(error, pkg, pWork->nSize); return; } // 获取消息类型 - ret = dhcp_get_option(OPT_MESSAGETYPE, pkg->dhcp.options, optSize, &optMsg); + ret = dhcp_get_option(OPT_MESSAGETYPE, pkg->options, optSize, &optMsg); if (ret != ERR_SUCCESS) { LOG_MOD(error, ZM_DHCP_NET, "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); -#if VLAN_SUPPORT - reqDhcp.uid = VLAN_VNI_ID(pkg->hdr.vlan.id); -#else - reqDhcp.uid = 0; -#endif + reqDhcp.unicast = pkg->flags != 0 ? TRUE : FALSE; + reqDhcp.xid = DHCP_XID(pkg->xid); + reqDhcp.uid = dhcp_get_uid(pWork->pPkgBase); reqDhcp.serverAddr = g_nicInfo.ipAddr; - reqDhcp.cliAddr = ntohl(pkg->dhcp.ciaddr); - memcpy(reqDhcp.cliMac, pkg->dhcp.chaddr, ETH_ALEN); + reqDhcp.cliAddr = ntohl(pkg->ciaddr); + memcpy(reqDhcp.cliMac, pkg->chaddr, ETH_ALEN); MAC_TO_STR(reqDhcp.cliMac, macStr); switch (*optMsg.pValue) { - case DHCP_MSG_DISCOVER: + case DHCP_MSG_DSCIOVER: // region DHCP Discover 处理 - ret = dhcp_get_option(OPT_REQUESTEDIPADDR, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_REQUESTEDIPADDR, pkg->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); + ret = dhcp_get_option(OPT_IPADDRLEASE, pkg->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); + ret = dhcp_get_option(OPT_CLIENTID, pkg->options, optSize, &opt); if (ret == ERR_SUCCESS) { strncpy(reqDhcp.clientId, (char *)opt.pValue, MIN((int)opt.len, 256)); } - ret = dhcp_get_option(OPT_VENDORCLASSID, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_VENDORCLASSID, pkg->options, optSize, &opt); if (ret == ERR_SUCCESS) { strncpy(reqDhcp.vendorClassId, (char *)opt.pValue, MIN((int)opt.len, 256)); } - ret = dhcp_get_option(OPT_HOSTNAME, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_HOSTNAME, pkg->options, optSize, &opt); if (ret == ERR_SUCCESS) { strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256)); } @@ -470,7 +596,7 @@ static void on_sock_recv(uv_work_t *req) { LOG_MOD(debug, ZM_DHCP_NET, "User %u DHCP prepare assign ipaddress: [%s(%s)] --> %s\n", reqDhcp.uid, macStr, reqDhcp.hostName, u32_to_str_ip(ntohl(ip))); - ret = dhcp_resp_offer(pkg, pIpInfo, ip); + ret = dhcp_resp_offer(pWork->pPkgBase, pIpInfo, ip); if (ret != ERR_SUCCESS) { LOG_MOD(error, ZM_DHCP_NET, "Send Offer error: %d\n", ret); } @@ -479,7 +605,7 @@ static void on_sock_recv(uv_work_t *req) { reqDhcp.uid, macStr, reqDhcp.hostName, getErrorEnumNameString(ret)); // Send NACK - ret = dhcp_resp_nack(pkg); + ret = dhcp_resp_nack(pWork->pPkgBase); } if (ret != ERR_SUCCESS) { @@ -490,18 +616,18 @@ static void on_sock_recv(uv_work_t *req) { case DHCP_MSG_REQUEST: // region DHCP Request 处理 // 客户端请求的服务器 - ret = dhcp_get_option(OPT_SERVERID, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_SERVERID, pkg->options, optSize, &opt); if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) { reqDhcp.reqServer = ntohl(*((U32 *)opt.pValue)); } else { // Request 服务器IP可以取目的 IP 地址 - if (pkg->hdr.ip.saddr != 0) { - reqDhcp.reqServer = ntohl(pkg->hdr.ip.daddr); + if (pIpHdr->saddr != 0) { + reqDhcp.reqServer = ntohl(pIpHdr->daddr); } } // 客户端请求的IP - ret = dhcp_get_option(OPT_REQUESTEDIPADDR, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_REQUESTEDIPADDR, pkg->options, optSize, &opt); if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) { reqDhcp.reqIpAddr = ntohl(*((U32 *)opt.pValue)); } else { @@ -509,7 +635,7 @@ static void on_sock_recv(uv_work_t *req) { } // 客户端主机名 - ret = dhcp_get_option(OPT_HOSTNAME, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_HOSTNAME, pkg->options, optSize, &opt); if (ret == ERR_SUCCESS) { strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256)); } @@ -529,12 +655,12 @@ static void on_sock_recv(uv_work_t *req) { LOG_MOD(debug, ZM_DHCP_NET, "User %u DHCP assign ipaddress: [%s(%s)] --> %s\n", reqDhcp.uid, macStr, reqDhcp.hostName, u32_to_str_ip(ntohl(ctx.minAddr))); - ret = dhcp_resp_ack(pkg, &ctx); + ret = dhcp_resp_ack(pWork->pPkgBase, &ctx); } else { LOG_MOD(error, ZM_DHCP_NET, "DHCP assign ipaddress error: User %u [%s(%s)] resion %s\n", reqDhcp.uid, macStr, reqDhcp.hostName, getErrorEnumNameString(ret)); // Send NACK - ret = dhcp_resp_nack(pkg); + ret = dhcp_resp_nack(pWork->pPkgBase); } if (ret != ERR_SUCCESS) { @@ -546,17 +672,17 @@ static void on_sock_recv(uv_work_t *req) { case DHCP_MSG_RELEASE: // region DHCP Release 处理 // 客户端请求的服务器 - ret = dhcp_get_option(OPT_SERVERID, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_SERVERID, pkg->options, optSize, &opt); if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) { reqDhcp.reqServer = ntohl(*((U32 *)opt.pValue)); } else { // Request 服务器IP可以取目的 IP 地址 - if (pkg->hdr.ip.saddr != 0) { - reqDhcp.reqServer = ntohl(pkg->hdr.ip.saddr); + if (pIpHdr->saddr != 0) { + reqDhcp.reqServer = ntohl(pIpHdr->saddr); } } - reqDhcp.reqIpAddr = ntohl(pkg->dhcp.ciaddr); + reqDhcp.reqIpAddr = ntohl(pkg->ciaddr); lease_release(&reqDhcp); LOG_MOD(debug, ZM_DHCP_NET, "User %u DHCP release lease: [%s(%s)] --> %s\n", reqDhcp.uid, macStr, @@ -565,7 +691,7 @@ static void on_sock_recv(uv_work_t *req) { break; case DHCP_MSG_INFORM: // 客户端主机名 - ret = dhcp_get_option(OPT_HOSTNAME, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_HOSTNAME, pkg->options, optSize, &opt); if (ret == ERR_SUCCESS) { strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256)); } @@ -591,14 +717,14 @@ static void on_sock_recv(uv_work_t *req) { break; } - //dhcp_option_prase(optMsg, pkg->dhcp.options, pWork->nSize - sizeof(DHCP_PACKAGE)); + //dhcp_option_prase(optMsg, pkg->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->hdr.vlan.id), DHCP_XID(pkg->dhcp.xid)); + //LOG_MSG(info, "vni: %d, xid: 0x%08X\n", VLAN_VNI_ID(pkg->hdr.vlan.id), DHCP_XID(pkg->xid)); #if 0 LOG_MOD(info, ZM_DHCP_NET, "vlan = %u\n", VXLAN_VIN_ID_PACK(pkg->hdr.vlan.id)); - LOG_MSG(info, "xid: 0x%08X\n", ntohl(pkg->dhcp.xid)); + LOG_MSG(info, "xid: 0x%08X\n", ntohl(pkg->xid)); LOG_MSG(info, "dest mac: %02X:%02X:%02X:%02X:%02X:%02X\n", pkg->hdr.eth.h_dest[0], @@ -609,16 +735,16 @@ static void on_sock_recv(uv_work_t *req) { pkg->hdr.eth.h_dest[5]); LOG_MSG(info, "client mac: %02X:%02X:%02X:%02X:%02X:%02X\n", - pkg->dhcp.chaddr[0], - pkg->dhcp.chaddr[1], - pkg->dhcp.chaddr[2], - pkg->dhcp.chaddr[3], - pkg->dhcp.chaddr[4], - pkg->dhcp.chaddr[5]); + pkg->chaddr[0], + pkg->chaddr[1], + pkg->chaddr[2], + pkg->chaddr[3], + pkg->chaddr[4], + pkg->chaddr[5]); #endif } -static void after_msg_recv(uv_work_t *req, int status) { +static void after_msg_recv(uv_work_t *req, int UNUSED(status)) { PPKG_PROCESS_INFO pInfo = (PPKG_PROCESS_INFO)req->data; PPKG_MSG pMsg = (PPKG_MSG)pInfo->pData; @@ -662,19 +788,14 @@ void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) { pMsg->nf = pbd->h1.num_pkts; ppd = (struct tpacket3_hdr *)((uint8_t *)pbd + pbd->h1.offset_to_first_pkt); for (i = 0; i < pbd->h1.num_pkts; i++) { - PDHCP_PACKAGE pkg; - U32 uid; + U32 uid; pMsg->pPkgInfo[i].pPkgBase = ((uint8_t *)ppd + ppd->tp_mac); pMsg->pPkgInfo[i].nSize = ppd->tp_snaplen; pMsg->pPkgInfo[i].uvWork.data = &pMsg->pPkgInfo[i]; pMsg->pPkgInfo[i].pData = pMsg; if (g_dhcpMode == MODE_DHCP_SERVER) { -#if VLAN_SUPPORT - pkg = (PDHCP_PACKAGE)pMsg->pPkgInfo[i].pPkgBase; - uid = VLAN_VNI_ID(pkg->hdr.vlan.id); -#else - uid = 0; -#endif + uid = dhcp_get_uid(pMsg->pPkgInfo[i].pPkgBase); + pMsg->pPkgInfo[i].pUser = dhcp_user_create(uid); // LOG_MOD(trace, ZM_DHCP_NET, ">>> User %u xid %08X addr %p\n", uid, DHCP_XID(pkg->dhcp.xid), diff --git a/srcs/service/dhcpd/include/dhcp_network.h b/srcs/service/dhcpd/include/dhcp_network.h index 59a0739..ff9e5a3 100644 --- a/srcs/service/dhcpd/include/dhcp_network.h +++ b/srcs/service/dhcpd/include/dhcp_network.h @@ -53,7 +53,7 @@ typedef struct { #pragma pack(1) typedef struct { - VLAN_PKG_HDR hdr; + VLAN_PKG_HDR1 hdr; DHCP_PROTO dhcp; } DHCP_PACKAGE, *PDHCP_PACKAGE; diff --git a/srcs/service/dhcpd/lease.c b/srcs/service/dhcpd/lease.c index a713f99..84c95e0 100644 --- a/srcs/service/dhcpd/lease.c +++ b/srcs/service/dhcpd/lease.c @@ -95,18 +95,14 @@ int pre_alloc_dhcp_res(PDHCP_REQ pReq, PDHCP_USER pUser, U32 *pOutIp, PPOOL_CTX addr = pPool->minAddr; do { PLOCK_IP pLock; - HASH_FIND_INT(pUser->plockIp, &addr, pLock); - // 该 IP 可用 if (pLock == NULL) { if (db_ip_is_pre_assign(pReq->uid, addr) == FALSE) { usr_lease_lock_ip(pUser, addr); *pOutIp = addr; *pOutPool = pPool; - db_add_pre_assign(pReq, addr, pPool); - return ERR_SUCCESS; } }