diff --git a/dhcp_tools/detail_wnd.c b/dhcp_tools/detail_wnd.c
index b300144..e5b6dc3 100644
--- a/dhcp_tools/detail_wnd.c
+++ b/dhcp_tools/detail_wnd.c
@@ -8,68 +8,7 @@
 #include "dhcp_network.h"
 #include "sds/sds.h"
 #include "dhcp_options.h"
-
-static GtkWidget *g_detailWnd = NULL;
-
-#if 0
-static void dhcp_details_store_create(GtkBuilder *builder) {
-    int           i, j;
-    PDHCP_INFO    pInfo, pTemp;
-    GtkTreeIter   iter, iter_child;
-    GtkWidget    *view  = GTK_WIDGET(gtk_builder_get_object(builder, "tvDiscDhcp"));
-    GtkTreeStore *store = GTK_TREE_STORE(gtk_builder_get_object(builder, "lsDhcpInfo"));
-
-    gtk_tree_view_set_model(GTK_TREE_VIEW(view), NULL);
-    gtk_tree_store_clear(store);
-
-    // 创建根节点
-    gtk_tree_store_append(store, &iter, NULL);
-    // clang-format off
-	gtk_tree_store_set(store,
-		   &iter,
-		   COL_DHCP_ITEM,           "name",
-		   COL_DHCP_VALUE,          "",
-		   COL_ITEM_ATTR_VISIABLE,  TRUE,
-		   COL_VALUE_ATTR_VISIABLE, FALSE,
-		   -1);
-    // clang-format on
-    gtk_tree_store_append(store, &iter_child, &iter);
-
-    // clang-format off
-	// 创建子节点
-	gtk_tree_store_set(store,
-		   &iter_child,
-		    COL_DHCP_VALUE,          "",
-            COL_ITEM_ATTR_VISIABLE,  FALSE,
-            COL_VALUE_ATTR_VISIABLE, TRUE,
-		    -1);
-    // clang-format on
-    gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
-}
-
-
-void details_wnd_create(void *b) {
-    GtkBuilder *builder = gtk_builder_new();
-    gtk_builder_add_from_file(builder, "./res/detail.glade", NULL);
-
-    GtkWidget *deatilWnd = GTK_WIDGET(gtk_builder_get_object(builder, "wndDetails"));
-    GtkWidget *panDisc   = GTK_WIDGET(gtk_builder_get_object(builder, "hbDisc"));
-    GtkWidget *tab       = GTK_WIDGET(gtk_builder_get_object(builder, "nbDetails"));
-    GtkWidget *labDisc   = GTK_WIDGET(gtk_builder_get_object(builder, "labDiscover"));
-    GtkWidget *labAck    = GTK_WIDGET(gtk_builder_get_object(builder, "labAck"));
-    GtkWidget *scAck     = GTK_WIDGET(gtk_builder_get_object(builder, "scAck"));
-
-    gtk_container_add(GTK_CONTAINER(deatilWnd), tab);    // 笔记本放进窗口
-    gtk_notebook_append_page(GTK_NOTEBOOK(tab), panDisc, labDisc);
-    gtk_notebook_append_page(GTK_NOTEBOOK(tab), scAck, labAck);
-
-    g_signal_connect(G_OBJECT(deatilWnd), "delete_event", G_CALLBACK(delete_event), builder);
-    g_signal_connect(G_OBJECT(deatilWnd), "show", G_CALLBACK(show), builder);
-
-    gtk_builder_connect_signals(builder, NULL);
-    //gtk_widget_show(deatilWnd);
-}
-#endif
+#include "user_errno.h"
 
 typedef struct {
     U8 op_code;
@@ -77,17 +16,24 @@ typedef struct {
     U8 op_value[256];
 } STR_OPT;
 
-static char *g_mess_info[] = {"NONE", "DISCOVER", "OFFER", "REQUEST", "DECLINE", "ACK", "NAK", "RELEASE", "INFORM"};
-
+static GtkWidget     *g_detailWnd = NULL;
+static GtkWidget     *g_statusBar = NULL;
 static GtkTextBuffer *g_pTxtBuf[4];
 static GtkWidget     *g_ptvDHcp[4];
-static GtkWidget     *g_ptvHex[4];
+static guint          g_timer_id    = 0;
+static const char    *g_mess_info[] = {"NONE", "DISCOVER", "OFFER",   "REQUEST", "DECLINE",
+                                       "ACK",  "NAK",      "RELEASE", "INFORM"};
 
 static gboolean delete_event(GtkWidget *widget, GdkEventAny *event) {
     /* 如果你的 "delete_event" 信号处理函数返回 FALSE,GTK 会发出 "destroy" 信号。
     * 返回 TRUE,你不希望关闭窗口。
     * 当你想弹出“你确定要退出吗?”对话框时它很有用。*/
     //gtk_widget_hide_all(window_test);
+
+    if (g_timer_id) {
+        g_source_remove(g_timer_id);
+    }
+
     gtk_widget_hide(widget);
     return TRUE;    //注意必须为TRUE,否则子窗口点击关闭按钮后,就摧毁了,而不是隐藏了。
 }
@@ -288,13 +234,13 @@ static void create_dhcp_tree_mode(PDHCP_PACKAGE p, U32 nBytes, GtkWidget *treeVi
     ADD_SUB_STRING("Client MAC address", s);
     sdsfree(s);
 
-    if (strlen((char *)p->dhcp.sname) != 0) {
+    if (strlen((char *)p->dhcp.sname) > 0) {
         ADD_SUB_STRING("Server host name", p->dhcp.sname);
     } else {
         ADD_SUB_STRING("Server host name", "not given");
     }
 
-    if (strlen((char *)p->dhcp.file) != 0) {
+    if (strlen((char *)p->dhcp.file) > 0) {
         ADD_SUB_STRING("Boot file name", p->dhcp.file);
     } else {
         ADD_SUB_STRING("Boot file name", "not given");
@@ -332,6 +278,80 @@ static void create_dhcp_tree_mode(PDHCP_PACKAGE p, U32 nBytes, GtkWidget *treeVi
 
 static PDHCP_INFO g_preInfo = NULL;
 
+static gboolean timer_proc(gpointer user_data) {
+    int         ret;
+    DHCP_OPT    opt;
+    char        buf[1024] = {0};
+    S32         tmOffer = 0, tmAck = 0;
+    const char *pIp = NULL, *pNetmask = NULL, *pGw = NULL, *pDns1 = NULL, *pDns2 = NULL;
+
+    if (g_preInfo) {
+        tmOffer = MAX(0,
+                      (g_preInfo->pOfferBuf.tm.tv_sec * 1000000 + g_preInfo->pOfferBuf.tm.tv_usec) -
+                          (g_preInfo->pDiscBuf.tm.tv_sec * 1000000 + g_preInfo->pDiscBuf.tm.tv_usec));
+        tmAck   = MAX(0,
+                      (g_preInfo->pAckBuf.tm.tv_sec * 1000000 + g_preInfo->pAckBuf.tm.tv_usec) -
+                          (g_preInfo->pReqBuf.tm.tv_sec * 1000000 + g_preInfo->pReqBuf.tm.tv_usec));
+
+        if (g_preInfo->pAckBuf.p) {
+            PDHCP_PACKAGE pkg     = (PDHCP_PACKAGE)g_preInfo->pAckBuf.p;
+            U32           optSize = g_preInfo->pAckBuf.buf_size - sizeof(DHCP_PACKAGE);
+            pIp                   = u32_to_str_ip_safe(pkg->dhcp.yiaddr);
+
+            ret = dhcp_get_option(OPT_NETMASK, pkg->dhcp.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);
+            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);
+            if (ret == ERR_SUCCESS && opt.len >= sizeof(U32)) {
+                U32 *pVal = (U32 *)opt.pValue;
+                pDns1     = u32_to_str_ip_safe(*pVal);
+
+                if (opt.len > sizeof(U32)) {
+                    pVal++;
+                    pDns2 = u32_to_str_ip_safe(*pVal);
+                }
+            }
+        }
+    }
+
+    sprintf(buf, "Offer %d.%03ds | ACK %d.%03ds | ip: %s | netmask: %s | gateway: %s | dns1: %s | dns2: %s |",
+            tmOffer / 1000000, (tmOffer % 1000000) / 1000, tmAck / 1000000, (tmAck % 1000000) / 1000,
+            SAFETY_STR_STRING(pIp, ""), SAFETY_STR_STRING(pNetmask, ""), SAFETY_STR_STRING(pGw, ""),
+            SAFETY_STR_STRING(pDns1, ""), SAFETY_STR_STRING(pDns2, ""));
+
+    gtk_statusbar_pop(GTK_STATUSBAR(g_statusBar), 0);
+    gtk_statusbar_push(GTK_STATUSBAR(g_statusBar), 0, buf);
+
+    if (pIp) {
+        free((void *)pIp);
+    }
+
+    if (pDns1) {
+        free((void *)pDns1);
+    }
+
+    if (pDns2) {
+        free((void *)pDns2);
+    }
+
+    if (pGw) {
+        free((void *)pGw);
+    }
+
+    if (pNetmask) {
+        free((void *)pNetmask);
+    }
+
+    return FALSE;
+}
+
 void details_wnd_show(PDHCP_INFO pInfo) {
     int         i;
     PBUF_INFO   hexBuf[4];
@@ -410,6 +430,7 @@ void details_wnd_show(PDHCP_INFO pInfo) {
         }
     }
 
+    g_timer_id = g_timeout_add(1000, (GSourceFunc)timer_proc, NULL);
     gtk_widget_show_all(g_detailWnd);
 }
 
@@ -447,11 +468,15 @@ void details_wnd_create(GtkBuilder *builder) {
     GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
     //设置窗口大小
     gtk_widget_set_size_request(window, 900, 600);
+    GtkWidget *vBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
+    // 笔记本放进窗口
+    gtk_container_add(GTK_CONTAINER(window), vBox);
 
     // 创建笔记本控件
     GtkWidget *notebook = gtk_notebook_new();
-    // 笔记本放进窗口
-    gtk_container_add(GTK_CONTAINER(window), notebook);
+    // 笔记本放进 VBox
+    //gtk_container_add(GTK_CONTAINER(vBox), notebook);
+    gtk_box_pack_start(GTK_BOX(vBox), notebook, TRUE, TRUE, 0);
 
     // 页标签的位置,可以有四种位置:上、下、左或右。
     gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
@@ -530,9 +555,12 @@ void details_wnd_create(GtkBuilder *builder) {
         g_signal_connect(G_OBJECT(scText), "button_release_event", G_CALLBACK(button_release_event), builder);
 
         g_ptvDHcp[i] = tvDhcp;
-        g_ptvHex[i]  = tvHex;
     }
 
+    g_statusBar = gtk_statusbar_new();
+    gtk_box_pack_start(GTK_BOX(vBox), g_statusBar, FALSE, FALSE, 1);
+    //gtk_widget_set_size_request(vBox, -1, 16);
+
     g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_event), builder);
 
     g_detailWnd = window;
diff --git a/dhcp_tools/main_wnd.c b/dhcp_tools/main_wnd.c
index 7cfc3c1..b2b7339 100644
--- a/dhcp_tools/main_wnd.c
+++ b/dhcp_tools/main_wnd.c
@@ -645,6 +645,7 @@ int main(int args, char **argv) {
 
     details_wnd_create(g_mainBuilder);
     //hex_wnd_create(g_mainBuilder);
+    //statis_wnd_create(g_mainBuilder);
 #if 0
     gtk_list_store_new(NUM_COLS,
                        G_TYPE_INT,
diff --git a/srcs/libs/include/common.h b/srcs/libs/include/common.h
index 00b8221..45354f3 100644
--- a/srcs/libs/include/common.h
+++ b/srcs/libs/include/common.h
@@ -71,7 +71,7 @@ extern "C" {
 #endif
 
 #define VERIFY_STRING(s)     (((s) != NULL) && (strlen(s) > 0))
-#define SAFETY_STR_STRING(s) ((s) == NULL ? "NULL" : (s))
+#define SAFETY_STR_STRING(s, defval) ((s) == NULL ? (defval) : (s))
 
 #define MAX_IP_V4_STR        (16)
 #define MAX_MAC_ADDR_STR     (18)