diff --git a/dhcp_tools/detail_wnd.c b/dhcp_tools/detail_wnd.c index 14001e7..d141a9d 100644 --- a/dhcp_tools/detail_wnd.c +++ b/dhcp_tools/detail_wnd.c @@ -6,6 +6,7 @@ #include "zlog_module.h" #include "dhcp_network.h" #include "sds/sds.h" +#include "dhcp_options.h" static GtkWidget *g_detailWnd = NULL; @@ -69,9 +70,17 @@ void details_wnd_create(void *b) { } #endif -static GtkTextBuffer *g_pTxtBuf[4]; -static GtkWidget *g_ptvDHcp[4]; -static GtkWidget *g_ptvHex[4]; +typedef struct { + U8 op_code; + U8 op_size; + U8 op_value[256]; +} STR_OPT; + +static char* g_mess_info[] = { "NONE", "DISCOVER", "OFFER", "REQUEST", "DECLINE", "ACK", "NAK", "RELEASE", "INFORM"}; + +static GtkTextBuffer *g_pTxtBuf[4]; +static GtkWidget *g_ptvDHcp[4]; +static GtkWidget *g_ptvHex[4]; static gboolean delete_event(GtkWidget *widget, GdkEventAny *event) { /* 如果你的 "delete_event" 信号处理函数返回 FALSE,GTK 会发出 "destroy" 信号。 @@ -107,10 +116,68 @@ static void add_dhcp_tree_colums(GtkWidget *treeView) { sdsfree(s); \ } while (0) +#define ADD_SUB_OPTION(code, len, val) \ + do { \ + int count_flag = 0; \ + char *p; \ + gtk_tree_store_append(store, &iterOpt, &iterSub); \ + s = sdsempty(); \ + sprintf(s, "%u", (len)); \ + gtk_tree_store_set(store, &iterOpt, 0, "Length", 1, s, -1); \ + sdsfree(s); \ + \ + switch(dhcp_get_opType(code)) { \ + case 1: \ + gtk_tree_store_append(store, &iterOpt, &iterSub); \ + gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, (val), -1);\ + break; \ + case 2: \ + do { \ + gtk_tree_store_append(store, &iterOpt, &iterSub); \ + s = sdsempty(); \ + sprintf(s, "(%u) %s", (val)[count_flag], dhcp_get_opName((val)[count_flag]));\ + gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, s, -1);\ + sdsfree(s); \ + count_flag++; \ + } while(count_flag != (len)); \ + break; \ + case 3: \ + do { \ + gtk_tree_store_append(store, &iterOpt, &iterSub); \ + s = sdsempty(); \ + sprintf(s, "%u.%u.%u.%u", (val)[count_flag], (val)[count_flag+1], (val)[count_flag+2], (val)[count_flag+3]);\ + gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, s, -1); \ + sdsfree(s); \ + count_flag += 4; \ + } while(count_flag != (len)); \ + break; \ + case 4: \ + gtk_tree_store_append(store, &iterOpt, &iterSub); \ + for(int i = 0; i<(len); i++) \ + count_flag = count_flag*256 + (val)[i]; \ + s = sdsempty(); \ + sprintf(s, "%d(s)", count_flag); \ + gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, s, -1); \ + sdsfree(s); \ + break; \ + case 6: \ + gtk_tree_store_append(store, &iterOpt, &iterSub); \ + s = sdsempty(); \ + if((code) == OPT_MESSAGETYPE) { \ + gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, g_mess_info[(val)[0]], -1);\ + } \ + sdsfree(s); \ + break; \ + default: \ + gtk_tree_store_append(store, &iterOpt, &iterSub); \ + gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, "", -1);\ + } \ + } while (0) + static void create_dhcp_tree_mode(PDHCP_PACKAGE p, GtkWidget *treeView) { // 填充右上侧 TreeView 协议数据 sds s; - GtkTreeIter iter, iterSub; + GtkTreeIter iter, iterSub, iterOpt; GtkTreeStore *store = 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"}; @@ -138,14 +205,99 @@ static void create_dhcp_tree_mode(PDHCP_PACKAGE p, GtkWidget *treeView) { // 添加 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->vlan_hdr.ip.version); + + s = sdsempty(); + sprintf(s, "%u %s (%u)", p->vlan_hdr.ip.ihl*4, "bytes", p->vlan_hdr.ip.ihl); + ADD_SUB_STRING("Header Length", s); + sdsfree(s); + + ADD_SUB_INT("Differentiated Services Field", "0x%02X", p->vlan_hdr.ip.tos); + ADD_SUB_INT("Total Length", "%u", ntohs(p->vlan_hdr.ip.tot_len)); + ADD_SUB_INT("Identification", "0x%04X", ntohs(p->vlan_hdr.ip.id)); + ADD_SUB_INT("Flags", "0x%04X", ntohs(p->vlan_hdr.ip.frag_off)); + ADD_SUB_INT("Time to live", "%u", p->vlan_hdr.ip.ttl); + ADD_SUB_STRING("Protocol", "UDP"); + ADD_SUB_INT("Header Checksum", "0x%04X", ntohs(p->vlan_hdr.ip.check)); + ADD_SUB_STRING("Source", inet_ntoa(*(struct in_addr*)&p->vlan_hdr.ip.saddr)); + ADD_SUB_STRING("Destination", inet_ntoa(*(struct in_addr*)&p->vlan_hdr.ip.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->vlan_hdr.udp.source)); + ADD_SUB_INT("Destination Port", "%u", ntohs(p->vlan_hdr.udp.dest)); + ADD_SUB_INT("Length", "%u", ntohs(p->vlan_hdr.udp.len)); + ADD_SUB_INT("Checksum", "0x%04X", ntohs(p->vlan_hdr.udp.check)); // 添加 DHCP 内容 gtk_tree_store_append(store, &iter, NULL); gtk_tree_store_set(store, &iter, 0, itemTitle[4], 1, "", -1); + switch(p->dhcp.op) { + case 1: + ADD_SUB_STRING("Message Type", "Boot Request"); + break; + case 2: + ADD_SUB_STRING("Message Type", "Boot Reply"); + break; + default: + ADD_SUB_STRING("Message Type", "Unknown"); + } + switch(p->dhcp.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)); + s = sdsempty(); + MAC_TO_STR(p->dhcp.chaddr, s); + ADD_SUB_STRING("Destination", s); + sdsfree(s); + + if(strlen(p->dhcp.sname) != 0) + ADD_SUB_STRING("Server host name", p->dhcp.sname); + else + ADD_SUB_STRING("Server host name", "not given"); + + if(strlen(p->dhcp.file) != 0) + ADD_SUB_STRING("Boot file name", p->dhcp.file); + else + ADD_SUB_STRING("Boot file name", "not given"); + + ADD_SUB_STRING("Magic cookie", "DHCP"); + + U8 *opPointer; + opPointer = p->dhcp.options; + while (*opPointer && *opPointer != OPT_END) { + STR_OPT opTmp; + opTmp.op_code = *opPointer; + opPointer++; + opTmp.op_size = *opPointer; + opPointer++; + memcpy(opTmp.op_value, opPointer, opTmp.op_size); + opPointer += opTmp.op_size; + + s = sdsempty(); + sprintf(s, "(%u) %s", opTmp.op_code, dhcp_get_opName(opTmp.op_code)); + ADD_SUB_STRING("Option", s); + sdsfree(s); + + ADD_SUB_OPTION(opTmp.op_code, opTmp.op_size, opTmp.op_value); + } + + if(*opPointer == OPT_END) { + ADD_SUB_STRING("Option", "(255) End"); + } gtk_tree_view_set_model(GTK_TREE_VIEW(treeView), GTK_TREE_MODEL(store)); g_object_unref(GTK_TREE_MODEL(store)); @@ -273,7 +425,7 @@ void details_wnd_create(GtkBuilder *builder) { GtkWidget *vSepar = gtk_separator_new(GTK_ORIENTATION_VERTICAL); // 右侧 详细信息窗口 GtkWidget *scMsg = gtk_scrolled_window_new(NULL, NULL); - // 上下分割面包 + // 上下分割面板 GtkWidget *vpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL); gtk_container_add(GTK_CONTAINER(scMsg), vpaned); // 上半部分控件 diff --git a/srcs/service/dhcpd/dhcp_option.c b/srcs/service/dhcpd/dhcp_option.c index c3ebf7e..9580056 100644 --- a/srcs/service/dhcpd/dhcp_option.c +++ b/srcs/service/dhcpd/dhcp_option.c @@ -200,4 +200,22 @@ int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal) { } return -ERR_ITEM_UNEXISTS; +} + +const char* dhcp_get_opName(int opt) { + for(int i=0; i