diff --git a/dhcp_tools/detail_wnd.c b/dhcp_tools/detail_wnd.c
index bbfea6d..43546ec 100644
--- a/dhcp_tools/detail_wnd.c
+++ b/dhcp_tools/detail_wnd.c
@@ -20,20 +20,15 @@ static GtkWidget *g_detailWnd = NULL;
static GtkWidget *g_statusBar = NULL;
static GtkTextBuffer *g_pTxtBuf[4];
static GtkWidget *g_ptvDHcp[4];
-static guint g_timer_id = 0;
static PDHCP_INFO g_preInfo = NULL;
static const char *g_mess_info[] = {"NONE", "DISCOVER", "OFFER", "REQUEST", "DECLINE",
"ACK", "NAK", "RELEASE", "INFORM"};
-static gboolean delete_event(GtkWidget *widget, GdkEventAny *event) {
+static gboolean delete_event(GtkWidget *widget, GdkEventAny *UNUSED(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,否则子窗口点击关闭按钮后,就摧毁了,而不是隐藏了。
}
@@ -317,8 +312,6 @@ static gboolean upgrade_statusbar_proc(gpointer user_data) {
pDns2 = u32_to_str_ip_safe(*pVal);
}
}
-
- g_source_remove(g_timer_id);
}
}
@@ -433,11 +426,11 @@ void details_wnd_show(PDHCP_INFO pInfo) {
upgrade_statusbar_proc(pInfo);
}
- g_timer_id = g_timeout_add(1000, (GSourceFunc)upgrade_statusbar_proc, NULL);
+ upgrade_statusbar_proc(NULL);
gtk_widget_show_all(g_detailWnd);
}
-static gboolean button_release_event(GtkWidget *self, GdkEventButton event, gpointer user_data) {
+static gboolean button_release_event(GtkWidget *self, GdkEventButton UNUSED(event), gpointer UNUSED(user_data)) {
GtkTextIter iter, start_sel, end_sel;
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(self));
gtk_text_buffer_get_iter_at_mark(buffer, &iter, gtk_text_buffer_get_insert(buffer));
diff --git a/dhcp_tools/main.h b/dhcp_tools/main.h
index d91da3d..0fe9139 100644
--- a/dhcp_tools/main.h
+++ b/dhcp_tools/main.h
@@ -47,7 +47,8 @@ typedef enum {
typedef enum {
STA_WAIT_START = 0,
STA_SEND_REQ,
- STA_RECV_RSP
+ STA_RECV_RSP,
+ STA_ERROR
} DHCP_STATUS;
typedef struct {
@@ -85,5 +86,6 @@ void details_wnd_create(GtkBuilder *builder);
void details_wnd_show(PDHCP_INFO pInfo);
void hex_wnd_create(GtkBuilder *builder);
void hex_wnd_show(PDHCP_INFO pInfo);
+void statis_wnd_create(GtkBuilder *builder);
GtkBuilder *get_main_builder();
#endif //VCPE_MAIN_H
diff --git a/dhcp_tools/main_wnd.c b/dhcp_tools/main_wnd.c
index b2b7339..cd71155 100644
--- a/dhcp_tools/main_wnd.c
+++ b/dhcp_tools/main_wnd.c
@@ -9,18 +9,37 @@
#include "user_errno.h"
#include "zlog_module.h"
#include "dhcp_network.h"
+#include "dhcp_options.h"
+#include "ipaddr.h"
-#define DHCP_STEP_TIMEOUT (30)
+#define DHCP_STEP_TIMEOUT (5)
+#define DHCP_PKG_RETRY (3)
#define MAIN_WND_WIDTH (1024)
#define MAIN_WND_HEIGHT (768)
#define ZLOG_CFG_PATH "./config/zlog.conf"
-static GtkBuilder *g_mainBuilder = NULL;
-static PDHCP_INFO g_pDhcpInfo = NULL;
-static GThread *g_pEvLoopThread = NULL;
-static int g_runTask = FALSE;
+static GtkBuilder *g_mainBuilder = NULL;
+static PDHCP_INFO g_pDhcpInfo = NULL;
+static PDHCP_INFO g_pDhcpFinish = NULL;
+static GThread *g_pEvLoopThread = NULL;
+static int g_runTask = FALSE;
+static U32 g_totalTask = 0;
+static U32 g_finshTask = 0;
+static U32 g_errTask = 0;
+static U32 g_endTask = 0;
+static struct timeval g_StartTm;
+
+const char *dhcp_step_to_string(DHCP_STEP step) {
+ const char *stepName[] = {"STEP_BEGIN", "STEP_DISCOVER", "STEP_OFFER", "STEP_REQUEST", "STEP_ACK", "STEP_END"};
+
+ if (step > 0 && step < ARRAY_SIZE(stepName)) {
+ return stepName[step];
+ } else {
+ return "Unknown Step";
+ }
+}
GtkBuilder *get_main_builder() {
return g_mainBuilder;
@@ -74,6 +93,55 @@ static gboolean calc_step_progress(PDHCP_INFO pInfo, DHCP_STEP step) {
return FALSE;
}
+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);
+
+ 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_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);
+ }
+ }
+
+ snprintf(pInBuf, maxBuf, "IP: %s/%u, DNS: [%s, %s]", pIp, ipv4_mask_to_cidr(pNetmask), pDns1, pDns2);
+
+ if (pIp) {
+ free((void *)pIp);
+ }
+
+ if (pDns1) {
+ free((void *)pDns1);
+ }
+
+ if (pDns2) {
+ free((void *)pDns2);
+ }
+
+ if (pNetmask) {
+ free((void *)pNetmask);
+ }
+ } else {
+ pInBuf[0] = 0;
+ }
+}
+
void view_popup_menu_onStatistics(GtkWidget *UNUSED(menuitem), gpointer userdata) {
//PDHCP_INFO pInfo = (PDHCP_INFO)userdata;
//hex_wnd_show(pInfo);
@@ -182,6 +250,7 @@ static void tree_view_data_store_create() {
if (pInfo->vni == (nVni + i)) {
char idx[64] = {0};
char mac[24] = {0};
+
sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", pInfo->mac[0], pInfo->mac[1], pInfo->mac[2],
pInfo->mac[3], pInfo->mac[4], pInfo->mac[5]);
@@ -286,6 +355,33 @@ static void tree_view_data_store_create() {
#endif
}
+static gboolean upgrade_status_bar_msg(gpointer UNUSED(pInfo)) {
+ char buf[1024] = {0};
+ static S32 tmdiff = 0;
+ GtkWidget *statusBar = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "labMsg"));
+ GtkWidget *prgBar = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "prgTotal"));
+ double percnt = g_errTask + g_finshTask;
+
+ if (g_runTask) {
+ struct timeval tvNow;
+ gettimeofday(&tvNow, NULL);
+ tmdiff = MAX(0, (tvNow.tv_sec * 1000000 + tvNow.tv_usec) - (g_StartTm.tv_sec * 1000000 + g_StartTm.tv_usec));
+ }
+
+ sprintf(buf, "Statistics: total %d | successed %d | error %d | total time %d.%03d(seconds)", g_totalTask,
+ MIN(g_finshTask, g_totalTask), g_errTask, tmdiff / 1000000, (tmdiff % 1000000) / 1000);
+
+ gtk_label_set_text(GTK_LABEL(statusBar), buf);
+
+ if (g_totalTask > 0) {
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(prgBar), percnt / g_totalTask);
+ } else {
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(prgBar), 0.0);
+ }
+
+ return TRUE;
+}
+
static gboolean tree_view_data_store_upgade(gpointer pInfo) {
GtkTreeIter iter;
GtkTreeStore *store = GTK_TREE_STORE(gtk_builder_get_object(g_mainBuilder, "tsDhcpInfo"));
@@ -298,6 +394,8 @@ static gboolean tree_view_data_store_upgade(gpointer pInfo) {
model = GTK_TREE_MODEL(store);
if (model && gtk_tree_model_get_iter_from_string(model, &iter, ((PDHCP_INFO)pInfo)->treeId)) {
+ char info[256] = {0};
+ get_task_result(pInfo, info, 256);
// clang-format off
gtk_tree_store_set(store,
&iter,
@@ -305,12 +403,30 @@ static gboolean tree_view_data_store_upgade(gpointer pInfo) {
COL_OFFER, calc_step_progress(pInfo, STEP_OFFER),
COL_REQUEST, calc_step_progress(pInfo, STEP_REQUEST),
COL_ACK, calc_step_progress(pInfo, STEP_ACK),
- COL_RESULT, "",
+ COL_RESULT, info,
COL_STATUS, calc_total_progress(pInfo),
COL_ATTR_EDITABLE, FALSE,
COL_ATTR_VISIABLE, TRUE,
-1);
// clang-format on
+
+ if (strlen(info) > 0) {
+ g_endTask++;
+ }
+ }
+
+ if (g_finshTask + g_errTask == g_totalTask && g_endTask >= g_totalTask) {
+ GtkWidget *startButton = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbStart"));
+ GtkWidget *stoptButton = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbStop"));
+ GtkWidget *nicSelect = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "cbNicName"));
+ GtkWidget *tbExpand = GTK_WIDGET(gtk_builder_get_object(g_mainBuilder, "tbExpand"));
+
+ g_runTask = FALSE;
+ gtk_widget_set_sensitive(GTK_WIDGET(stoptButton), FALSE);
+ gtk_widget_set_sensitive(startButton, TRUE);
+ gtk_widget_set_sensitive(nicSelect, TRUE);
+ g_object_set(G_OBJECT(tbExpand), "stock_id", "gtk-indent", NULL);
+ upgrade_status_bar_msg(NULL);
}
return TRUE;
@@ -356,6 +472,8 @@ _Noreturn static void *dhcpThreadCb(void *UNUSED(pData)) {
continue;
}
+ g_idle_add(upgrade_status_bar_msg, NULL);
+
HASH_ITER(hh, g_pDhcpInfo, pInfo, pTemp) {
switch (pInfo->step) {
case STEP_BEGIN:
@@ -387,8 +505,14 @@ _Noreturn static void *dhcpThreadCb(void *UNUSED(pData)) {
gettimeofday(&now, NULL);
if (now.tv_sec - pInfo->pDiscBuf.tm.tv_sec > DHCP_STEP_TIMEOUT) {
- // 超时重传
- pInfo->status = STA_WAIT_START;
+ if (pInfo->pDiscBuf.snd < DHCP_PKG_RETRY) {
+ // 超时重传
+ pInfo->status = STA_WAIT_START;
+ } else {
+ pInfo->status = STA_ERROR;
+ g_errTask++;
+ g_idle_add(upgrade_status_bar_msg, NULL);
+ }
}
}
break;
@@ -423,19 +547,26 @@ _Noreturn static void *dhcpThreadCb(void *UNUSED(pData)) {
gettimeofday(&now, NULL);
if (now.tv_sec - pInfo->pReqBuf.tm.tv_sec > DHCP_STEP_TIMEOUT) {
- // 超时重传
- pInfo->status = STA_WAIT_START;
+ if (pInfo->pReqBuf.snd < DHCP_PKG_RETRY) {
+ // 超时重传
+ pInfo->status = STA_WAIT_START;
+ } else {
+ pInfo->status = STA_ERROR;
+ g_errTask++;
+ g_idle_add(upgrade_status_bar_msg, NULL);
+ }
}
}
break;
case STEP_ACK:
pInfo->step = STEP_END;
+ g_finshTask++;
+ g_idle_add(upgrade_status_bar_msg, NULL);
break;
case STEP_END:
break;
}
}
-
g_usleep(100);
}
@@ -486,6 +617,8 @@ static void mainWnd_on_tb_start(GObject *object, gpointer UNUSED(user_data)) {
U32 nVni = (U32)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vniStart));
U32 nVniCnt = (U32)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(numVniCli));
+ g_totalTask = g_finshTask = g_errTask = g_endTask = 0;
+
string_mac_to_bytes(strMacBegin, mac);
macVal = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
@@ -517,6 +650,7 @@ static void mainWnd_on_tb_start(GObject *object, gpointer UNUSED(user_data)) {
HASH_ADD_INT(g_pDhcpInfo, index, pInfo);
index++;
+ g_totalTask++;
}
}
@@ -531,6 +665,7 @@ static void mainWnd_on_tb_start(GObject *object, gpointer UNUSED(user_data)) {
dhcp_tools_init_network(pCobText);
g_runTask = TRUE;
+ gettimeofday(&g_StartTm, NULL);
}
static void mainWnd_on_tb_stop(GObject *object, gpointer UNUSED(user_data)) {
@@ -668,6 +803,7 @@ int main(int args, char **argv) {
gtk_builder_connect_signals(g_mainBuilder, NULL);
gtk_widget_show(mainWnd);
+ upgrade_status_bar_msg(NULL);
g_pEvLoopThread = g_thread_new("uv_loop", uv_loop_thread, NULL);
g_thread_new("dhcp", dhcpThreadCb, NULL);
diff --git a/dhcp_tools/res/detail.glade b/dhcp_tools/res/detail.glade
index 57ff73f..7974059 100644
--- a/dhcp_tools/res/detail.glade
+++ b/dhcp_tools/res/detail.glade
@@ -187,7 +187,23 @@
-
+
+
+ True
+ True
+
diff --git a/dhcp_tools/res/main.glade b/dhcp_tools/res/main.glade
index ce3b076..d377365 100644
--- a/dhcp_tools/res/main.glade
+++ b/dhcp_tools/res/main.glade
@@ -592,8 +592,9 @@
Progress
0.5
-
+
+ 11
9
@@ -640,13 +641,30 @@
-
diff --git a/srcs/libs/include/ipaddr.h b/srcs/libs/include/ipaddr.h
index b35e4e7..0bfdf09 100644
--- a/srcs/libs/include/ipaddr.h
+++ b/srcs/libs/include/ipaddr.h
@@ -11,6 +11,7 @@ extern "C" {
U32 ipv4_get_network_addr(U32 ipAddr, U32 netmask);
U32 ipv4_get_boardcast_addr(U32 ipAddr, U32 netmask);
U32 ipv4_network_total_addr(U32 netmask);
+U32 ipv4_mask_to_cidr(const char * netmask);
#ifdef __cplusplus
}
#endif
diff --git a/srcs/libs/ipaddr/ipaddr.c b/srcs/libs/ipaddr/ipaddr.c
index 2994d59..3959ce0 100644
--- a/srcs/libs/ipaddr/ipaddr.c
+++ b/srcs/libs/ipaddr/ipaddr.c
@@ -1,8 +1,11 @@
//
// Created by xajhuang on 2023/3/21.
//
+#include
#include "ipaddr.h"
+#define BIT_TEST(c, i) ((c[(i) / 8] & (1 << ((i) % 8))) ? 1 : 0)
+
U32 ipv4_get_network_addr(U32 ipAddr, U32 netmask) {
return (ipAddr & netmask);
}
@@ -13,4 +16,22 @@ U32 ipv4_get_boardcast_addr(U32 ipAddr, U32 netmask) {
U32 ipv4_network_total_addr(U32 netmask) {
return (~netmask) + 1;
+}
+
+U32 ipv4_mask_to_cidr(const char *netmask) {
+ const char *cidr[] = {"128.0.0.0", "192.0.0.0", "224.0.0.0", "240.0.0.0", "248.0.0.0",
+ "252.0.0.0", "254.0.0.0", "255.0.0.0", "255.128.0.0", "255.192.0.0",
+ "255.224.0.0", "255.240.0.0", "255.248.0.0", "255.252.0.0", "255.254.0.0",
+ "255.255.0.0", "255.255.128.0", "255.255.192.0", "255.255.224.0", "255.255.240.0",
+ "255.255.248.0", "255.255.252.0", "255.255.254.0", "255.255.255.0", "255.255.255.128",
+ "255.255.255.192", "255.255.255.224", "255.255.255.240", "255.255.255.248", "255.255.255.252",
+ "255.255.255.254", "255.255.255.255"};
+
+ for(int i = 0; i < ARRAY_SIZE(cidr); i++) {
+ if(strcmp(cidr[i], netmask) == 0) {
+ return i + 1;
+ }
+ }
+
+ return 0xFF;
}
\ No newline at end of file
diff --git a/srcs/service/dhcpd/dhcpd_network.c b/srcs/service/dhcpd/dhcpd_network.c
index 68fee7c..07d104e 100644
--- a/srcs/service/dhcpd/dhcpd_network.c
+++ b/srcs/service/dhcpd/dhcpd_network.c
@@ -476,6 +476,13 @@ static void on_sock_recv(uv_work_t *req) {
} else {
LOG_MOD(error, ZM_DHCP_NET, "DHCP prepare assign ipaddress error: User %u [%s(%s)] resion %s\n",
reqDhcp.uid, macStr, reqDhcp.hostName, getErrorEnumNameString(ret));
+
+ // Send NACK
+ ret = dhcp_resp_nack(pkg);
+ }
+
+ if (ret != ERR_SUCCESS) {
+ LOG_MOD(error, ZM_DHCP_NET, "Send Offer error: %d\n", ret);
}
// endregion
break;
@@ -507,9 +514,10 @@ static void on_sock_recv(uv_work_t *req) {
}
// 当改请求的服务端不是本机时,忽略该消息
- if (reqDhcp.reqServer != ntohl(g_nicInfo.ipAddr)) {
+ if (reqDhcp.reqServer != ntohl(g_nicInfo.ipAddr) && reqDhcp.reqServer != 0) {
const char *pReq = u32_to_str_ip_safe(htonl(reqDhcp.reqServer));
const char *pLocal = u32_to_str_ip_safe(g_nicInfo.ipAddr);
+ LOG_MOD_HEX(error, ZM_DHCP_NET, pWork->pPkgBase, pWork->nSize);
LOG_MOD(debug, ZM_DHCP_NET, "Receive others server's DHCP request: request need %s, localhost %s\n",
pReq, pLocal);
free((void *)pReq);
@@ -529,7 +537,7 @@ static void on_sock_recv(uv_work_t *req) {
}
if (ret != ERR_SUCCESS) {
- LOG_MOD(error, ZM_DHCP_NET, "Send Offer error: %d\n", ret);
+ LOG_MOD(error, ZM_DHCP_NET, "Send Ack error: %d\n", ret);
}
}
// endregion