From e6ea44dd190d49ae2bf82e933a8d3d21d09720cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=98=95?= Date: Tue, 16 May 2023 15:00:37 +0800 Subject: [PATCH] =?UTF-8?q?OCT=201.=20DHCP=20=E6=B5=8B=E8=AF=95=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E6=94=AF=E6=8C=81=E5=8F=8C=E5=B1=82VLAN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dhcp_tools/CMakeLists.txt | 1 + dhcp_tools/detail_wnd.c | 142 +++++++++++++---------- dhcp_tools/main.h | 2 + dhcp_tools/main_wnd.c | 16 +-- dhcp_tools/uv_rawsocket.c | 233 ++++++++++++++++++++++---------------- 5 files changed, 233 insertions(+), 161 deletions(-) diff --git a/dhcp_tools/CMakeLists.txt b/dhcp_tools/CMakeLists.txt index 0d0e7a5..8fc90c5 100644 --- a/dhcp_tools/CMakeLists.txt +++ b/dhcp_tools/CMakeLists.txt @@ -3,6 +3,7 @@ SET(PROJECT_TARGET dhcp_tools) PROJECT(${PROJECT_TARGET} LANGUAGES C) FIND_PACKAGE(PkgConfig REQUIRED) +# sudo apt install libgtk-3-dev PKG_CHECK_MODULES(GTK3 REQUIRED gtk+-3.0) INCLUDE_DIRECTORIES(${GTK3_INCLUDE_DIRS}) LINK_DIRECTORIES(${GTK3_LIBRARY_DIRS}) diff --git a/dhcp_tools/detail_wnd.c b/dhcp_tools/detail_wnd.c index 8395fc9..d054f1a 100644 --- a/dhcp_tools/detail_wnd.c +++ b/dhcp_tools/detail_wnd.c @@ -97,10 +97,10 @@ static void add_dhcp_tree_colums(GtkWidget *treeView) { break; \ case 3: \ do { \ - U32 *pIp = (U32 *)(val); \ + U32 *pIps = (U32 *)(val); \ gtk_tree_store_append(store, &iterOpt, &iterSub); \ s = sdsempty(); \ - sprintf(s, "%s", u32_to_str_ip(*pIp)); \ + sprintf(s, "%s", u32_to_str_ip(*pIps)); \ gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, s, -1); \ sdsfree(s); \ count_flag += 4; \ @@ -129,14 +129,19 @@ static void add_dhcp_tree_colums(GtkWidget *treeView) { } \ } while (0) -static void create_dhcp_tree_mode(PDHCP_PACKAGE p, U32 nBytes, GtkWidget *treeView) { +static void create_dhcp_tree_mode(U8 *pkg, U32 nBytes, GtkWidget *treeView) { + PVLAN_HDR pvLan; + PVLAN_HDR2 pvLan2; // 填充右上侧 TreeView 协议数据 - sds s; - GtkTreeIter iter, iterSub, iterOpt; - GtkTreeStore *store = NULL; //gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_STRING); - const char *itemTitle[] = {"Ethernet II", "802.1Q Virtual LAN", "IP Version 4", "UDP", "DHCP"}; - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeView)); - //GtkTreeStore *store = GTK_TREE_STORE(); + sds s; + GtkTreeIter iter, iterSub, iterOpt; + GtkTreeStore *store = NULL; //gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_STRING); + const char *itemTitle[] = {"Ethernet II", "802.1Q Virtual LAN", "IP Version 4", "UDP", "DHCP"}; + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeView)); + struct ethhdr *pEth = (struct ethhdr *)pkg; + struct iphdr *pIp = NULL; + struct udphdr *pUdp = NULL; + PDHCP_PROTO pDhcp = NULL; if (model) { store = GTK_TREE_STORE(model); @@ -153,55 +158,78 @@ static void create_dhcp_tree_mode(PDHCP_PACKAGE p, U32 nBytes, GtkWidget *treeVi // 添加 Ethernet II 头相关内容 s = sdsempty(); - MAC_TO_STR(p->hdr.eth.h_dest, s); + MAC_TO_STR(pEth->h_dest, s); ADD_SUB_STRING("Destination", s); sdsfree(s); s = sdsempty(); - MAC_TO_STR(p->hdr.eth.h_source, s); + MAC_TO_STR(pEth->h_source, s); ADD_SUB_STRING("Source", s); sdsfree(s); -#if VLAN_SUPPORT - // 添加 VLan 头相关内容 - gtk_tree_store_append(store, &iter, NULL); - gtk_tree_store_set(store, &iter, 0, itemTitle[1], 1, "", -1); - ADD_SUB_INT("ID", "%u", VLAN_VNI_ID(p->hdr.vlan.id)); - ADD_SUB_INT("Type", "0x%04X", ntohs(p->hdr.vlan.type)); -#endif + switch (get_package_vlan_type(pkg)) { + default: + pIp = (struct iphdr *)(pkg + IP_HDR_OFFSET); + pUdp = (struct udphdr *)(UDP_HDR_OFFSET); + pDhcp = (PDHCP_PROTO)((U8 *)pkg + DHCP_OFFSET); + break; + case VLAN_LEVEL1: + pvLan = (PVLAN_HDR)(pkg + sizeof(struct ethhdr)); + pIp = (struct iphdr *)(pkg + IP_HDR_OFFSET + sizeof(VLAN_HDR)); + pUdp = (struct udphdr *)(pkg + UDP_HDR_OFFSET + sizeof(VLAN_HDR)); + pDhcp = (PDHCP_PROTO)((U8 *)pkg + DHCP_OFFSET + sizeof(VLAN_HDR)); + // 添加 VLan 头相关内容 + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set(store, &iter, 0, itemTitle[1], 1, "", -1); + ADD_SUB_INT("ID", "%u", VLAN_VNI_ID(pvLan->id)); + ADD_SUB_INT("Type", "0x%04X", ntohs(pvLan->type)); + break; + case VLAN_LEVEL2: + pvLan2 = (PVLAN_HDR2)(pkg + sizeof(struct ethhdr)); + pIp = (struct iphdr *)(pkg + IP_HDR_OFFSET + sizeof(VLAN_HDR2)); + pUdp = (struct udphdr *)(pkg + UDP_HDR_OFFSET + sizeof(VLAN_HDR2)); + pDhcp = (PDHCP_PROTO)((U8 *)pkg + DHCP_OFFSET + sizeof(VLAN_HDR2)); + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set(store, &iter, 0, itemTitle[1], 1, "", -1); + ADD_SUB_INT("ID Low", "%u", VLAN_VNI_ID(pvLan2->id1)); + ADD_SUB_INT("Type", "0x%04X", ntohs(pvLan2->h_type)); + ADD_SUB_INT("ID Hight", "%u", VLAN_VNI_ID(pvLan2->id2)); + ADD_SUB_INT("Type", "0x%04X", ntohs(pvLan2->type)); + break; + } // 添加 IP 头 gtk_tree_store_append(store, &iter, NULL); gtk_tree_store_set(store, &iter, 0, itemTitle[2], 1, "", -1); - ADD_SUB_INT("Version", "%u", p->hdr.ip.version); + ADD_SUB_INT("Version", "%u", pIp->version); s = sdsempty(); - sprintf(s, "%u %s (%u)", p->hdr.ip.ihl * 4, "bytes", p->hdr.ip.ihl); + sprintf(s, "%u %s (%u)", pIp->ihl * 4, "bytes", pIp->ihl); ADD_SUB_STRING("Header Length", s); sdsfree(s); - ADD_SUB_INT("Differentiated Services Field", "0x%02X", p->hdr.ip.tos); - ADD_SUB_INT("Total Length", "%u", ntohs(p->hdr.ip.tot_len)); - ADD_SUB_INT("Identification", "0x%04X", ntohs(p->hdr.ip.id)); - ADD_SUB_INT("Flags", "0x%04X", ntohs(p->hdr.ip.frag_off)); - ADD_SUB_INT("Time to live", "%u", p->hdr.ip.ttl); + ADD_SUB_INT("Differentiated Services Field", "0x%02X", pIp->tos); + ADD_SUB_INT("Total Length", "%u", ntohs(pIp->tot_len)); + ADD_SUB_INT("Identification", "0x%04X", ntohs(pIp->id)); + ADD_SUB_INT("Flags", "0x%04X", ntohs(pIp->frag_off)); + ADD_SUB_INT("Time to live", "%u", pIp->ttl); ADD_SUB_STRING("Protocol", "UDP"); - ADD_SUB_INT("Header Checksum", "0x%04X", ntohs(p->hdr.ip.check)); - ADD_SUB_STRING("Source", inet_ntoa(*(struct in_addr *)&p->hdr.ip.saddr)); - ADD_SUB_STRING("Destination", inet_ntoa(*(struct in_addr *)&p->hdr.ip.daddr)); + ADD_SUB_INT("Header Checksum", "0x%04X", ntohs(pIp->check)); + ADD_SUB_STRING("Source", inet_ntoa(*(struct in_addr *)&pIp->saddr)); + ADD_SUB_STRING("Destination", inet_ntoa(*(struct in_addr *)&pIp->daddr)); // 添加 UDP 头 gtk_tree_store_append(store, &iter, NULL); gtk_tree_store_set(store, &iter, 0, itemTitle[3], 1, "", -1); - ADD_SUB_INT("Source Port", "%u", ntohs(p->hdr.udp.source)); - ADD_SUB_INT("Destination Port", "%u", ntohs(p->hdr.udp.dest)); - ADD_SUB_INT("Length", "%u", ntohs(p->hdr.udp.len)); - ADD_SUB_INT("Checksum", "0x%04X", ntohs(p->hdr.udp.check)); + ADD_SUB_INT("Source Port", "%u", ntohs(pUdp->source)); + ADD_SUB_INT("Destination Port", "%u", ntohs(pUdp->dest)); + ADD_SUB_INT("Length", "%u", ntohs(pUdp->len)); + ADD_SUB_INT("Checksum", "0x%04X", ntohs(pUdp->check)); // 添加 DHCP 内容 gtk_tree_store_append(store, &iter, NULL); gtk_tree_store_set(store, &iter, 0, itemTitle[4], 1, "", -1); - switch (p->dhcp.op) { + switch (pDhcp->op) { case 1: ADD_SUB_STRING("Message Type", "Boot Request"); break; @@ -211,43 +239,43 @@ static void create_dhcp_tree_mode(PDHCP_PACKAGE p, U32 nBytes, GtkWidget *treeVi default: ADD_SUB_STRING("Message Type", "Unknown"); } - switch (p->dhcp.htype) { + switch (pDhcp->htype) { case 1: ADD_SUB_STRING("Hardware Type", "Ethernet"); break; default: ADD_SUB_STRING("Hardware Type", "Unknown"); } - ADD_SUB_INT("Hardware address length", "%u", p->dhcp.hlen); - ADD_SUB_INT("Hops", "%u", p->dhcp.hops); - ADD_SUB_INT("Transaction ID", "0x%08X", p->dhcp.xid); - ADD_SUB_INT("Seconds elapsed", "%u", p->dhcp.secs); - ADD_SUB_INT("Bootp flags", "0x%04X", p->dhcp.flags); - ADD_SUB_STRING("Client IP address", inet_ntoa(*(struct in_addr *)&p->dhcp.ciaddr)); - ADD_SUB_STRING("Your(client) IP address", inet_ntoa(*(struct in_addr *)&p->dhcp.yiaddr)); - ADD_SUB_STRING("Next server IP address", inet_ntoa(*(struct in_addr *)&p->dhcp.siaddr)); - ADD_SUB_STRING("Relay agent IP address", inet_ntoa(*(struct in_addr *)&p->dhcp.giaddr)); + ADD_SUB_INT("Hardware address length", "%u", pDhcp->hlen); + ADD_SUB_INT("Hops", "%u", pDhcp->hops); + ADD_SUB_INT("Transaction ID", "0x%08X", pDhcp->xid); + ADD_SUB_INT("Seconds elapsed", "%u", pDhcp->secs); + ADD_SUB_INT("Bootp flags", "0x%04X", pDhcp->flags); + ADD_SUB_STRING("Client IP address", inet_ntoa(*(struct in_addr *)&pDhcp->ciaddr)); + ADD_SUB_STRING("Your(client) IP address", inet_ntoa(*(struct in_addr *)&pDhcp->yiaddr)); + ADD_SUB_STRING("Next server IP address", inet_ntoa(*(struct in_addr *)&pDhcp->siaddr)); + ADD_SUB_STRING("Relay agent IP address", inet_ntoa(*(struct in_addr *)&pDhcp->giaddr)); s = sdsempty(); - MAC_TO_STR(p->dhcp.chaddr, s); + MAC_TO_STR(pDhcp->chaddr, s); ADD_SUB_STRING("Client MAC address", s); sdsfree(s); - if (strlen((char *)p->dhcp.sname) > 0) { - ADD_SUB_STRING("Server host name", p->dhcp.sname); + if (strlen((char *)pDhcp->sname) > 0) { + ADD_SUB_STRING("Server host name", pDhcp->sname); } else { ADD_SUB_STRING("Server host name", "not given"); } - if (strlen((char *)p->dhcp.file) > 0) { - ADD_SUB_STRING("Boot file name", p->dhcp.file); + if (strlen((char *)pDhcp->file) > 0) { + ADD_SUB_STRING("Boot file name", pDhcp->file); } else { ADD_SUB_STRING("Boot file name", "not given"); } ADD_SUB_STRING("Magic cookie", "DHCP"); - U8 *opPointer, *optEnd = (U8 *)p + nBytes; - opPointer = p->dhcp.options; + U8 *opPointer, *optEnd = (U8 *)pkg + nBytes; + opPointer = pDhcp->options; while (*opPointer && opPointer < optEnd) { if (*opPointer == OPT_END) { ADD_SUB_STRING("Option(255)", "End"); @@ -291,21 +319,21 @@ static gboolean upgrade_statusbar_proc(gpointer user_data) { (pInfo->pReqBuf.tm.tv_sec * 1000000 + pInfo->pReqBuf.tm.tv_usec)); if (pInfo->pAckBuf.p) { - PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pInfo->pAckBuf.p; - U32 optSize = pInfo->pAckBuf.buf_size - sizeof(DHCP_PACKAGE); - pIp = u32_to_str_ip_safe(pkg->dhcp.yiaddr); + U32 optSize = 0; + PDHCP_PROTO pDhcp = get_dhcp_date(pInfo->pAckBuf.p, &optSize, pInfo->pAckBuf.buf_size); + pIp = u32_to_str_ip_safe(pDhcp->yiaddr); - ret = dhcp_get_option(OPT_NETMASK, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_NETMASK, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) { pNetmask = u32_to_str_ip_safe(*((U32 *)opt.pValue)); } - ret = dhcp_get_option(OPT_ROUTER, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_ROUTER, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) { pGw = u32_to_str_ip_safe(*((U32 *)opt.pValue)); } - ret = dhcp_get_option(OPT_DNS, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_DNS, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS && opt.len >= sizeof(U32)) { U32 *pVal = (U32 *)opt.pValue; pDns1 = u32_to_str_ip_safe(*pVal); @@ -424,7 +452,7 @@ void details_wnd_show(PDHCP_INFO pInfo) { // 填充 TreeView add_dhcp_tree_colums(g_ptvDHcp[i]); - create_dhcp_tree_mode((PDHCP_PACKAGE)g_HexBuf[i]->p, g_HexBuf[i]->buf_size, g_ptvDHcp[i]); + create_dhcp_tree_mode(g_HexBuf[i]->p, g_HexBuf[i]->buf_size, g_ptvDHcp[i]); } upgrade_statusbar_proc(pInfo); diff --git a/dhcp_tools/main.h b/dhcp_tools/main.h index 4a72ce9..3b22ebe 100644 --- a/dhcp_tools/main.h +++ b/dhcp_tools/main.h @@ -8,6 +8,7 @@ #include #include "uthash/uthash.h" #include "rfc2131.h" +#include "service/dhcpd.h" #define ADD_LOG_MSG(level, m, format, ...) \ (format_log_msg(level, (m), "[%s] - %s(%d):" format, basename_v2(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)) @@ -95,4 +96,5 @@ void statis_wnd_create(GtkBuilder *builder); void write_log_msg(const char *pMsg, int mode); GtkBuilder *get_main_builder(); void format_log_msg(int level, int mode, const char *pMsg, ...); +PDHCP_PROTO get_dhcp_date(void *pBuf, U32 *pOptSize, U32 bufSize); #endif //VCPE_MAIN_H diff --git a/dhcp_tools/main_wnd.c b/dhcp_tools/main_wnd.c index e1c81fb..1b2faaf 100644 --- a/dhcp_tools/main_wnd.c +++ b/dhcp_tools/main_wnd.c @@ -96,19 +96,19 @@ static void get_task_result(PDHCP_INFO pInfo, char *pInBuf, int maxBuf) { if (pInfo->status == STA_ERROR) { snprintf(pInBuf, maxBuf, "Error at %s", dhcp_step_to_string(pInfo->step)); } else if (pInfo->step == STEP_END) { - int ret; - DHCP_OPT opt; - PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pInfo->pAckBuf.p; - U32 optSize = pInfo->pAckBuf.buf_size - sizeof(DHCP_PACKAGE); - const char *pIp = NULL, *pNetmask = NULL, *pDns1 = NULL, *pDns2 = NULL; - pIp = u32_to_str_ip_safe(pkg->dhcp.yiaddr); + int ret; + DHCP_OPT opt; + const char *pIp = NULL, *pNetmask = NULL, *pDns1 = NULL, *pDns2 = NULL; + U32 optSize = 0; + PDHCP_PROTO pDhcp = get_dhcp_date(pInfo->pAckBuf.p, &optSize, pInfo->pAckBuf.buf_size); - ret = dhcp_get_option(OPT_NETMASK, pkg->dhcp.options, optSize, &opt); + pIp = u32_to_str_ip_safe(pDhcp->yiaddr); + ret = dhcp_get_option(OPT_NETMASK, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) { pNetmask = u32_to_str_ip_safe(*((U32 *)opt.pValue)); } - ret = dhcp_get_option(OPT_DNS, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_DNS, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS && opt.len >= sizeof(U32)) { U32 *pVal = (U32 *)opt.pValue; pDns1 = u32_to_str_ip_safe(*pVal); diff --git a/dhcp_tools/uv_rawsocket.c b/dhcp_tools/uv_rawsocket.c index 29df04b..22554c6 100644 --- a/dhcp_tools/uv_rawsocket.c +++ b/dhcp_tools/uv_rawsocket.c @@ -15,110 +15,156 @@ static U8 g_dhcpReqParams[] = {0x01, 0x1c, 0x02, 0x03, 0x0f, 0x06, 0x77, 0x0c, 0x2c, 0x2f, 0x1a, 0x79, 0x2a}; static char *g_pNicName = NULL; -static void pkg_init_head(PDHCP_PACKAGE p, PDHCP_INFO pInfo) { +static PDHCP_PROTO fill_dhcp_pkg(U8 *pRsp, PDHCP_INFO pInfo) { + struct ethhdr *pEth = (struct ethhdr *)pRsp; + struct iphdr *pIp = NULL; + struct udphdr *pUdp = NULL; + PDHCP_PROTO pDhcp = NULL; + + memset(pRsp, 0, MAX_DHCP_PKG_SIZE); + // 目的地 MAC 地址 - memset(p->hdr.eth.h_dest, 0xFF, ETH_ALEN); + memset(pEth->h_dest, 0xFF, ETH_ALEN); // 源 MAC 地址 - memcpy(p->hdr.eth.h_source, pInfo->mac, ETH_ALEN); + memcpy(pEth->h_source, pInfo->mac, ETH_ALEN); -#if VLAN_SUPPORT - // 协议 VLAN - p->hdr.eth.h_proto = htons(ETH_P_8021Q); - - // VLAN 隧道信息 - p->hdr.vlan.id = htons(pInfo->vni); - p->hdr.vlan.type = htons(ETH_P_IP); -#else - // 协议 VLAN - p->hdr.eth.h_proto = htons(ETH_P_IP); -#endif + if (pInfo->vni == 0) { + pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET); + pUdp = (struct udphdr *)(UDP_HDR_OFFSET); + pDhcp = (PDHCP_PROTO)((U8 *)pRsp + DHCP_OFFSET); + pEth->h_proto = htons(ETH_P_IP); + } else if (pInfo->vni >= 1 && pInfo->vni <= 4094) { + PVLAN_HDR pHdr = (PVLAN_HDR)(pRsp + sizeof(struct ethhdr)); + pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET + sizeof(VLAN_HDR)); + pUdp = (struct udphdr *)(pRsp + UDP_HDR_OFFSET + sizeof(VLAN_HDR)); + pDhcp = (PDHCP_PROTO)((U8 *)pRsp + DHCP_OFFSET + sizeof(VLAN_HDR)); + pEth->h_proto = htons(ETH_P_8021Q); + pHdr->id = htons(pInfo->vni); + pHdr->type = htons(ETH_P_IP); + } else { + PVLAN_HDR2 pHdr = (PVLAN_HDR2)(pRsp + sizeof(struct ethhdr)); + pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET + sizeof(VLAN_HDR2)); + pUdp = (struct udphdr *)(pRsp + UDP_HDR_OFFSET + sizeof(VLAN_HDR2)); + pDhcp = (PDHCP_PROTO)((U8 *)pRsp + DHCP_OFFSET + sizeof(VLAN_HDR2)); + pEth->h_proto = htons(ETH_P_8021Q); + pHdr->id1 = htons(4094); + pHdr->h_type = htons(ETH_P_8021Q); + pHdr->id2 = htons((pInfo->vni - 4094) & 0x0FFF); + pHdr->type = htons(ETH_P_IP); + } // IP 头 - p->hdr.ip.version = IPVERSION; - p->hdr.ip.ihl = 5; - p->hdr.ip.tos = 0; - p->hdr.ip.tot_len = 0; - p->hdr.ip.id = 0; - p->hdr.ip.frag_off = 0; - p->hdr.ip.ttl = 128; - p->hdr.ip.protocol = IPPROTO_UDP; - p->hdr.ip.check = 0; - p->hdr.ip.saddr = INADDR_ANY; - p->hdr.ip.daddr = INADDR_BROADCAST; + pIp->version = IPVERSION; + pIp->ihl = 5; + pIp->tos = 0; + pIp->tot_len = 0; + pIp->id = 0; + pIp->frag_off = 0; + pIp->ttl = 128; + pIp->protocol = IPPROTO_UDP; + pIp->check = 0; + pIp->saddr = INADDR_ANY; + pIp->daddr = INADDR_BROADCAST; // UDP 头 - p->hdr.udp.source = htons(DHCP_CLI_PORT); - p->hdr.udp.dest = htons(DHCP_SVR_PORT); - p->hdr.udp.len = 0; - p->hdr.udp.check = 0; + pUdp->source = htons(DHCP_CLI_PORT); + pUdp->dest = htons(DHCP_SVR_PORT); + pUdp->len = 0; + pUdp->check = 0; // DHCP 协议内容 - p->dhcp.op = BOOTP_REQUEST; - p->dhcp.htype = 0x01; - p->dhcp.hlen = ETH_ALEN; - p->dhcp.hops = 0; - p->dhcp.xid = 0; - p->dhcp.secs = 0; - p->dhcp.flags = 0; - p->dhcp.ciaddr = INADDR_ANY; - p->dhcp.yiaddr = INADDR_ANY; - p->dhcp.siaddr = INADDR_ANY; - p->dhcp.giaddr = INADDR_ANY; - memcpy(p->dhcp.chaddr, pInfo->mac, ETH_ALEN); - p->dhcp.cookie = htonl(DHCP_COOKIE_VAL); + pDhcp->op = BOOTP_REQUEST; + pDhcp->htype = 0x01; + pDhcp->hlen = ETH_ALEN; + pDhcp->hops = 0; + pDhcp->xid = 0; + pDhcp->secs = 0; + pDhcp->flags = 0; + pDhcp->ciaddr = INADDR_ANY; + pDhcp->yiaddr = INADDR_ANY; + pDhcp->siaddr = INADDR_ANY; + pDhcp->giaddr = INADDR_ANY; + memcpy(pDhcp->chaddr, pInfo->mac, ETH_ALEN); + pDhcp->cookie = htonl(DHCP_COOKIE_VAL); + + return pDhcp; } -static void cacl_package_checksum(PDHCP_PACKAGE p, int tolSize) { - U16 csum; +static U32 dhcp_pkk_checksum(U8 *pRsp, U32 optSize) { + struct iphdr *pIp = NULL; + struct udphdr *pUdp = NULL; + U16 csum; + U32 tolSize; + U8 vlanSize = 0; + + 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); + vlanSize = 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); + vlanSize = sizeof(VLAN_HDR2); + break; + } // 计算 IP 数据长度 - p->hdr.ip.tot_len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr)); + pIp->tot_len = htons(tolSize - sizeof(struct ethhdr) - vlanSize); // 计算 UDP 数据长度 - p->hdr.udp.len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr) - sizeof(struct iphdr)); + pUdp->len = htons(tolSize - sizeof(struct ethhdr) - vlanSize - sizeof(struct iphdr)); // 计算 IP 校验和 - csum = htons(ip_checksum((unsigned char *)&p->hdr.ip)); - p->hdr.ip.check = htons(csum); + csum = htons(ip_checksum((unsigned char *)pIp)); + pIp->check = htons(csum); // 计算 UDP 校验和 - csum = htons(udp_checksum(p->hdr.ip.saddr, p->hdr.ip.daddr, (unsigned char *)&p->hdr.udp)); - p->hdr.udp.check = htons(csum); + csum = htons(udp_checksum(pIp->saddr, pIp->daddr, (unsigned char *)pUdp)); + pUdp->check = htons(csum); + + return tolSize; } U8 *dhcp_create_request_req(PDHCP_INFO pInfo, int *pOutSize) { U8 *pOpt; - int tolSize; U8 *pReqData = (U8 *)malloc(MAX_DHCP_PKG_SIZE); if (pReqData) { - PDHCP_PACKAGE p = (PDHCP_PACKAGE)pReqData; - memset(pReqData, 0, MAX_DHCP_PKG_SIZE); + //PDHCP_PACKAGE pDhcp = (PDHCP_PACKAGE)pReqData; + PDHCP_PROTO pDhcp = fill_dhcp_pkg(pReqData, pInfo); - pkg_init_head(p, pInfo); + //pkg_init_head(pDhcp, pInfo); - p->dhcp.xid = htonl(pInfo->offerRsp.xid); + pDhcp->xid = htonl(pInfo->offerRsp.xid); // DHCP Options - pOpt = p->dhcp.options; + pOpt = pDhcp->options; // DHCP 消息类型 - pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_REQUEST); + pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_REQUEST); // DHCP 请求参数列表 - pOpt += dhcp_add_buf_option(pOpt, OPT_PARAMREQLIST, g_dhcpReqParams, 13); + pOpt += dhcp_add_buf_option(pOpt, OPT_PARAMREQLIST, g_dhcpReqParams, 13); // DHCP 主机名 - pOpt += dhcp_add_string_option(pOpt, OPT_HOSTNAME, pInfo->hostname); + pOpt += dhcp_add_string_option(pOpt, OPT_HOSTNAME, pInfo->hostname); // DHCP Server 主机 - pOpt += dhcp_add_u32_option(pOpt, OPT_SERVERID, htonl(pInfo->offerRsp.svrIp)); + pOpt += dhcp_add_u32_option(pOpt, OPT_SERVERID, htonl(pInfo->offerRsp.svrIp)); // DHCP 请求分配IP - pOpt += dhcp_add_u32_option(pOpt, OPT_REQUESTEDIPADDR, htonl(pInfo->offerRsp.ipAddr)); + pOpt += dhcp_add_u32_option(pOpt, OPT_REQUESTEDIPADDR, htonl(pInfo->offerRsp.ipAddr)); // 结束 - *pOpt = OPT_END; - // 计算包总长度 - tolSize = (int)((pOpt - p->dhcp.options) + 1 + sizeof(DHCP_PACKAGE)); + *pOpt = OPT_END; - cacl_package_checksum(p, tolSize); - - *pOutSize = tolSize; + *pOutSize = (int)dhcp_pkk_checksum(pReqData, (int)((pOpt - pDhcp->options) + 1)); } return pReqData; @@ -130,15 +176,15 @@ U8 *dhcp_create_discover_req(PDHCP_INFO pInfo, int *pOutSize) { U8 *pReqData = (U8 *)malloc(MAX_DHCP_PKG_SIZE); if (pReqData) { - PDHCP_PACKAGE p = (PDHCP_PACKAGE)pReqData; + //PDHCP_PACKAGE pDhcp = (PDHCP_PACKAGE)pReqData; + PDHCP_PROTO pDhcp = fill_dhcp_pkg(pReqData, pInfo); + //memset(pReqData, 0, MAX_DHCP_PKG_SIZE); - memset(pReqData, 0, MAX_DHCP_PKG_SIZE); - - pkg_init_head(p, pInfo); - p->dhcp.xid = htonl((rand_number() & 0xFF000000) + pInfo->index); + //pkg_init_head(pDhcp, pInfo); + pDhcp->xid = htonl((rand_number() & 0xFF000000) + pInfo->index); // DHCP Options - pOpt = p->dhcp.options; + pOpt = pDhcp->options; // DHCP 消息类型 pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_DISCOVER); @@ -149,12 +195,7 @@ U8 *dhcp_create_discover_req(PDHCP_INFO pInfo, int *pOutSize) { // 结束 *pOpt = OPT_END; - // 计算包总长度 - tolSize = (int)((pOpt - p->dhcp.options) + 1 + sizeof(DHCP_PACKAGE)); - - cacl_package_checksum(p, tolSize); - - *pOutSize = tolSize; + *pOutSize = (int)dhcp_pkk_checksum(pReqData, (int)((pOpt - pDhcp->options) + 1)); } return pReqData; @@ -167,18 +208,18 @@ static void on_dhcp_recv(uv_work_t *req) { 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); - U32 id = DHCP_XID(pkg->dhcp.xid); + U32 optSize = 0; + PDHCP_PROTO pDhcp = get_dhcp_date(pWork->pPkgBase, &optSize, pWork->nSize); + U32 id = DHCP_XID(pDhcp->xid); // Check op flag - if (pkg->dhcp.op != BOOTP_REPLY) { - LOG_MOD(error, ZM_DHCP_NET, "Error message op code %d\n", pkg->dhcp.op); + if (pDhcp->op != BOOTP_REPLY) { + LOG_MOD(error, ZM_DHCP_NET, "Error message op code %d\n", pDhcp->op); return; } // 获取消息类型 - ret = dhcp_get_option(OPT_MESSAGETYPE, pkg->dhcp.options, optSize, &optMsg); + ret = dhcp_get_option(OPT_MESSAGETYPE, pDhcp->options, optSize, &optMsg); if (ret != ERR_SUCCESS) { LOG_MOD(error, ZM_DHCP_NET, "Get \'message type\' option error %d\n", ret); return; @@ -187,24 +228,24 @@ static void on_dhcp_recv(uv_work_t *req) { pInfo = get_dhcp_info_by_id(id); if (pInfo == NULL) { - LOG_MOD(error, ZM_DHCP_NET, "Unknown Client %d\n", DHCP_XID(pkg->dhcp.xid) & 0xFFFFFF); + LOG_MOD(error, ZM_DHCP_NET, "Unknown Client %d\n", DHCP_XID(pDhcp->xid) & 0xFFFFFF); return; } memset(&rspDhcp, 0, sizeof(DHCP_RSP)); rspDhcp.xid = id; - rspDhcp.ipAddr = ntohl(pkg->dhcp.yiaddr); - memcpy(rspDhcp.cliMac, pkg->dhcp.chaddr, ETH_ALEN); - memcpy(rspDhcp.svrHostname, pkg->dhcp.sname, 64); + rspDhcp.ipAddr = ntohl(pDhcp->yiaddr); + memcpy(rspDhcp.cliMac, pDhcp->chaddr, ETH_ALEN); + memcpy(rspDhcp.svrHostname, pDhcp->sname, 64); switch (*optMsg.pValue) { case DHCP_MSG_OFFER: - ret = dhcp_get_option(OPT_NETMASK, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_NETMASK, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) { rspDhcp.netmask = ntohl(*((U32 *)opt.pValue)); } - ret = dhcp_get_option(OPT_DNS, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_DNS, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS) { U32 *pVal = (U32 *)opt.pValue; rspDhcp.primeDNS = ntohl(*pVal); @@ -214,22 +255,22 @@ static void on_dhcp_recv(uv_work_t *req) { } } - ret = dhcp_get_option(OPT_ROUTER, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_ROUTER, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS) { rspDhcp.route = ntohl(*((U32 *)opt.pValue)); } - ret = dhcp_get_option(OPT_IPADDRLEASE, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_IPADDRLEASE, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS) { rspDhcp.leaseTime = ntohl(*((U32 *)opt.pValue)); } - ret = dhcp_get_option(OPT_SERVERID, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_SERVERID, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS) { rspDhcp.svrIp = ntohl(*((U32 *)opt.pValue)); } - ret = dhcp_get_option(OPT_DOMAINNAME, pkg->dhcp.options, optSize, &opt); + ret = dhcp_get_option(OPT_DOMAINNAME, pDhcp->options, optSize, &opt); if (ret == ERR_SUCCESS) { strncpy(rspDhcp.domainName, (char *)opt.pValue, MIN((int)opt.len, 64)); } @@ -271,7 +312,7 @@ int dhcp_tools_init_network(const char *pNicName) { } #if VLAN_SUPPORT - init_filter("vlan and udp and dst port 68"); + init_filter("vlan or (udp and dst port 68)"); #else init_filter("udp and dst port 68"); #endif