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 + vertical + + + + + + + + + + + + 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 @@ - + True - 2 + + + 682 + True + 0.0099999997764825821 + + + 0 + + + + + True + True + + + 1 + + False - False 5 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