OCT 1. DHCP 测试工具支持双层VLAN

This commit is contained in:
黄昕 2023-05-16 15:00:37 +08:00
parent a356a7f9ef
commit e6ea44dd19
5 changed files with 233 additions and 161 deletions

View File

@ -3,6 +3,7 @@ SET(PROJECT_TARGET dhcp_tools)
PROJECT(${PROJECT_TARGET} LANGUAGES C) PROJECT(${PROJECT_TARGET} LANGUAGES C)
FIND_PACKAGE(PkgConfig REQUIRED) FIND_PACKAGE(PkgConfig REQUIRED)
# sudo apt install libgtk-3-dev
PKG_CHECK_MODULES(GTK3 REQUIRED gtk+-3.0) PKG_CHECK_MODULES(GTK3 REQUIRED gtk+-3.0)
INCLUDE_DIRECTORIES(${GTK3_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${GTK3_INCLUDE_DIRS})
LINK_DIRECTORIES(${GTK3_LIBRARY_DIRS}) LINK_DIRECTORIES(${GTK3_LIBRARY_DIRS})

View File

@ -97,10 +97,10 @@ static void add_dhcp_tree_colums(GtkWidget *treeView) {
break; \ break; \
case 3: \ case 3: \
do { \ do { \
U32 *pIp = (U32 *)(val); \ U32 *pIps = (U32 *)(val); \
gtk_tree_store_append(store, &iterOpt, &iterSub); \ gtk_tree_store_append(store, &iterOpt, &iterSub); \
s = sdsempty(); \ 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); \ gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, s, -1); \
sdsfree(s); \ sdsfree(s); \
count_flag += 4; \ count_flag += 4; \
@ -129,14 +129,19 @@ static void add_dhcp_tree_colums(GtkWidget *treeView) {
} \ } \
} while (0) } 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 协议数据 // 填充右上侧 TreeView 协议数据
sds s; sds s;
GtkTreeIter iter, iterSub, iterOpt; GtkTreeIter iter, iterSub, iterOpt;
GtkTreeStore *store = NULL; //gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_STRING); 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"}; 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)); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeView));
//GtkTreeStore *store = GTK_TREE_STORE(); struct ethhdr *pEth = (struct ethhdr *)pkg;
struct iphdr *pIp = NULL;
struct udphdr *pUdp = NULL;
PDHCP_PROTO pDhcp = NULL;
if (model) { if (model) {
store = GTK_TREE_STORE(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 头相关内容 // 添加 Ethernet II 头相关内容
s = sdsempty(); s = sdsempty();
MAC_TO_STR(p->hdr.eth.h_dest, s); MAC_TO_STR(pEth->h_dest, s);
ADD_SUB_STRING("Destination", s); ADD_SUB_STRING("Destination", s);
sdsfree(s); sdsfree(s);
s = sdsempty(); s = sdsempty();
MAC_TO_STR(p->hdr.eth.h_source, s); MAC_TO_STR(pEth->h_source, s);
ADD_SUB_STRING("Source", s); ADD_SUB_STRING("Source", s);
sdsfree(s); sdsfree(s);
#if VLAN_SUPPORT 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 头相关内容 // 添加 VLan 头相关内容
gtk_tree_store_append(store, &iter, NULL); gtk_tree_store_append(store, &iter, NULL);
gtk_tree_store_set(store, &iter, 0, itemTitle[1], 1, "", -1); 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("ID", "%u", VLAN_VNI_ID(pvLan->id));
ADD_SUB_INT("Type", "0x%04X", ntohs(p->hdr.vlan.type)); ADD_SUB_INT("Type", "0x%04X", ntohs(pvLan->type));
#endif 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 头 // 添加 IP 头
gtk_tree_store_append(store, &iter, NULL); gtk_tree_store_append(store, &iter, NULL);
gtk_tree_store_set(store, &iter, 0, itemTitle[2], 1, "", -1); 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(); 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); ADD_SUB_STRING("Header Length", s);
sdsfree(s); sdsfree(s);
ADD_SUB_INT("Differentiated Services Field", "0x%02X", p->hdr.ip.tos); ADD_SUB_INT("Differentiated Services Field", "0x%02X", pIp->tos);
ADD_SUB_INT("Total Length", "%u", ntohs(p->hdr.ip.tot_len)); ADD_SUB_INT("Total Length", "%u", ntohs(pIp->tot_len));
ADD_SUB_INT("Identification", "0x%04X", ntohs(p->hdr.ip.id)); ADD_SUB_INT("Identification", "0x%04X", ntohs(pIp->id));
ADD_SUB_INT("Flags", "0x%04X", ntohs(p->hdr.ip.frag_off)); ADD_SUB_INT("Flags", "0x%04X", ntohs(pIp->frag_off));
ADD_SUB_INT("Time to live", "%u", p->hdr.ip.ttl); ADD_SUB_INT("Time to live", "%u", pIp->ttl);
ADD_SUB_STRING("Protocol", "UDP"); ADD_SUB_STRING("Protocol", "UDP");
ADD_SUB_INT("Header Checksum", "0x%04X", ntohs(p->hdr.ip.check)); ADD_SUB_INT("Header Checksum", "0x%04X", ntohs(pIp->check));
ADD_SUB_STRING("Source", inet_ntoa(*(struct in_addr *)&p->hdr.ip.saddr)); ADD_SUB_STRING("Source", inet_ntoa(*(struct in_addr *)&pIp->saddr));
ADD_SUB_STRING("Destination", inet_ntoa(*(struct in_addr *)&p->hdr.ip.daddr)); ADD_SUB_STRING("Destination", inet_ntoa(*(struct in_addr *)&pIp->daddr));
// 添加 UDP 头 // 添加 UDP 头
gtk_tree_store_append(store, &iter, NULL); gtk_tree_store_append(store, &iter, NULL);
gtk_tree_store_set(store, &iter, 0, itemTitle[3], 1, "", -1); 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("Source Port", "%u", ntohs(pUdp->source));
ADD_SUB_INT("Destination Port", "%u", ntohs(p->hdr.udp.dest)); ADD_SUB_INT("Destination Port", "%u", ntohs(pUdp->dest));
ADD_SUB_INT("Length", "%u", ntohs(p->hdr.udp.len)); ADD_SUB_INT("Length", "%u", ntohs(pUdp->len));
ADD_SUB_INT("Checksum", "0x%04X", ntohs(p->hdr.udp.check)); ADD_SUB_INT("Checksum", "0x%04X", ntohs(pUdp->check));
// 添加 DHCP 内容 // 添加 DHCP 内容
gtk_tree_store_append(store, &iter, NULL); gtk_tree_store_append(store, &iter, NULL);
gtk_tree_store_set(store, &iter, 0, itemTitle[4], 1, "", -1); gtk_tree_store_set(store, &iter, 0, itemTitle[4], 1, "", -1);
switch (p->dhcp.op) { switch (pDhcp->op) {
case 1: case 1:
ADD_SUB_STRING("Message Type", "Boot Request"); ADD_SUB_STRING("Message Type", "Boot Request");
break; break;
@ -211,43 +239,43 @@ static void create_dhcp_tree_mode(PDHCP_PACKAGE p, U32 nBytes, GtkWidget *treeVi
default: default:
ADD_SUB_STRING("Message Type", "Unknown"); ADD_SUB_STRING("Message Type", "Unknown");
} }
switch (p->dhcp.htype) { switch (pDhcp->htype) {
case 1: case 1:
ADD_SUB_STRING("Hardware Type", "Ethernet"); ADD_SUB_STRING("Hardware Type", "Ethernet");
break; break;
default: default:
ADD_SUB_STRING("Hardware Type", "Unknown"); ADD_SUB_STRING("Hardware Type", "Unknown");
} }
ADD_SUB_INT("Hardware address length", "%u", p->dhcp.hlen); ADD_SUB_INT("Hardware address length", "%u", pDhcp->hlen);
ADD_SUB_INT("Hops", "%u", p->dhcp.hops); ADD_SUB_INT("Hops", "%u", pDhcp->hops);
ADD_SUB_INT("Transaction ID", "0x%08X", p->dhcp.xid); ADD_SUB_INT("Transaction ID", "0x%08X", pDhcp->xid);
ADD_SUB_INT("Seconds elapsed", "%u", p->dhcp.secs); ADD_SUB_INT("Seconds elapsed", "%u", pDhcp->secs);
ADD_SUB_INT("Bootp flags", "0x%04X", p->dhcp.flags); ADD_SUB_INT("Bootp flags", "0x%04X", pDhcp->flags);
ADD_SUB_STRING("Client IP address", inet_ntoa(*(struct in_addr *)&p->dhcp.ciaddr)); 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 *)&p->dhcp.yiaddr)); 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 *)&p->dhcp.siaddr)); 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 *)&p->dhcp.giaddr)); ADD_SUB_STRING("Relay agent IP address", inet_ntoa(*(struct in_addr *)&pDhcp->giaddr));
s = sdsempty(); s = sdsempty();
MAC_TO_STR(p->dhcp.chaddr, s); MAC_TO_STR(pDhcp->chaddr, s);
ADD_SUB_STRING("Client MAC address", s); ADD_SUB_STRING("Client MAC address", s);
sdsfree(s); sdsfree(s);
if (strlen((char *)p->dhcp.sname) > 0) { if (strlen((char *)pDhcp->sname) > 0) {
ADD_SUB_STRING("Server host name", p->dhcp.sname); ADD_SUB_STRING("Server host name", pDhcp->sname);
} else { } else {
ADD_SUB_STRING("Server host name", "not given"); ADD_SUB_STRING("Server host name", "not given");
} }
if (strlen((char *)p->dhcp.file) > 0) { if (strlen((char *)pDhcp->file) > 0) {
ADD_SUB_STRING("Boot file name", p->dhcp.file); ADD_SUB_STRING("Boot file name", pDhcp->file);
} else { } else {
ADD_SUB_STRING("Boot file name", "not given"); ADD_SUB_STRING("Boot file name", "not given");
} }
ADD_SUB_STRING("Magic cookie", "DHCP"); ADD_SUB_STRING("Magic cookie", "DHCP");
U8 *opPointer, *optEnd = (U8 *)p + nBytes; U8 *opPointer, *optEnd = (U8 *)pkg + nBytes;
opPointer = p->dhcp.options; opPointer = pDhcp->options;
while (*opPointer && opPointer < optEnd) { while (*opPointer && opPointer < optEnd) {
if (*opPointer == OPT_END) { if (*opPointer == OPT_END) {
ADD_SUB_STRING("Option(255)", "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)); (pInfo->pReqBuf.tm.tv_sec * 1000000 + pInfo->pReqBuf.tm.tv_usec));
if (pInfo->pAckBuf.p) { if (pInfo->pAckBuf.p) {
PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pInfo->pAckBuf.p; U32 optSize = 0;
U32 optSize = pInfo->pAckBuf.buf_size - sizeof(DHCP_PACKAGE); PDHCP_PROTO pDhcp = get_dhcp_date(pInfo->pAckBuf.p, &optSize, pInfo->pAckBuf.buf_size);
pIp = u32_to_str_ip_safe(pkg->dhcp.yiaddr); 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)) { if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
pNetmask = u32_to_str_ip_safe(*((U32 *)opt.pValue)); 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)) { if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
pGw = u32_to_str_ip_safe(*((U32 *)opt.pValue)); 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)) { if (ret == ERR_SUCCESS && opt.len >= sizeof(U32)) {
U32 *pVal = (U32 *)opt.pValue; U32 *pVal = (U32 *)opt.pValue;
pDns1 = u32_to_str_ip_safe(*pVal); pDns1 = u32_to_str_ip_safe(*pVal);
@ -424,7 +452,7 @@ void details_wnd_show(PDHCP_INFO pInfo) {
// 填充 TreeView // 填充 TreeView
add_dhcp_tree_colums(g_ptvDHcp[i]); 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); upgrade_statusbar_proc(pInfo);

View File

@ -8,6 +8,7 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "uthash/uthash.h" #include "uthash/uthash.h"
#include "rfc2131.h" #include "rfc2131.h"
#include "service/dhcpd.h"
#define ADD_LOG_MSG(level, m, format, ...) \ #define ADD_LOG_MSG(level, m, format, ...) \
(format_log_msg(level, (m), "[%s] - %s(%d):" format, basename_v2(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)) (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); void write_log_msg(const char *pMsg, int mode);
GtkBuilder *get_main_builder(); GtkBuilder *get_main_builder();
void format_log_msg(int level, int mode, const char *pMsg, ...); 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 #endif //VCPE_MAIN_H

View File

@ -98,17 +98,17 @@ static void get_task_result(PDHCP_INFO pInfo, char *pInBuf, int maxBuf) {
} else if (pInfo->step == STEP_END) { } else if (pInfo->step == STEP_END) {
int ret; int ret;
DHCP_OPT opt; 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; const char *pIp = NULL, *pNetmask = NULL, *pDns1 = NULL, *pDns2 = NULL;
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);
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)) { if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
pNetmask = u32_to_str_ip_safe(*((U32 *)opt.pValue)); 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)) { if (ret == ERR_SUCCESS && opt.len >= sizeof(U32)) {
U32 *pVal = (U32 *)opt.pValue; U32 *pVal = (U32 *)opt.pValue;
pDns1 = u32_to_str_ip_safe(*pVal); pDns1 = u32_to_str_ip_safe(*pVal);

View File

@ -15,91 +15,141 @@
static U8 g_dhcpReqParams[] = {0x01, 0x1c, 0x02, 0x03, 0x0f, 0x06, 0x77, 0x0c, 0x2c, 0x2f, 0x1a, 0x79, 0x2a}; static U8 g_dhcpReqParams[] = {0x01, 0x1c, 0x02, 0x03, 0x0f, 0x06, 0x77, 0x0c, 0x2c, 0x2f, 0x1a, 0x79, 0x2a};
static char *g_pNicName = NULL; 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 地址 // 目的地 MAC 地址
memset(p->hdr.eth.h_dest, 0xFF, ETH_ALEN); memset(pEth->h_dest, 0xFF, ETH_ALEN);
// 源 MAC 地址 // 源 MAC 地址
memcpy(p->hdr.eth.h_source, pInfo->mac, ETH_ALEN); memcpy(pEth->h_source, pInfo->mac, ETH_ALEN);
#if VLAN_SUPPORT if (pInfo->vni == 0) {
// 协议 VLAN pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET);
p->hdr.eth.h_proto = htons(ETH_P_8021Q); pUdp = (struct udphdr *)(UDP_HDR_OFFSET);
pDhcp = (PDHCP_PROTO)((U8 *)pRsp + DHCP_OFFSET);
// VLAN 隧道信息 pEth->h_proto = htons(ETH_P_IP);
p->hdr.vlan.id = htons(pInfo->vni); } else if (pInfo->vni >= 1 && pInfo->vni <= 4094) {
p->hdr.vlan.type = htons(ETH_P_IP); PVLAN_HDR pHdr = (PVLAN_HDR)(pRsp + sizeof(struct ethhdr));
#else pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET + sizeof(VLAN_HDR));
// 协议 VLAN pUdp = (struct udphdr *)(pRsp + UDP_HDR_OFFSET + sizeof(VLAN_HDR));
p->hdr.eth.h_proto = htons(ETH_P_IP); pDhcp = (PDHCP_PROTO)((U8 *)pRsp + DHCP_OFFSET + sizeof(VLAN_HDR));
#endif pEth->h_proto = htons(ETH_P_8021Q);
pHdr->id = htons(pInfo->vni);
// IP 头 pHdr->type = htons(ETH_P_IP);
p->hdr.ip.version = IPVERSION; } else {
p->hdr.ip.ihl = 5; PVLAN_HDR2 pHdr = (PVLAN_HDR2)(pRsp + sizeof(struct ethhdr));
p->hdr.ip.tos = 0; pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET + sizeof(VLAN_HDR2));
p->hdr.ip.tot_len = 0; pUdp = (struct udphdr *)(pRsp + UDP_HDR_OFFSET + sizeof(VLAN_HDR2));
p->hdr.ip.id = 0; pDhcp = (PDHCP_PROTO)((U8 *)pRsp + DHCP_OFFSET + sizeof(VLAN_HDR2));
p->hdr.ip.frag_off = 0; pEth->h_proto = htons(ETH_P_8021Q);
p->hdr.ip.ttl = 128; pHdr->id1 = htons(4094);
p->hdr.ip.protocol = IPPROTO_UDP; pHdr->h_type = htons(ETH_P_8021Q);
p->hdr.ip.check = 0; pHdr->id2 = htons((pInfo->vni - 4094) & 0x0FFF);
p->hdr.ip.saddr = INADDR_ANY; pHdr->type = htons(ETH_P_IP);
p->hdr.ip.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;
// 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);
} }
static void cacl_package_checksum(PDHCP_PACKAGE p, int tolSize) { // IP 头
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 头
pUdp->source = htons(DHCP_CLI_PORT);
pUdp->dest = htons(DHCP_SVR_PORT);
pUdp->len = 0;
pUdp->check = 0;
// DHCP 协议内容
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 U32 dhcp_pkk_checksum(U8 *pRsp, U32 optSize) {
struct iphdr *pIp = NULL;
struct udphdr *pUdp = NULL;
U16 csum; 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 数据长度 // 计算 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 数据长度 // 计算 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 校验和 // 计算 IP 校验和
csum = htons(ip_checksum((unsigned char *)&p->hdr.ip)); csum = htons(ip_checksum((unsigned char *)pIp));
p->hdr.ip.check = htons(csum); pIp->check = htons(csum);
// 计算 UDP 校验和 // 计算 UDP 校验和
csum = htons(udp_checksum(p->hdr.ip.saddr, p->hdr.ip.daddr, (unsigned char *)&p->hdr.udp)); csum = htons(udp_checksum(pIp->saddr, pIp->daddr, (unsigned char *)pUdp));
p->hdr.udp.check = htons(csum); pUdp->check = htons(csum);
return tolSize;
} }
U8 *dhcp_create_request_req(PDHCP_INFO pInfo, int *pOutSize) { U8 *dhcp_create_request_req(PDHCP_INFO pInfo, int *pOutSize) {
U8 *pOpt; U8 *pOpt;
int tolSize;
U8 *pReqData = (U8 *)malloc(MAX_DHCP_PKG_SIZE); U8 *pReqData = (U8 *)malloc(MAX_DHCP_PKG_SIZE);
if (pReqData) { if (pReqData) {
PDHCP_PACKAGE p = (PDHCP_PACKAGE)pReqData; //PDHCP_PACKAGE pDhcp = (PDHCP_PACKAGE)pReqData;
memset(pReqData, 0, MAX_DHCP_PKG_SIZE); 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 // DHCP Options
pOpt = p->dhcp.options; pOpt = pDhcp->options;
// DHCP 消息类型 // DHCP 消息类型
pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_REQUEST); pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_REQUEST);
@ -113,12 +163,8 @@ U8 *dhcp_create_request_req(PDHCP_INFO pInfo, int *pOutSize) {
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; *pOpt = OPT_END;
// 计算包总长度
tolSize = (int)((pOpt - p->dhcp.options) + 1 + sizeof(DHCP_PACKAGE));
cacl_package_checksum(p, tolSize); *pOutSize = (int)dhcp_pkk_checksum(pReqData, (int)((pOpt - pDhcp->options) + 1));
*pOutSize = tolSize;
} }
return pReqData; return pReqData;
@ -130,15 +176,15 @@ U8 *dhcp_create_discover_req(PDHCP_INFO pInfo, int *pOutSize) {
U8 *pReqData = (U8 *)malloc(MAX_DHCP_PKG_SIZE); U8 *pReqData = (U8 *)malloc(MAX_DHCP_PKG_SIZE);
if (pReqData) { 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(pDhcp, pInfo);
pDhcp->xid = htonl((rand_number() & 0xFF000000) + pInfo->index);
pkg_init_head(p, pInfo);
p->dhcp.xid = htonl((rand_number() & 0xFF000000) + pInfo->index);
// DHCP Options // DHCP Options
pOpt = p->dhcp.options; pOpt = pDhcp->options;
// DHCP 消息类型 // DHCP 消息类型
pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_DISCOVER); 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; *pOpt = OPT_END;
// 计算包总长度 *pOutSize = (int)dhcp_pkk_checksum(pReqData, (int)((pOpt - pDhcp->options) + 1));
tolSize = (int)((pOpt - p->dhcp.options) + 1 + sizeof(DHCP_PACKAGE));
cacl_package_checksum(p, tolSize);
*pOutSize = tolSize;
} }
return pReqData; return pReqData;
@ -167,18 +208,18 @@ static void on_dhcp_recv(uv_work_t *req) {
DHCP_OPT optMsg, opt; DHCP_OPT optMsg, opt;
int ret; int ret;
PPKG_PROCESS_INFO pWork = (PPKG_PROCESS_INFO)req->data; PPKG_PROCESS_INFO pWork = (PPKG_PROCESS_INFO)req->data;
PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pWork->pPkgBase; U32 optSize = 0;
U32 optSize = pWork->nSize - sizeof(DHCP_PACKAGE); PDHCP_PROTO pDhcp = get_dhcp_date(pWork->pPkgBase, &optSize, pWork->nSize);
U32 id = DHCP_XID(pkg->dhcp.xid); U32 id = DHCP_XID(pDhcp->xid);
// Check op flag // Check op flag
if (pkg->dhcp.op != BOOTP_REPLY) { if (pDhcp->op != BOOTP_REPLY) {
LOG_MOD(error, ZM_DHCP_NET, "Error message op code %d\n", pkg->dhcp.op); LOG_MOD(error, ZM_DHCP_NET, "Error message op code %d\n", pDhcp->op);
return; 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) { if (ret != ERR_SUCCESS) {
LOG_MOD(error, ZM_DHCP_NET, "Get \'message type\' option error %d\n", ret); LOG_MOD(error, ZM_DHCP_NET, "Get \'message type\' option error %d\n", ret);
return; return;
@ -187,24 +228,24 @@ static void on_dhcp_recv(uv_work_t *req) {
pInfo = get_dhcp_info_by_id(id); pInfo = get_dhcp_info_by_id(id);
if (pInfo == NULL) { 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; return;
} }
memset(&rspDhcp, 0, sizeof(DHCP_RSP)); memset(&rspDhcp, 0, sizeof(DHCP_RSP));
rspDhcp.xid = id; rspDhcp.xid = id;
rspDhcp.ipAddr = ntohl(pkg->dhcp.yiaddr); rspDhcp.ipAddr = ntohl(pDhcp->yiaddr);
memcpy(rspDhcp.cliMac, pkg->dhcp.chaddr, ETH_ALEN); memcpy(rspDhcp.cliMac, pDhcp->chaddr, ETH_ALEN);
memcpy(rspDhcp.svrHostname, pkg->dhcp.sname, 64); memcpy(rspDhcp.svrHostname, pDhcp->sname, 64);
switch (*optMsg.pValue) { switch (*optMsg.pValue) {
case DHCP_MSG_OFFER: 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)) { if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
rspDhcp.netmask = ntohl(*((U32 *)opt.pValue)); 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) { if (ret == ERR_SUCCESS) {
U32 *pVal = (U32 *)opt.pValue; U32 *pVal = (U32 *)opt.pValue;
rspDhcp.primeDNS = ntohl(*pVal); 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) { if (ret == ERR_SUCCESS) {
rspDhcp.route = ntohl(*((U32 *)opt.pValue)); 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) { if (ret == ERR_SUCCESS) {
rspDhcp.leaseTime = ntohl(*((U32 *)opt.pValue)); 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) { if (ret == ERR_SUCCESS) {
rspDhcp.svrIp = ntohl(*((U32 *)opt.pValue)); 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) { if (ret == ERR_SUCCESS) {
strncpy(rspDhcp.domainName, (char *)opt.pValue, MIN((int)opt.len, 64)); 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 #if VLAN_SUPPORT
init_filter("vlan and udp and dst port 68"); init_filter("vlan or (udp and dst port 68)");
#else #else
init_filter("udp and dst port 68"); init_filter("udp and dst port 68");
#endif #endif