5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10 * needed by dissect routines
11 * Jeff Foster, 2001/03/12, added support tabbed hex display windowss
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <gdk/gdkkeysyms.h>
44 #ifdef NEED_STRERROR_H
45 #include "wsutil/strerror.h"
51 #include "wsutil/wsgetopt.h"
54 #ifdef _WIN32 /* Needed for console I/O */
59 #ifdef HAVE_LIBPORTAUDIO
60 #include <portaudio.h>
61 #endif /* HAVE_LIBPORTAUDIO */
63 #include <epan/epan.h>
64 #include <epan/filesystem.h>
65 #include <wsutil/privileges.h>
66 #include <epan/epan_dissect.h>
67 #include <epan/timestamp.h>
68 #include <epan/packet.h>
69 #include <epan/plugins.h>
70 #include <epan/dfilter/dfilter.h>
71 #include <epan/strutil.h>
72 #include <epan/addr_resolv.h>
73 #include <epan/emem.h>
74 #include <epan/ex-opt.h>
75 #include <epan/funnel.h>
76 #include <epan/expert.h>
77 #include <epan/frequency-utils.h>
78 #include <epan/prefs.h>
79 #include <epan/prefs-int.h>
81 #include <epan/stat_cmd_args.h>
83 #include <epan/column.h>
85 /* general (not GTK specific) */
87 #include "../summary.h"
88 #include "../filters.h"
89 #include "../disabled_protos.h"
91 #include "../color_filters.h"
93 #include "../simple_dialog.h"
94 #include "../main_statusbar.h"
95 #include "../register.h"
96 #include "../ringbuffer.h"
97 #include "../ui_util.h"
99 #include "../clopts_common.h"
100 #include "../console_io.h"
101 #include "../cmdarg_err.h"
102 #include "../version_info.h"
103 #include "../merge.h"
104 #include "../alert_box.h"
107 #include <wsutil/file_util.h>
110 #include "../capture_ui_utils.h"
111 #include "../capture-pcap-util.h"
112 #include "../capture_ifinfo.h"
113 #include "../capture.h"
114 #include "../capture_sync.h"
118 #include "../capture-wpcap.h"
119 #include "../capture_wpcap_packet.h"
120 #include <tchar.h> /* Needed for Unicode */
121 #include <commctrl.h>
122 #include <shellapi.h>
126 #include "gtk/file_dlg.h"
127 #include "gtk/gtkglobals.h"
128 #include "gtk/color_utils.h"
129 #include "gtk/gui_utils.h"
130 #include "gtk/color_dlg.h"
131 #include "gtk/filter_dlg.h"
132 #include "gtk/uat_gui.h"
133 #include "gtk/main.h"
134 #include "gtk/main_airpcap_toolbar.h"
135 #include "gtk/main_filter_toolbar.h"
136 #include "gtk/menus.h"
137 #include "gtk/macros_dlg.h"
138 #include "gtk/main_packet_list.h"
139 #include "gtk/main_statusbar_private.h"
140 #include "gtk/main_toolbar.h"
141 #include "gtk/main_welcome.h"
142 #include "gtk/drag_and_drop.h"
143 #include "gtk/capture_file_dlg.h"
144 #include "gtk/main_proto_draw.h"
145 #include "gtk/keys.h"
146 #include "gtk/packet_win.h"
147 #include "gtk/stock_icons.h"
148 #include "gtk/find_dlg.h"
149 #include "gtk/recent.h"
150 #include "gtk/follow_tcp.h"
151 #include "gtk/font_utils.h"
152 #include "gtk/about_dlg.h"
153 #include "gtk/help_dlg.h"
154 #include "gtk/decode_as_dlg.h"
155 #include "gtk/webbrowser.h"
156 #include "gtk/capture_dlg.h"
157 #include "gtk/capture_if_dlg.h"
158 #include "gtk/tap_dfilter_dlg.h"
159 #include "gtk/prefs_column.h"
160 #include "gtk/prefs_dlg.h"
161 #include "gtk/proto_help.h"
164 #include "../image/wsicon16.xpm"
165 #include "../image/wsicon32.xpm"
166 #include "../image/wsicon48.xpm"
167 #include "../image/wsicon64.xpm"
168 #include "../image/wsiconcap16.xpm"
169 #include "../image/wsiconcap32.xpm"
170 #include "../image/wsiconcap48.xpm"
175 #include "airpcap_loader.h"
176 #include "airpcap_dlg.h"
177 #include "airpcap_gui_utils.h"
181 #include <epan/crypt/airpdcap_ws.h>
184 #ifdef NEW_PACKET_LIST
185 #include "gtk/new_packet_list.h"
188 #ifdef HAVE_GTKOSXAPPLICATION
189 #include <igemacintegration/gtkosxapplication.h>
193 * Files under personal and global preferences directories in which
194 * GTK settings for Wireshark are stored.
196 #define RC_FILE "gtkrc"
200 /* "exported" main widgets */
201 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view_gbl, *byte_nb_ptr_gbl;
203 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
204 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
205 static GtkWidget *main_first_pane, *main_second_pane;
207 /* internally used widgets */
208 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
211 GtkWidget *airpcap_tb;
212 int airpcap_dll_ret_val = -1;
215 GString *comp_info_str, *runtime_info_str;
217 static gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
219 static guint tap_update_timer_id;
222 static gboolean has_console; /* TRUE if app has console */
223 static void destroy_console(void);
224 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
226 static void console_log_handler(const char *log_domain,
227 GLogLevelFlags log_level, const char *message, gpointer user_data);
230 capture_options global_capture_opts;
234 static void create_main_window(gint, gint, gint, e_prefs*);
235 static void show_main_window(gboolean);
236 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
237 static void main_save_window_geometry(GtkWidget *widget);
240 /* Match selected byte pattern */
242 match_selected_cb_do(gpointer data, int action, gchar *text)
244 GtkWidget *filter_te;
245 char *cur_filter, *new_filter;
247 if ((!text) || (0 == strlen(text))) {
248 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
253 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
256 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
258 switch (action&MATCH_SELECTED_MASK) {
260 case MATCH_SELECTED_REPLACE:
261 new_filter = g_strdup(text);
264 case MATCH_SELECTED_AND:
265 if ((!cur_filter) || (0 == strlen(cur_filter)))
266 new_filter = g_strdup(text);
268 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
271 case MATCH_SELECTED_OR:
272 if ((!cur_filter) || (0 == strlen(cur_filter)))
273 new_filter = g_strdup(text);
275 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
278 case MATCH_SELECTED_NOT:
279 new_filter = g_strconcat("!(", text, ")", NULL);
282 case MATCH_SELECTED_AND_NOT:
283 if ((!cur_filter) || (0 == strlen(cur_filter)))
284 new_filter = g_strconcat("!(", text, ")", NULL);
286 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
289 case MATCH_SELECTED_OR_NOT:
290 if ((!cur_filter) || (0 == strlen(cur_filter)))
291 new_filter = g_strconcat("!(", text, ")", NULL);
293 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
297 g_assert_not_reached();
302 /* Free up the copy we got of the old filter text. */
305 /* Don't change the current display filter if we only want to copy the filter */
306 if (action&MATCH_SELECTED_COPY_ONLY) {
307 GString *gtk_text_str = g_string_new("");
308 g_string_append(gtk_text_str, new_filter);
309 copy_to_clipboard(gtk_text_str);
310 g_string_free(gtk_text_str, TRUE);
312 /* create a new one and set the display filter entry accordingly */
313 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
315 /* Run the display filter so it goes in effect. */
316 if (action&MATCH_SELECTED_APPLY_NOW)
317 main_filter_packets(&cfile, new_filter, FALSE);
320 /* Free up the new filter text. */
325 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
329 if (cfile.finfo_selected) {
330 filter = proto_construct_match_selected_string(cfile.finfo_selected,
332 match_selected_cb_do((data ? data : w), action, filter);
337 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
341 if (cfile.finfo_selected) {
342 filter = proto_construct_match_selected_string(cfile.finfo_selected,
344 if ((!filter) || (0 == strlen(filter))) {
345 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
346 "Could not acquire information to build a filter!\n"
347 "Try expanding or choosing another item.");
352 color_display_with_filter(filter);
355 color_filters_reset_tmp();
357 color_filters_set_tmp(filt_nr,filter, FALSE);
359 #ifdef NEW_PACKET_LIST
360 new_packet_list_colorize_packets();
362 cf_colorize_packets(&cfile);
369 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
371 gchar *selected_proto_url;
372 gchar *proto_abbrev = data;
377 if (cfile.finfo_selected) {
378 /* open wiki page using the protocol abbreviation */
379 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
380 browser_open_url(selected_proto_url);
381 g_free(selected_proto_url);
384 case(ESD_BTN_CANCEL):
387 g_assert_not_reached();
393 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
396 const gchar *proto_abbrev;
400 if (cfile.finfo_selected) {
401 /* convert selected field to protocol abbreviation */
402 /* XXX - could this conversion be simplified? */
403 field_id = cfile.finfo_selected->hfinfo->id;
404 /* if the selected field isn't a protocol, get it's parent */
405 if(!proto_registrar_is_protocol(field_id)) {
406 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
409 proto_abbrev = proto_registrar_get_abbrev(field_id);
411 if (!proto_is_private(field_id)) {
412 /* ask the user if the wiki page really should be opened */
413 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
414 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
416 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
418 "The Wireshark Wiki is a collaborative approach to provide information "
419 "about Wireshark in several ways (not limited to protocol specifics).\n"
421 "This Wiki is new, so the page of the selected protocol "
422 "may not exist and/or may not contain valuable information.\n"
424 "As everyone can edit the Wiki and add new content (or extend existing), "
425 "you are encouraged to add information if you can.\n"
427 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
429 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
430 "which will save you a lot of editing and will give a consistent look over the pages.",
431 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
432 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
434 /* appologize to the user that the wiki page cannot be opened */
435 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
436 "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
438 "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
440 "Since this is a private protocol, such information is not available in "
441 "a public wiki. Therefore this wiki entry is blocked.\n"
443 "Sorry for the inconvenience.\n",
444 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
449 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
451 gchar *selected_proto_url;
452 gchar *proto_abbrev = data;
456 if (cfile.finfo_selected) {
457 /* open reference page using the protocol abbreviation */
458 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
459 browser_open_url(selected_proto_url);
460 g_free(selected_proto_url);
463 case(ESD_BTN_CANCEL):
466 g_assert_not_reached();
471 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
474 const gchar *proto_abbrev;
478 if (cfile.finfo_selected) {
479 /* convert selected field to protocol abbreviation */
480 /* XXX - could this conversion be simplified? */
481 field_id = cfile.finfo_selected->hfinfo->id;
482 /* if the selected field isn't a protocol, get it's parent */
483 if(!proto_registrar_is_protocol(field_id)) {
484 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
487 proto_abbrev = proto_registrar_get_abbrev(field_id);
489 if (!proto_is_private(field_id)) {
490 /* ask the user if the wiki page really should be opened */
491 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
492 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
494 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
496 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
497 simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
499 /* appologize to the user that the wiki page cannot be opened */
500 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
501 "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
503 "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
505 "Since this is a private protocol, such information is not available on "
506 "a public website. Therefore this filter entry is blocked.\n"
508 "Sorry for the inconvenience.\n",
509 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
515 is_address_column (gint column)
517 if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
518 (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
519 (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
520 (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
521 strlen(cfile.cinfo.col_expr.col_expr_val[column]))
530 get_ip_address_list_from_packet_list_row(gpointer data)
532 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
533 #ifdef NEW_PACKET_LIST
534 gint column = new_packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
536 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
540 GList *addr_list = NULL;
542 #ifdef NEW_PACKET_LIST
543 fdata = (frame_data *) new_packet_list_get_row_data(row);
545 fdata = (frame_data *) packet_list_get_row_data(row);
551 if (!cf_read_frame (&cfile, fdata))
552 return NULL; /* error reading the frame */
554 epan_dissect_init(&edt, FALSE, FALSE);
555 col_custom_prime_edt(&edt, &cfile.cinfo);
557 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
558 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
560 /* First check selected column */
561 if (is_address_column (column)) {
562 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
565 for (col = 0; col < cfile.cinfo.num_cols; col++) {
566 /* Then check all columns except the selected */
567 if ((col != column) && (is_address_column (col))) {
568 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
572 epan_dissect_cleanup(&edt);
579 get_filter_from_packet_list_row_and_column(gpointer data)
581 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
582 #ifdef NEW_PACKET_LIST
583 gint column = new_packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
585 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
590 #ifdef NEW_PACKET_LIST
591 fdata = (frame_data *) new_packet_list_get_row_data(row);
593 fdata = (frame_data *) packet_list_get_row_data(row);
599 if (!cf_read_frame(&cfile, fdata))
600 return NULL; /* error reading the frame */
601 /* proto tree, visible. We need a proto tree if there's custom columns */
602 epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
603 col_custom_prime_edt(&edt, &cfile.cinfo);
605 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata,
607 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
609 if ((cfile.cinfo.col_custom_occurrence[column]) ||
610 (strchr (cfile.cinfo.col_expr.col_expr_val[column], ',') == NULL))
612 /* Only construct the filter when a single occurrence is displayed
613 * otherwise we might end up with a filter like "ip.proto==1,6".
615 * Or do we want to be able to filter on multiple occurrences so that
616 * the filter might be calculated as "ip.proto==1 && ip.proto==6"
619 if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
620 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
621 /* leak a little but safer than ep_ here */
622 if (cfile.cinfo.col_fmt[column] == COL_CUSTOM) {
623 header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[column]);
624 if (hfi->parent == -1) {
626 buf = se_strdup(cfile.cinfo.col_expr.col_expr[column]);
627 } else if (hfi->type == FT_STRING) {
628 /* Custom string, add quotes */
629 buf = se_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
630 cfile.cinfo.col_expr.col_expr_val[column]);
634 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
635 cfile.cinfo.col_expr.col_expr_val[column]);
640 epan_dissect_cleanup(&edt);
647 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
649 match_selected_cb_do(data,
651 get_filter_from_packet_list_row_and_column(data));
654 /* This function allows users to right click in the details window and copy the text
655 * information to the operating systems clipboard.
657 * We first check to see if a string representation is setup in the tree and then
658 * read the string. If not available then we try to grab the value. If all else
659 * fails we display a message to the user to indicate the copy could not be completed.
662 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
664 GString *gtk_text_str = g_string_new("");
665 char labelstring[256];
666 char *stringpointer = labelstring;
670 case COPY_SELECTED_DESCRIPTION:
671 if (cfile.finfo_selected->rep->representation != 0) {
672 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
675 case COPY_SELECTED_FIELDNAME:
676 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
677 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
680 case COPY_SELECTED_VALUE:
681 if (cfile.edt !=0 ) {
682 g_string_append(gtk_text_str,
683 get_node_field_value(cfile.finfo_selected, cfile.edt));
690 if (gtk_text_str->len == 0) {
691 /* If no representation then... Try to read the value */
692 proto_item_fill_label(cfile.finfo_selected, stringpointer);
693 g_string_append(gtk_text_str, stringpointer);
696 if (gtk_text_str->len == 0) {
697 /* Could not get item so display error msg */
698 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
700 /* Copy string to clipboard */
701 copy_to_clipboard(gtk_text_str);
703 g_string_free(gtk_text_str, TRUE); /* Free the memory */
707 /* mark as reference time frame */
709 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
713 frame->flags.ref_time=1;
714 cfile.ref_time_count++;
716 frame->flags.ref_time=0;
717 cfile.ref_time_count--;
719 cf_reftime_packets(&cfile);
720 #ifdef NEW_PACKET_LIST
721 if (!frame->flags.ref_time && !frame->flags.passed_dfilter) {
722 new_packet_list_freeze();
723 cfile.displayed_count--;
724 new_packet_list_recreate_visible_rows();
725 new_packet_list_thaw();
727 new_packet_list_queue_draw();
732 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
736 timestamp_set_type(TS_RELATIVE);
737 recent.gui_time_format = TS_RELATIVE;
738 #ifdef NEW_PACKET_LIST
739 cf_timestamp_auto_precision(&cfile);
740 new_packet_list_queue_draw();
742 cf_change_time_formats(&cfile);
748 g_assert_not_reached();
751 if (cfile.current_frame) {
752 set_frame_reftime(!cfile.current_frame->flags.ref_time,
753 cfile.current_frame, cfile.current_row);
759 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
761 static GtkWidget *reftime_dialog = NULL;
765 if (cfile.current_frame) {
766 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
767 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
768 "%sSwitch to the appropriate Time Display Format?%s\n\n"
769 "Time References don't work well with the currently selected Time Display Format.\n\n"
770 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
771 simple_dialog_primary_start(), simple_dialog_primary_end());
772 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
774 set_frame_reftime(!cfile.current_frame->flags.ref_time,
775 cfile.current_frame, cfile.current_row);
779 case REFTIME_FIND_NEXT:
780 cf_find_packet_time_reference(&cfile, SD_FORWARD);
782 case REFTIME_FIND_PREV:
783 cf_find_packet_time_reference(&cfile, SD_BACKWARD);
789 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
791 cf_find_packet_marked(&cfile, SD_FORWARD);
795 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
797 cf_find_packet_marked(&cfile, SD_BACKWARD);
801 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
804 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
806 gboolean has_blurb = FALSE;
807 guint length = 0, byte_len;
808 GtkWidget *byte_view;
809 const guint8 *byte_data;
814 /* if nothing is selected */
815 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
818 * Which byte view is displaying the current protocol tree
821 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
822 if (byte_view == NULL)
825 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
826 if (byte_data == NULL)
829 cf_unselect_field(&cfile);
830 packet_hex_print(byte_view, byte_data,
831 cfile.current_frame, NULL, byte_len);
832 proto_help_menu_modify(sel, &cfile);
835 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
838 set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
840 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
841 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
842 g_assert(byte_data != NULL);
844 cfile.finfo_selected = finfo;
845 set_menus_for_selected_tree_row(&cfile);
848 if (finfo->hfinfo->blurb != NULL &&
849 finfo->hfinfo->blurb[0] != '\0') {
851 length = (guint) strlen(finfo->hfinfo->blurb);
853 length = (guint) strlen(finfo->hfinfo->name);
855 finfo_length = finfo->length + finfo->appendix_length;
857 if (finfo_length == 0) {
859 } else if (finfo_length == 1) {
860 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
862 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
864 statusbar_pop_field_msg(); /* get rid of current help msg */
866 statusbar_push_field_msg(" %s (%s)%s",
867 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
868 finfo->hfinfo->abbrev, len_str);
871 * Don't show anything if the field name is zero-length;
872 * the pseudo-field for "proto_tree_add_text()" is such
873 * a field, and we don't want "Text (text)" showing up
874 * on the status line if you've selected such a field.
876 * XXX - there are zero-length fields for which we *do*
877 * want to show the field name.
879 * XXX - perhaps the name and abbrev field should be null
880 * pointers rather than null strings for that pseudo-field,
881 * but we'd have to add checks for null pointers in some
882 * places if we did that.
884 * Or perhaps protocol tree items added with
885 * "proto_tree_add_text()" should have -1 as the field index,
886 * with no pseudo-field being used, but that might also
887 * require special checks for -1 to be added.
889 statusbar_push_field_msg("%s", "");
892 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
894 proto_help_menu_modify(sel, &cfile);
897 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
899 collapse_all_tree(cfile.edt->tree, tree_view_gbl);
902 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
904 expand_all_tree(cfile.edt->tree, tree_view_gbl);
907 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
909 if (cfile.finfo_selected) {
910 column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
911 cfile.finfo_selected->hfinfo->abbrev,0);
912 /* Recreate the packet list according to new preferences */
913 #ifdef NEW_PACKET_LIST
914 new_packet_list_recreate ();
916 packet_list_recreate ();
918 if (!prefs.gui_use_pref_save) {
921 cfile.cinfo.columns_changed = FALSE; /* Reset value */
925 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
928 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
930 /* the mouse position is at an entry, expand that one */
931 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
932 gtk_tree_path_free(path);
936 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
937 if (cfile.edt->tree) {
938 guint32 tmp = gbl_resolv_flags;
939 gbl_resolv_flags = RESOLV_ALL;
940 proto_tree_draw(cfile.edt->tree, tree_view_gbl);
941 gbl_resolv_flags = tmp;
946 main_set_for_capture_file(gboolean have_capture_file_in)
948 have_capture_file = have_capture_file_in;
950 main_widgets_show_or_hide();
956 /* get the current geometry, before writing it to disk */
957 main_save_window_geometry(top_level);
959 /* write user's recent file to disk
960 * It is no problem to write this file, even if we do not quit */
961 write_profile_recent();
964 /* XXX - should we check whether the capture file is an
965 unsaved temporary file for a live capture and, if so,
966 pop up a "do you want to exit without saving the capture
967 file?" dialog, and then just return, leaving said dialog
968 box to forcibly quit if the user clicks "OK"?
970 If so, note that this should be done in a subroutine that
971 returns TRUE if we do so, and FALSE otherwise, and if it
972 returns TRUE we should return TRUE without nuking anything.
974 Note that, if we do that, we might also want to check if
975 an "Update list of packets in real time" capture is in
976 progress and, if so, ask whether they want to terminate
977 the capture and discard it, and return TRUE, before nuking
978 any child capture, if they say they don't want to do so. */
981 /* Nuke any child capture in progress. */
982 capture_kill_child(&global_capture_opts);
985 /* Are we in the middle of reading a capture? */
986 if (cfile.state == FILE_READ_IN_PROGRESS) {
987 /* Yes, so we can't just close the file and quit, as
988 that may yank the rug out from under the read in
989 progress; instead, just set the state to
990 "FILE_READ_ABORTED" and return - the code doing the read
991 will check for that and, if it sees that, will clean
993 cfile.state = FILE_READ_ABORTED;
995 /* Say that the window should *not* be deleted;
996 that'll be done by the code that cleans up. */
999 /* Close any capture file we have open; on some OSes, you
1000 can't unlink a temporary capture file if you have it
1002 "cf_close()" will unlink it after closing it if
1003 it's a temporary file.
1005 We do this here, rather than after the main loop returns,
1006 as, after the main loop returns, the main window may have
1007 been destroyed (if this is called due to a "destroy"
1008 even on the main window rather than due to the user
1009 selecting a menu item), and there may be a crash
1010 or other problem when "cf_close()" tries to
1011 clean up stuff in the main window.
1013 XXX - is there a better place to put this?
1014 Or should we have a routine that *just* closes the
1015 capture file, and doesn't do anything with the UI,
1016 which we'd call here, and another routine that
1017 calls that routine and also cleans up the UI, which
1018 we'd call elsewhere? */
1021 /* Exit by leaving the main loop, so that any quit functions
1022 we registered get called. */
1025 /* Say that the window should be deleted. */
1031 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1035 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1036 gtk_window_present(GTK_WINDOW(top_level));
1037 /* user didn't saved his current file, ask him */
1038 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1039 "%sSave capture file before program quit?%s\n\n"
1040 "If you quit the program without saving, your capture data will be discarded.",
1041 simple_dialog_primary_start(), simple_dialog_primary_end());
1042 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1045 /* unchanged file, just exit */
1046 /* "main_do_quit()" indicates whether the main window should be deleted. */
1047 return main_do_quit();
1053 main_pane_load_window_geometry(void)
1055 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1056 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1057 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
1058 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1064 main_load_window_geometry(GtkWidget *widget)
1066 window_geometry_t geom;
1068 geom.set_pos = prefs.gui_geometry_save_position;
1069 geom.x = recent.gui_geometry_main_x;
1070 geom.y = recent.gui_geometry_main_y;
1071 geom.set_size = prefs.gui_geometry_save_size;
1072 if (recent.gui_geometry_main_width > 0 &&
1073 recent.gui_geometry_main_height > 0) {
1074 geom.width = recent.gui_geometry_main_width;
1075 geom.height = recent.gui_geometry_main_height;
1076 geom.set_maximized = prefs.gui_geometry_save_maximized;
1078 /* We assume this means the width and height weren't set in
1079 the "recent" file (or that there is no "recent" file),
1080 and weren't set to a default value, so we don't set the
1081 size. (The "recent" file code rejects non-positive width
1082 and height values.) */
1083 geom.set_size = FALSE;
1085 geom.maximized = recent.gui_geometry_main_maximized;
1087 window_set_geometry(widget, &geom);
1089 main_pane_load_window_geometry();
1090 statusbar_load_window_geometry();
1095 main_save_window_geometry(GtkWidget *widget)
1097 window_geometry_t geom;
1099 window_get_geometry(widget, &geom);
1101 if (prefs.gui_geometry_save_position) {
1102 recent.gui_geometry_main_x = geom.x;
1103 recent.gui_geometry_main_y = geom.y;
1106 if (prefs.gui_geometry_save_size) {
1107 recent.gui_geometry_main_width = geom.width;
1108 recent.gui_geometry_main_height = geom.height;
1111 if(prefs.gui_geometry_save_maximized) {
1112 recent.gui_geometry_main_maximized = geom.maximized;
1115 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1116 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1117 statusbar_save_window_geometry();
1120 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1124 /* save file first */
1125 file_save_as_cmd(after_save_exit, NULL);
1127 case(ESD_BTN_QUIT_DONT_SAVE):
1130 case(ESD_BTN_CANCEL):
1133 g_assert_not_reached();
1138 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1142 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1143 /* user didn't saved his current file, ask him */
1144 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1145 "%sSave capture file before program quit?%s\n\n"
1146 "If you quit the program without saving, your capture data will be discarded.",
1147 simple_dialog_primary_start(), simple_dialog_primary_end());
1148 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1150 /* unchanged file, just exit */
1156 print_usage(gboolean print_ver) {
1166 fprintf(output, "Wireshark " VERSION "%s\n"
1167 "Interactively dump and analyze network traffic.\n"
1168 "See http://www.wireshark.org for more information.\n"
1171 wireshark_svnversion, get_copyright_info());
1175 fprintf(output, "\n");
1176 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1177 fprintf(output, "\n");
1180 fprintf(output, "Capture interface:\n");
1181 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1182 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1183 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1184 fprintf(output, " -p don't capture in promiscuous mode\n");
1185 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1186 fprintf(output, " -Q quit Wireshark after capturing\n");
1187 fprintf(output, " -S update packet display when new packets are captured\n");
1188 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1189 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
1190 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1192 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1193 fprintf(output, " -D print list of interfaces and exit\n");
1194 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1195 fprintf(output, "\n");
1196 fprintf(output, "Capture stop conditions:\n");
1197 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1198 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1199 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1200 fprintf(output, " files:NUM - stop after NUM files\n");
1201 /*fprintf(output, "\n");*/
1202 fprintf(output, "Capture output:\n");
1203 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1204 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1205 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1206 #endif /* HAVE_LIBPCAP */
1208 /*fprintf(output, "\n");*/
1209 fprintf(output, "Input file:\n");
1210 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1212 fprintf(output, "\n");
1213 fprintf(output, "Processing:\n");
1214 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1215 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1216 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1218 fprintf(output, "\n");
1219 fprintf(output, "User interface:\n");
1220 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1221 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1222 fprintf(output, " -J <jump filter> jump to the first packet matching the (display) filter\n");
1223 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
1224 fprintf(output, " -m <font> set the font name used for most text\n");
1225 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1226 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
1227 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1228 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1230 fprintf(output, "\n");
1231 fprintf(output, "Output:\n");
1232 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1234 fprintf(output, "\n");
1235 fprintf(output, "Miscellaneous:\n");
1236 fprintf(output, " -h display this help and exit\n");
1237 fprintf(output, " -v display version info and exit\n");
1238 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1239 fprintf(output, " persdata:path - personal data files\n");
1240 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1241 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1243 fprintf(output, " --display=DISPLAY X display to use\n");
1258 printf(PACKAGE " " VERSION "%s\n"
1265 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1266 runtime_info_str->str);
1274 * Print to the standard error. On Windows, create a console for the
1275 * standard error to show up on, if necessary.
1276 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1277 * terminal isn't the standard error?
1280 vfprintf_stderr(const char *fmt, va_list ap)
1285 vfprintf(stderr, fmt, ap);
1289 fprintf_stderr(const char *fmt, ...)
1294 vfprintf_stderr(fmt, ap);
1299 * Report an error in command-line arguments.
1300 * Creates a console on Windows.
1303 cmdarg_err(const char *fmt, ...)
1307 fprintf_stderr("wireshark: ");
1309 vfprintf_stderr(fmt, ap);
1311 fprintf_stderr("\n");
1315 * Report additional information for an error in command-line arguments.
1316 * Creates a console on Windows.
1317 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1318 * terminal isn't the standard error?
1321 cmdarg_err_cont(const char *fmt, ...)
1326 vfprintf_stderr(fmt, ap);
1327 fprintf_stderr("\n");
1332 Once every 3 seconds we get a callback here which we use to update
1336 tap_update_cb(gpointer data _U_)
1338 draw_tap_listeners(FALSE);
1342 /* Restart the tap update display timer with new configured interval */
1343 void reset_tap_update_timer(void)
1345 g_source_remove(tap_update_timer_id);
1346 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1350 protect_thread_critical_region(void)
1352 /* Threading support for TAP:s removed
1353 * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
1354 * See the commit for removed code:
1355 * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
1359 unprotect_thread_critical_region(void)
1361 /* Threading support for TAP:s removed
1362 * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
1368 * Periodically process outstanding hostname lookups. If we have new items,
1369 * redraw the packet list and tree view.
1373 resolv_update_cb(gpointer data _U_)
1375 /* Anything new show up? */
1376 if (host_name_lookup_process(NULL)) {
1377 if (pkt_scrollw->window)
1378 gdk_window_invalidate_rect(pkt_scrollw->window, NULL, TRUE);
1379 if (tv_scrollw->window)
1380 gdk_window_invalidate_rect(tv_scrollw->window, NULL, TRUE);
1383 /* Always check. Even if we don't do async lookups we could still get
1384 passive updates, e.g. from DNS packets. */
1389 /* Set main_window_name and it's icon title to the capture filename */
1391 set_display_filename(capture_file *cf)
1396 window_name = g_strdup_printf("%s", cf_get_display_name(cf));
1397 set_main_window_name(window_name);
1398 g_free(window_name);
1400 set_main_window_name("The Wireshark Network Analyzer");
1404 static GtkWidget *close_dlg = NULL;
1407 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1409 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1414 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1416 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1421 main_cf_cb_file_closing(capture_file *cf)
1424 /* if we have more than 10000 packets, show a splash screen while closing */
1425 /* XXX - don't know a better way to decide whether to show or not,
1426 * as most of the time is spend in a single eth_clist_clear function,
1427 * so we can't use a progress bar here! */
1428 if(cf->count > 10000) {
1429 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1430 "%sClosing file!%s\n\nPlease wait ...",
1431 simple_dialog_primary_start(),
1432 simple_dialog_primary_end());
1433 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1436 /* Destroy all windows, which refer to the
1437 capture file we're closing. */
1438 destroy_packet_wins();
1439 file_save_as_destroy();
1441 /* Restore the standard title bar message. */
1442 set_main_window_name("The Wireshark Network Analyzer");
1444 /* Disable all menu items that make sense only if you have a capture. */
1445 set_menus_for_capture_file(NULL);
1446 set_menus_for_captured_packets(FALSE);
1447 set_menus_for_selected_packet(cf);
1448 set_menus_for_capture_in_progress(FALSE);
1449 set_capture_if_dialog_for_capture_in_progress(FALSE);
1450 set_menus_for_selected_tree_row(cf);
1452 /* Set up main window for no capture file. */
1453 main_set_for_capture_file(FALSE);
1455 main_window_update();
1459 main_cf_cb_file_closed(capture_file *cf _U_)
1461 if(close_dlg != NULL) {
1462 splash_destroy(close_dlg);
1469 main_cf_cb_file_read_started(capture_file *cf _U_)
1471 tap_dfilter_dlg_update();
1473 /* Set up main window for a capture file. */
1474 main_set_for_capture_file(TRUE);
1478 main_cf_cb_file_read_finished(capture_file *cf)
1482 if (!cf->is_tempfile && cf->filename) {
1483 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1484 add_menu_recent_capture_file(cf->filename);
1486 /* Remember folder for next Open dialog and save it in recent */
1487 dir_path = get_dirname(g_strdup(cf->filename));
1488 set_last_open_dir(dir_path);
1491 set_display_filename(cf);
1493 /* Enable menu items that make sense if you have a capture file you've
1494 finished reading. */
1495 set_menus_for_capture_file(cf);
1497 /* Enable menu items that make sense if you have some captured packets. */
1498 set_menus_for_captured_packets(TRUE);
1502 static GList *icon_list_create(
1503 const char **icon16_xpm,
1504 const char **icon32_xpm,
1505 const char **icon48_xpm,
1506 const char **icon64_xpm)
1508 GList *icon_list = NULL;
1509 GdkPixbuf * pixbuf16;
1510 GdkPixbuf * pixbuf32;
1511 GdkPixbuf * pixbuf48;
1512 GdkPixbuf * pixbuf64;
1515 if(icon16_xpm != NULL) {
1516 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1518 icon_list = g_list_append(icon_list, pixbuf16);
1521 if(icon32_xpm != NULL) {
1522 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1524 icon_list = g_list_append(icon_list, pixbuf32);
1527 if(icon48_xpm != NULL) {
1528 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1530 icon_list = g_list_append(icon_list, pixbuf48);
1533 if(icon64_xpm != NULL) {
1534 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1536 icon_list = g_list_append(icon_list, pixbuf64);
1543 main_capture_set_main_window_title(capture_options *capture_opts)
1545 GString *title = g_string_new("");
1547 g_string_append(title, "Capturing ");
1548 if(capture_opts->iface) {
1549 g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1551 set_main_window_name(title->str);
1552 g_string_free(title, TRUE);
1556 main_capture_cb_capture_prepared(capture_options *capture_opts)
1558 static GList *icon_list = NULL;
1560 main_capture_set_main_window_title(capture_opts);
1562 if(icon_list == NULL) {
1563 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1565 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1567 /* Disable menu items that make no sense if you're currently running
1569 set_menus_for_capture_in_progress(TRUE);
1570 set_capture_if_dialog_for_capture_in_progress(TRUE);
1572 /* Don't set up main window for a capture file. */
1573 main_set_for_capture_file(FALSE);
1577 main_capture_cb_capture_update_started(capture_options *capture_opts)
1579 /* We've done this in "prepared" above, but it will be cleared while
1580 switching to the next multiple file. */
1581 main_capture_set_main_window_title(capture_opts);
1583 set_menus_for_capture_in_progress(TRUE);
1584 set_capture_if_dialog_for_capture_in_progress(TRUE);
1586 /* Enable menu items that make sense if you have some captured
1587 packets (yes, I know, we don't have any *yet*). */
1588 set_menus_for_captured_packets(TRUE);
1590 /* Set up main window for a capture file. */
1591 main_set_for_capture_file(TRUE);
1595 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1597 capture_file *cf = capture_opts->cf;
1598 static GList *icon_list = NULL;
1600 if (!cf->is_tempfile && cf->filename) {
1601 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1602 add_menu_recent_capture_file(cf->filename);
1604 set_display_filename(cf);
1606 /* Enable menu items that make sense if you're not currently running
1608 set_menus_for_capture_in_progress(FALSE);
1609 set_capture_if_dialog_for_capture_in_progress(FALSE);
1611 /* Enable menu items that make sense if you have a capture file
1612 you've finished reading. */
1613 set_menus_for_capture_file(cf);
1615 /* Set up main window for a capture file. */
1616 main_set_for_capture_file(TRUE);
1618 if(icon_list == NULL) {
1619 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1621 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1623 if(global_capture_opts.quit_after_cap) {
1624 /* command line asked us to quit after the capture */
1625 /* don't pop up a dialog to ask for unsaved files etc. */
1631 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1633 /* Don't set up main window for a capture file. */
1634 main_set_for_capture_file(FALSE);
1638 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1641 capture_file *cf = capture_opts->cf;
1643 static GList *icon_list = NULL;
1645 /*set_display_filename(cf);*/
1647 /* Enable menu items that make sense if you're not currently running
1649 set_menus_for_capture_in_progress(FALSE);
1650 set_capture_if_dialog_for_capture_in_progress(FALSE);
1652 /* Restore the standard title bar message */
1653 /* (just in case we have trouble opening the capture file). */
1654 set_main_window_name("The Wireshark Network Analyzer");
1656 if(icon_list == NULL) {
1657 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1659 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1661 /* We don't have loaded the capture file, this will be done later.
1662 * For now we still have simply a blank screen. */
1664 if(global_capture_opts.quit_after_cap) {
1665 /* command line asked us to quit after the capture */
1666 /* don't pop up a dialog to ask for unsaved files etc. */
1671 #endif /* HAVE_LIBPCAP */
1674 main_cf_cb_packet_selected(gpointer data)
1676 capture_file *cf = data;
1678 /* Display the GUI protocol tree and packet bytes.
1679 XXX - why do we dump core if we call "proto_tree_draw()"
1680 before calling "add_byte_views()"? */
1681 add_main_byte_views(cf->edt);
1682 main_proto_tree_draw(cf->edt->tree);
1684 /* Note: Both string and hex value searches in the packet data produce a non-zero
1685 search_pos if successful */
1686 if(cf->search_in_progress &&
1687 (cf->search_pos != 0 || (cf->string && cf->decode_data))) {
1688 highlight_field(cf->edt->tvb, cf->search_pos,
1689 (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1692 /* A packet is selected. */
1693 set_menus_for_selected_packet(cf);
1697 main_cf_cb_packet_unselected(capture_file *cf)
1699 /* Clear out the display of that packet. */
1700 clear_tree_and_hex_views();
1702 /* No packet is selected. */
1703 set_menus_for_selected_packet(cf);
1707 main_cf_cb_field_unselected(capture_file *cf)
1709 set_menus_for_selected_tree_row(cf);
1713 main_cf_cb_file_save_reload_finished(gpointer data _U_)
1715 set_display_filename(&cfile);
1716 set_menus_for_capture_file(&cfile);
1720 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1723 case(cf_cb_file_closing):
1724 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1725 main_cf_cb_file_closing(data);
1727 case(cf_cb_file_closed):
1728 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1729 main_cf_cb_file_closed(data);
1731 case(cf_cb_file_read_started):
1732 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1733 main_cf_cb_file_read_started(data);
1735 case(cf_cb_file_read_finished):
1736 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1737 main_cf_cb_file_read_finished(data);
1739 case(cf_cb_packet_selected):
1740 main_cf_cb_packet_selected(data);
1742 case(cf_cb_packet_unselected):
1743 main_cf_cb_packet_unselected(data);
1745 case(cf_cb_field_unselected):
1746 main_cf_cb_field_unselected(data);
1748 case(cf_cb_file_save_started):
1749 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1751 case(cf_cb_file_save_finished):
1752 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1754 case(cf_cb_file_save_reload_finished):
1755 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1756 main_cf_cb_file_save_reload_finished(data);
1758 case(cf_cb_file_save_failed):
1759 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1762 g_warning("main_cf_callback: event %u unknown", event);
1763 g_assert_not_reached();
1769 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1771 #ifdef HAVE_GTKOSXAPPLICATION
1772 GtkOSXApplication *theApp;
1775 case(capture_cb_capture_prepared):
1776 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1777 main_capture_cb_capture_prepared(capture_opts);
1779 case(capture_cb_capture_update_started):
1780 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1781 main_capture_cb_capture_update_started(capture_opts);
1782 #ifdef HAVE_GTKOSXAPPLICATION
1783 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1784 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsiconcap48_xpm));
1787 case(capture_cb_capture_update_continue):
1788 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1790 case(capture_cb_capture_update_finished):
1791 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1792 main_capture_cb_capture_update_finished(capture_opts);
1794 case(capture_cb_capture_fixed_started):
1795 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1796 main_capture_cb_capture_fixed_started(capture_opts);
1798 case(capture_cb_capture_fixed_continue):
1799 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1801 case(capture_cb_capture_fixed_finished):
1802 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1803 main_capture_cb_capture_fixed_finished(capture_opts);
1805 case(capture_cb_capture_stopping):
1806 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1807 /* Beware: this state won't be called, if the capture child
1808 * closes the capturing on it's own! */
1809 #ifdef HAVE_GTKOSXAPPLICATION
1810 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1811 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
1815 g_warning("main_capture_callback: event %u unknown", event);
1816 g_assert_not_reached();
1822 get_gtk_compiled_info(GString *str)
1824 g_string_append(str, "with ");
1825 g_string_append_printf(str,
1826 #ifdef GTK_MAJOR_VERSION
1827 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1830 "GTK+ (version unknown)");
1832 g_string_append(str, ", ");
1836 get_gui_compiled_info(GString *str)
1838 epan_get_compiled_version_info(str);
1840 g_string_append(str, ", ");
1841 #ifdef HAVE_LIBPORTAUDIO
1842 #ifdef PORTAUDIO_API_1
1843 g_string_append(str, "with PortAudio <= V18");
1844 #else /* PORTAUDIO_API_1 */
1845 g_string_append(str, "with ");
1846 g_string_append(str, Pa_GetVersionText());
1847 #endif /* PORTAUDIO_API_1 */
1848 #else /* HAVE_LIBPORTAUDIO */
1849 g_string_append(str, "without PortAudio");
1850 #endif /* HAVE_LIBPORTAUDIO */
1852 g_string_append(str, ", ");
1854 get_compiled_airpcap_version(str);
1856 g_string_append(str, "without AirPcap");
1858 #ifndef NEW_PACKET_LIST
1859 g_string_append(str, ", with old_packet_list");
1864 get_gui_runtime_info(GString *str)
1866 epan_get_runtime_version_info(str);
1869 g_string_append(str, ", ");
1870 get_runtime_airpcap_version(str);
1874 g_string_append(str, ", ");
1875 u3_runtime_info(str);
1880 read_configuration_files(char **gdp_path, char **dp_path)
1882 int gpf_open_errno, gpf_read_errno;
1883 int cf_open_errno, df_open_errno;
1884 int gdp_open_errno, gdp_read_errno;
1885 int dp_open_errno, dp_read_errno;
1886 char *gpf_path, *pf_path;
1887 char *cf_path, *df_path;
1888 int pf_open_errno, pf_read_errno;
1891 /* Read the preference files. */
1892 prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1893 &pf_open_errno, &pf_read_errno, &pf_path);
1895 if (gpf_path != NULL) {
1896 if (gpf_open_errno != 0) {
1897 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1898 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1899 strerror(gpf_open_errno));
1901 if (gpf_read_errno != 0) {
1902 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1903 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1904 strerror(gpf_read_errno));
1907 if (pf_path != NULL) {
1908 if (pf_open_errno != 0) {
1909 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1910 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1911 strerror(pf_open_errno));
1913 if (pf_read_errno != 0) {
1914 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1915 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1916 strerror(pf_read_errno));
1923 /* if the user wants a console to be always there, well, we should open one for him */
1924 if (prefs_p->gui_console_open == console_open_always) {
1929 /* Read the capture filter file. */
1930 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1931 if (cf_path != NULL) {
1932 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1933 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1934 strerror(cf_open_errno));
1938 /* Read the display filter file. */
1939 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1940 if (df_path != NULL) {
1941 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1942 "Could not open your display filter file\n\"%s\": %s.", df_path,
1943 strerror(df_open_errno));
1947 /* Read the disabled protocols file. */
1948 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1949 dp_path, &dp_open_errno, &dp_read_errno);
1950 if (*gdp_path != NULL) {
1951 if (gdp_open_errno != 0) {
1952 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1953 "Could not open global disabled protocols file\n\"%s\": %s.",
1954 *gdp_path, strerror(gdp_open_errno));
1956 if (gdp_read_errno != 0) {
1957 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1958 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1959 *gdp_path, strerror(gdp_read_errno));
1964 if (*dp_path != NULL) {
1965 if (dp_open_errno != 0) {
1966 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1967 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1968 strerror(dp_open_errno));
1970 if (dp_read_errno != 0) {
1971 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1972 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1973 strerror(dp_read_errno));
1982 /* Check if there's something important to tell the user during startup.
1983 * We want to do this *after* showing the main window so that any windows
1984 * we pop up will be above the main window.
1988 check_and_warn_user_startup(gchar *cf_name)
1990 check_and_warn_user_startup(gchar *cf_name _U_)
1993 gchar *cur_user, *cur_group;
1994 gpointer priv_warning_dialog;
1996 /* Tell the user not to run as root. */
1997 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
1998 cur_user = get_cur_username();
1999 cur_group = get_cur_groupname();
2000 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2001 "Running as user \"%s\" and group \"%s\".\n"
2002 "This could be dangerous.", cur_user, cur_group);
2005 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2006 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
2010 /* Warn the user if npf.sys isn't loaded. */
2011 if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
2012 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2013 "The NPF driver isn't running. You may have trouble\n"
2014 "capturing or listing interfaces.");
2015 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2016 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
2023 /* And now our feature presentation... [ fade to music ] */
2025 main(int argc, char *argv[])
2027 char *init_progfile_dir_error;
2030 gboolean arg_error = FALSE;
2032 extern int info_update_freq; /* Found in about_dlg.c. */
2033 const gchar *filter;
2043 char *gdp_path, *dp_path;
2046 gboolean start_capture = FALSE;
2047 gboolean list_link_layer_types = FALSE;
2051 gboolean capture_option_specified = FALSE;
2058 gint pl_size = 280, tv_size = 95, bv_size = 75;
2059 gchar *rc_file, *cf_name = NULL, *rfilter = NULL, *jfilter = NULL;
2060 dfilter_t *rfcode = NULL;
2061 gboolean rfilter_parse_failed = FALSE;
2064 GtkWidget *splash_win = NULL;
2065 GLogLevelFlags log_flags;
2066 guint go_to_packet = 0;
2067 gboolean jump_backwards = FALSE;
2068 dfilter_t *jump_to_filter = NULL;
2071 #ifdef HAVE_GTKOSXAPPLICATION
2072 GtkOSXApplication *theApp;
2076 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2077 #define OPTSTRING_B "B:"
2079 #define OPTSTRING_B ""
2080 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2081 #else /* HAVE_LIBPCAP */
2082 #define OPTSTRING_B ""
2083 #endif /* HAVE_LIBPCAP */
2085 #ifdef HAVE_PCAP_CREATE
2086 #define OPTSTRING_I "I"
2088 #define OPTSTRING_I ""
2091 #define OPTSTRING "a:b:" OPTSTRING_B "c:C:Df:g:Hhi:" OPTSTRING_I "jJ:kK:lLm:nN:o:P:pQr:R:Ss:t:u:vw:X:y:z:"
2093 static const char optstring[] = OPTSTRING;
2096 /* Convert our arg list to UTF-8. */
2097 wc_argv = CommandLineToArgvW(GetCommandLineW(), &wc_argc);
2098 if (wc_argv && wc_argc == argc) {
2099 for (i = 0; i < argc; i++) {
2100 argv[i] = g_utf16_to_utf8(wc_argv[i], -1, NULL, NULL, NULL);
2102 } /* XXX else bail because something is horribly, horribly wrong? */
2106 * Get credential information for later use, and drop privileges
2107 * before doing anything else.
2108 * Let the user know if anything happened.
2110 init_process_policies();
2111 relinquish_special_privs_perm();
2114 * Attempt to get the pathname of the executable file.
2116 init_progfile_dir_error = init_progfile_dir(argv[0], main);
2118 /* initialize the funnel mini-api */
2119 initialize_funnel_ops();
2121 #ifdef HAVE_AIRPDCAP
2122 AirPDcapInitContext(&airpdcap_ctx);
2126 /* Load wpcap if possible. Do this before collecting the run-time version information */
2129 /* ... and also load the packet.dll from wpcap */
2130 wpcap_packet_load();
2133 /* Load the airpcap.dll. This must also be done before collecting
2134 * run-time version information. */
2135 airpcap_dll_ret_val = load_airpcap();
2137 switch (airpcap_dll_ret_val) {
2138 case AIRPCAP_DLL_OK:
2139 /* load the airpcap interfaces */
2140 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2142 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2143 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2144 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2147 airpcap_if_active = NULL;
2151 /* select the first ad default (THIS SHOULD BE CHANGED) */
2152 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2157 * XXX - Maybe we need to warn the user if one of the following happens???
2159 case AIRPCAP_DLL_OLD:
2160 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2163 case AIRPCAP_DLL_ERROR:
2164 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2167 case AIRPCAP_DLL_NOT_FOUND:
2168 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2172 #endif /* HAVE_AIRPCAP */
2174 /* Start windows sockets */
2175 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2178 profile_store_persconffiles (TRUE);
2180 /* Assemble the compile-time version information string */
2181 comp_info_str = g_string_new("Compiled ");
2183 get_compiled_version_info(comp_info_str, get_gtk_compiled_info, get_gui_compiled_info);
2185 /* Assemble the run-time version information string */
2186 runtime_info_str = g_string_new("Running ");
2187 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2189 /* Read the profile independent recent file. We have to do this here so we can */
2190 /* set the profile before it can be set from the command line parameterts */
2191 recent_read_static(&rf_path, &rf_open_errno);
2192 if (rf_path != NULL && rf_open_errno != 0) {
2193 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2194 "Could not open common recent file\n\"%s\": %s.",
2195 rf_path, strerror(rf_open_errno));
2198 /* "pre-scan" the command line parameters, if we have "console only"
2199 parameters. We do this so we don't start GTK+ if we're only showing
2200 command-line help or version information.
2202 XXX - this pre-scan is done before we start GTK+, so we haven't
2203 run gtk_init() on the arguments. That means that GTK+ arguments
2204 have not been removed from the argument list; those arguments
2205 begin with "--", and will be treated as an error by getopt().
2207 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2210 optind_initial = optind;
2211 while ((opt = getopt(argc, argv, optstring)) != -1) {
2213 case 'C': /* Configuration Profile */
2214 if (profile_exists (optarg)) {
2215 set_profile_name (optarg);
2217 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2221 case 'h': /* Print help and exit */
2227 if (strcmp(optarg, "-") == 0)
2228 stdin_capture = TRUE;
2231 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2232 status = filesystem_opt(opt, optarg);
2234 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2238 case 'v': /* Show version and exit */
2244 * Extension command line options have to be processed before
2245 * we call epan_init() as they are supposed to be used by dissectors
2246 * or taps very early in the registration process.
2250 case '?': /* Ignore errors - the "real" scan will catch them. */
2255 /* Init the "Open file" dialog directory */
2256 /* (do this after the path settings are processed) */
2258 /* Read the profile dependent (static part) of the recent file. */
2259 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2260 /* recent lists which is done in the dynamic part. */
2261 /* We have to do this already here, so command line parameters can overwrite these values. */
2262 recent_read_profile_static(&rf_path, &rf_open_errno);
2263 if (rf_path != NULL && rf_open_errno != 0) {
2264 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2265 "Could not open recent file\n\"%s\": %s.",
2266 rf_path, strerror(rf_open_errno));
2269 if (recent.gui_fileopen_remembered_dir &&
2270 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
2271 set_last_open_dir(recent.gui_fileopen_remembered_dir);
2273 set_last_open_dir(get_persdatafile_dir());
2276 /* Set getopt index back to initial value, so it will start with the
2277 first command line parameter again. Also reset opterr to 1, so that
2278 error messages are printed by getopt().
2280 XXX - this seems to work on most platforms, but time will tell.
2281 The Single UNIX Specification says "The getopt() function need
2282 not be reentrant", so this isn't guaranteed to work. The Mac
2283 OS X 10.4[.x] getopt() man page says
2285 In order to use getopt() to evaluate multiple sets of arguments, or to
2286 evaluate a single set of arguments multiple times, the variable optreset
2287 must be set to 1 before the second and each additional set of calls to
2288 getopt(), and the variable optind must be reinitialized.
2292 The optreset variable was added to make it possible to call the getopt()
2293 function multiple times. This is an extension to the IEEE Std 1003.2
2294 (``POSIX.2'') specification.
2296 which I think comes from one of the other BSDs.
2298 XXX - if we want to control all the command-line option errors, so
2299 that we can display them where we choose (e.g., in a window), we'd
2300 want to leave opterr as 0, and produce our own messages using optopt.
2301 We'd have to check the value of optopt to see if it's a valid option
2302 letter, in which case *presumably* the error is "this option requires
2303 an argument but none was specified", or not a valid option letter,
2304 in which case *presumably* the error is "this option isn't valid".
2305 Some versions of getopt() let you supply a option string beginning
2306 with ':', which means that getopt() will return ':' rather than '?'
2307 for "this option requires an argument but none was specified", but
2309 optind = optind_initial;
2312 /* Set the current locale according to the program environment.
2313 * We haven't localized anything, but some GTK widgets are localized
2314 * (the file selection dialogue, for example).
2315 * This also sets the C-language locale to the native environment. */
2318 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2319 gtk_init (&argc, &argv);
2321 cf_callback_add(main_cf_callback, NULL);
2323 capture_callback_add(main_capture_callback, NULL);
2325 cf_callback_add(statusbar_cf_callback, NULL);
2327 capture_callback_add(statusbar_capture_callback, NULL);
2330 /* Arrange that if we have no console window, and a GLib message logging
2331 routine is called to log a message, we pop up a console window.
2333 We do that by inserting our own handler for all messages logged
2334 to the default domain; that handler pops up a console if necessary,
2335 and then calls the default handler. */
2337 /* We might want to have component specific log levels later ... */
2341 G_LOG_LEVEL_CRITICAL|
2342 G_LOG_LEVEL_WARNING|
2343 G_LOG_LEVEL_MESSAGE|
2346 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2348 g_log_set_handler(NULL,
2350 console_log_handler, NULL /* user_data */);
2351 g_log_set_handler(LOG_DOMAIN_MAIN,
2353 console_log_handler, NULL /* user_data */);
2356 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2358 console_log_handler, NULL /* user_data */);
2359 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2361 console_log_handler, NULL /* user_data */);
2363 /* Set the initial values in the capture options. This might be overwritten
2364 by preference settings and then again by the command line parameters. */
2365 capture_opts_init(&global_capture_opts, &cfile);
2368 /* Initialize whatever we need to allocate colors for GTK+ */
2371 /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2372 filter = get_conn_cfilter();
2373 if ( *filter != '\0' ) {
2374 info_update_freq = 1000; /* Milliseconds */
2377 /* We won't come till here, if we had a "console only" command line parameter. */
2378 splash_win = splash_new("Loading Wireshark ...");
2379 if (init_progfile_dir_error != NULL) {
2380 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2381 "Can't get pathname of Wireshark: %s.\n"
2382 "It won't be possible to capture traffic.\n"
2383 "Report this to the Wireshark developers.",
2384 init_progfile_dir_error);
2385 g_free(init_progfile_dir_error);
2388 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2390 /* Register all dissectors; we must do this before checking for the
2391 "-G" flag, as the "-G" flag dumps information registered by the
2392 dissectors, and we must do it before we read the preferences, in
2393 case any dissectors register preferences. */
2394 epan_init(register_all_protocols,register_all_protocol_handoffs,
2395 splash_update, (gpointer) splash_win,
2396 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2397 write_failure_alert_box);
2399 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2401 /* Register all tap listeners; we do this before we parse the arguments,
2402 as the "-z" argument can specify a registered tap. */
2404 /* we register the plugin taps before the other taps because
2405 stats_tree taps plugins will be registered as tap listeners
2406 by stats_tree_stat.c and need to registered before that */
2409 register_all_plugin_tap_listeners();
2412 register_all_tap_listeners();
2414 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2416 /* Now register the preferences for any non-dissector modules.
2417 We must do that before we read the preferences as well. */
2418 prefs_register_modules();
2420 prefs_p = read_configuration_files (&gdp_path, &dp_path);
2421 /* Removed thread code:
2422 * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
2425 /* this is to keep tap extensions updating once every 3 seconds */
2426 tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2428 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2430 cap_file_init(&cfile);
2432 /* Fill in capture options with values from the preferences */
2433 prefs_to_capture_opts();
2435 /* Now get our args */
2436 while ((opt = getopt(argc, argv, optstring)) != -1) {
2438 /*** capture option specific ***/
2439 case 'a': /* autostop criteria */
2440 case 'b': /* Ringbuffer option */
2441 case 'c': /* Capture xxx packets */
2442 case 'f': /* capture filter */
2443 case 'k': /* Start capture immediately */
2444 case 'H': /* Hide capture info dialog box */
2445 case 'i': /* Use interface xxx */
2446 case 'p': /* Don't capture in promiscuous mode */
2447 #ifdef HAVE_PCAP_CREATE
2448 case 'I': /* Capture in monitor mode, if available */
2450 case 'Q': /* Quit after capture (just capture to file) */
2451 case 's': /* Set the snapshot (capture) length */
2452 case 'S': /* "Sync" mode: used for following file ala tail -f */
2453 case 'w': /* Write to capture file xxx */
2454 case 'y': /* Set the pcap data link type */
2455 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2456 case 'B': /* Buffer size */
2457 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2459 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2465 capture_option_specified = TRUE;
2470 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2471 case 'K': /* Kerberos keytab file */
2472 read_keytab_file(optarg);
2476 /*** all non capture option specific ***/
2478 /* Configuration profile settings were already processed just ignore them this time*/
2480 case 'D': /* Print a list of capture devices and exit */
2482 if_list = capture_interface_list(&err, &err_str);
2483 if (if_list == NULL) {
2485 case CANT_GET_INTERFACE_LIST:
2486 cmdarg_err("%s", err_str);
2490 case NO_INTERFACES_FOUND:
2491 cmdarg_err("There are no interfaces on which a capture can be done");
2496 capture_opts_print_interfaces(if_list);
2497 free_interface_list(if_list);
2500 capture_option_specified = TRUE;
2504 case 'j': /* Search backwards for a matching packet from filter in option J */
2505 jump_backwards = TRUE;
2507 case 'g': /* Go to packet with the given packet number */
2508 go_to_packet = get_positive_int(optarg, "go to packet");
2510 case 'J': /* Jump to the first packet which matches the filter criteria */
2513 case 'l': /* Automatic scrolling in live capture mode */
2515 auto_scroll_live = TRUE;
2517 capture_option_specified = TRUE;
2521 case 'L': /* Print list of link-layer types and exit */
2523 list_link_layer_types = TRUE;
2525 capture_option_specified = TRUE;
2529 case 'm': /* Fixed-width font for the display */
2530 g_free(prefs_p->gui_font_name);
2531 prefs_p->gui_font_name = g_strdup(optarg);
2533 case 'n': /* No name resolution */
2534 gbl_resolv_flags = RESOLV_NONE;
2536 case 'N': /* Select what types of addresses/port #s to resolve */
2537 if (gbl_resolv_flags == RESOLV_ALL)
2538 gbl_resolv_flags = RESOLV_NONE;
2539 badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
2540 if (badopt != '\0') {
2541 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2546 case 'o': /* Override preference from command line */
2547 switch (prefs_set_pref(optarg)) {
2550 case PREFS_SET_SYNTAX_ERR:
2551 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2554 case PREFS_SET_NO_SUCH_PREF:
2555 /* not a preference, might be a recent setting */
2556 switch (recent_set_arg(optarg)) {
2559 case PREFS_SET_SYNTAX_ERR:
2560 /* shouldn't happen, checked already above */
2561 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2564 case PREFS_SET_NO_SUCH_PREF:
2565 case PREFS_SET_OBSOLETE:
2566 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2571 g_assert_not_reached();
2574 case PREFS_SET_OBSOLETE:
2575 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2580 g_assert_not_reached();
2584 /* Path settings were already processed just ignore them this time*/
2586 case 'r': /* Read capture file xxx */
2587 /* We may set "last_open_dir" to "cf_name", and if we change
2588 "last_open_dir" later, we free the old value, so we have to
2589 set "cf_name" to something that's been allocated. */
2590 cf_name = g_strdup(optarg);
2592 case 'R': /* Read file filter */
2595 case 't': /* Time stamp type */
2596 if (strcmp(optarg, "r") == 0)
2597 timestamp_set_type(TS_RELATIVE);
2598 else if (strcmp(optarg, "a") == 0)
2599 timestamp_set_type(TS_ABSOLUTE);
2600 else if (strcmp(optarg, "ad") == 0)
2601 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2602 else if (strcmp(optarg, "d") == 0)
2603 timestamp_set_type(TS_DELTA);
2604 else if (strcmp(optarg, "dd") == 0)
2605 timestamp_set_type(TS_DELTA_DIS);
2606 else if (strcmp(optarg, "e") == 0)
2607 timestamp_set_type(TS_EPOCH);
2609 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2610 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2611 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2615 case 'u': /* Seconds type */
2616 if (strcmp(optarg, "s") == 0)
2617 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
2618 else if (strcmp(optarg, "hms") == 0)
2619 timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
2621 cmdarg_err("Invalid seconds type \"%s\"", optarg);
2622 cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
2627 /* ext ops were already processed just ignore them this time*/
2630 /* We won't call the init function for the stat this soon
2631 as it would disallow MATE's fields (which are registered
2632 by the preferences set callback) from being used as
2633 part of a tap filter. Instead, we just add the argument
2634 to a list of stat arguments. */
2635 if (!process_stat_cmd_arg(optarg)) {
2636 cmdarg_err("Invalid -z argument.");
2637 cmdarg_err_cont(" -z argument must be one of :");
2638 list_stat_cmd_args();
2643 case '?': /* Bad flag - print usage message */
2651 if (cf_name != NULL) {
2653 * Input file name specified with "-r" *and* specified as a regular
2654 * command-line argument.
2656 cmdarg_err("File name specified both with -r and regular argument");
2660 * Input file name not specified with "-r", and a command-line argument
2661 * was specified; treat it as the input file name.
2663 * Yes, this is different from tshark, where non-flag command-line
2664 * arguments are a filter, but this works better on GUI desktops
2665 * where a command can be specified to be run to open a particular
2666 * file - yes, you could have "-r" as the last part of the command,
2667 * but that's a bit ugly.
2669 cf_name = g_strdup(argv[0]);
2677 * Extra command line arguments were specified; complain.
2679 cmdarg_err("Invalid argument: %s", argv[0]);
2684 #ifndef HAVE_LIBPCAP
2685 if (capture_option_specified) {
2686 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2694 if (start_capture && list_link_layer_types) {
2695 /* Specifying *both* is bogus. */
2696 cmdarg_err("You can't specify both -L and a live capture.");
2700 if (list_link_layer_types) {
2701 /* We're supposed to list the link-layer types for an interface;
2702 did the user also specify a capture file to be read? */
2704 /* Yes - that's bogus. */
2705 cmdarg_err("You can't specify -L and a capture file to be read.");
2708 /* No - did they specify a ring buffer option? */
2709 if (global_capture_opts.multi_files_on) {
2710 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2714 /* We're supposed to do a live capture; did the user also specify
2715 a capture file to be read? */
2716 if (start_capture && cf_name) {
2717 /* Yes - that's bogus. */
2718 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2722 /* No - was the ring buffer option specified and, if so, does it make
2724 if (global_capture_opts.multi_files_on) {
2725 /* Ring buffer works only under certain conditions:
2726 a) ring buffer does not work with temporary files;
2727 b) real_time_mode and multi_files_on are mutually exclusive -
2728 real_time_mode takes precedence;
2729 c) it makes no sense to enable the ring buffer if the maximum
2730 file size is set to "infinite". */
2731 if (global_capture_opts.save_file == NULL) {
2732 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2733 global_capture_opts.multi_files_on = FALSE;
2735 /* if (global_capture_opts.real_time_mode) {
2736 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2737 global_capture_opts.multi_files_on = FALSE;
2739 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2740 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2741 /* XXX - this must be redesigned as the conditions changed */
2742 /* global_capture_opts.multi_files_on = FALSE;*/
2747 if (start_capture || list_link_layer_types) {
2748 /* Did the user specify an interface to use? */
2749 if (!capture_opts_trim_iface(&global_capture_opts,
2750 (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2755 if (list_link_layer_types) {
2756 /* Get the list of link-layer types for the capture device. */
2757 if_capabilities_t *caps;
2759 caps = capture_get_if_capabilities(global_capture_opts.iface,
2760 global_capture_opts.monitor_mode,
2763 cmdarg_err("%s", err_str);
2767 if (caps->data_link_types == NULL) {
2768 cmdarg_err("The capture device \"%s\" has no data link types.", global_capture_opts.iface);
2771 capture_opts_print_if_capabilities(caps, global_capture_opts.monitor_mode);
2772 free_if_capabilities(caps);
2776 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2777 capture_opts_trim_ring_num_files(&global_capture_opts);
2778 #endif /* HAVE_LIBPCAP */
2780 /* Notify all registered modules that have had any of their preferences
2781 changed either from one of the preferences file or from the command
2782 line that their preferences have changed. */
2785 /* disabled protocols as per configuration file */
2786 if (gdp_path == NULL && dp_path == NULL) {
2787 set_disabled_protos_list();
2790 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2792 /* read in rc file from global and personal configuration paths. */
2793 rc_file = get_datafile_path(RC_FILE);
2794 gtk_rc_parse(rc_file);
2796 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2797 gtk_rc_parse(rc_file);
2806 /* close the splash screen, as we are going to open the main window now */
2807 splash_destroy(splash_win);
2809 /************************************************************************/
2810 /* Everything is prepared now, preferences and command line was read in */
2812 /* Pop up the main window. */
2813 create_main_window(pl_size, tv_size, bv_size, prefs_p);
2815 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2816 recent_read_dynamic(&rf_path, &rf_open_errno);
2817 if (rf_path != NULL && rf_open_errno != 0) {
2818 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2819 "Could not open recent file\n\"%s\": %s.",
2820 rf_path, strerror(rf_open_errno));
2823 color_filters_enable(recent.packet_list_colorize);
2825 /* rearrange all the widgets as we now have all recent settings ready for this */
2826 main_widgets_rearrange();
2828 /* Fill in column titles. This must be done after the top level window
2831 XXX - is that still true, with fixed-width columns? */
2832 #ifndef NEW_PACKET_LIST
2833 packet_list_set_column_titles();
2836 menu_recent_read_finished();
2838 menu_auto_scroll_live_changed(auto_scroll_live);
2841 switch (user_font_apply()) {
2844 case FA_FONT_NOT_RESIZEABLE:
2845 /* "user_font_apply()" popped up an alert box. */
2846 /* turn off zooming - font can't be resized */
2847 case FA_FONT_NOT_AVAILABLE:
2848 /* XXX - did we successfully load the un-zoomed version earlier?
2849 If so, this *probably* means the font is available, but not at
2850 this particular zoom level, but perhaps some other failure
2851 occurred; I'm not sure you can determine which is the case,
2853 /* turn off zooming - zoom level is unavailable */
2855 /* in any other case than FA_SUCCESS, turn off zooming */
2856 recent.gui_zoom_level = 0;
2857 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2860 dnd_init(top_level);
2862 color_filters_init();
2865 /* the window can be sized only, if it's not already shown, so do it now! */
2866 main_load_window_geometry(top_level);
2868 g_timeout_add(info_update_freq, resolv_update_cb, NULL);
2871 /* If we were given the name of a capture file, read it in now;
2872 we defer it until now, so that, if we can't open it, and pop
2873 up an alert box, the alert box is more likely to come up on
2874 top of the main window - but before the preference-file-error
2875 alert box, so, if we get one of those, it's more likely to come
2878 show_main_window(TRUE);
2879 check_and_warn_user_startup(cf_name);
2880 if (rfilter != NULL) {
2881 if (!dfilter_compile(rfilter, &rfcode)) {
2882 bad_dfilter_alert_box(rfilter);
2883 rfilter_parse_failed = TRUE;
2886 if (!rfilter_parse_failed) {
2887 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2888 /* "cf_open()" succeeded, so it closed the previous
2889 capture file, and thus destroyed any previous read filter
2890 attached to "cf". */
2892 cfile.rfcode = rfcode;
2893 /* Open stat windows; we do so after creating the main window,
2894 to avoid GTK warnings, and after successfully opening the
2895 capture file, so we know we have something to compute stats
2896 on, and after registering all dissectors, so that MATE will
2897 have registered its field array and we can have a tap filter
2898 with one of MATE's late-registered fields as part of the
2900 start_requested_stats();
2902 /* Read the capture file. */
2903 switch (cf_read(&cfile, FALSE)) {
2907 /* Just because we got an error, that doesn't mean we were unable
2908 to read any of the file; we handle what we could get from the
2910 /* if the user told us to jump to a specific packet, do it now */
2911 if(go_to_packet != 0) {
2912 /* Jump to the specified frame number, kept for backward
2914 cf_goto_frame(&cfile, go_to_packet);
2915 } else if (jfilter != NULL) {
2916 /* try to compile given filter */
2917 if (!dfilter_compile(jfilter, &jump_to_filter)) {
2918 bad_dfilter_alert_box(jfilter);
2920 /* Filter ok, jump to the first packet matching the filter
2921 conditions. Default search direction is forward, but if
2922 option d was given, search backwards */
2923 cf_find_packet_dfilter(&cfile, jump_to_filter, jump_backwards);
2928 case CF_READ_ABORTED:
2934 /* If the filename is not the absolute path, prepend the current dir. This happens
2935 when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */
2936 if (!g_path_is_absolute(cf_name)) {
2937 char *old_cf_name = cf_name;
2938 char *pwd = g_get_current_dir();
2939 cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name);
2940 g_free(old_cf_name);
2944 /* Save the name of the containing directory specified in the
2945 path name, if any; we can write over cf_name, which is a
2946 good thing, given that "get_dirname()" does write over its
2948 s = get_dirname(cf_name);
2949 set_last_open_dir(s);
2954 dfilter_free(rfcode);
2955 cfile.rfcode = NULL;
2956 show_main_window(FALSE);
2957 /* Don't call check_and_warn_user_startup(): we did it above */
2958 set_menus_for_capture_in_progress(FALSE);
2959 set_capture_if_dialog_for_capture_in_progress(FALSE);
2964 if (start_capture) {
2965 if (global_capture_opts.save_file != NULL) {
2966 /* Save the directory name for future file dialogs. */
2967 /* (get_dirname overwrites filename) */
2968 s = get_dirname(g_strdup(global_capture_opts.save_file));
2969 set_last_open_dir(s);
2972 /* "-k" was specified; start a capture. */
2973 show_main_window(TRUE);
2974 check_and_warn_user_startup(cf_name);
2975 if (capture_start(&global_capture_opts)) {
2976 /* The capture started. Open stat windows; we do so after creating
2977 the main window, to avoid GTK warnings, and after successfully
2978 opening the capture file, so we know we have something to compute
2979 stats on, and after registering all dissectors, so that MATE will
2980 have registered its field array and we can have a tap filter with
2981 one of MATE's late-registered fields as part of the filter. */
2982 start_requested_stats();
2986 show_main_window(FALSE);
2987 check_and_warn_user_startup(cf_name);
2988 set_menus_for_capture_in_progress(FALSE);
2989 set_capture_if_dialog_for_capture_in_progress(FALSE);
2992 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2993 if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2994 g_free(global_capture_opts.cfilter);
2995 global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2997 #else /* HAVE_LIBPCAP */
2998 show_main_window(FALSE);
2999 check_and_warn_user_startup(cf_name);
3000 set_menus_for_capture_in_progress(FALSE);
3001 set_capture_if_dialog_for_capture_in_progress(FALSE);
3002 #endif /* HAVE_LIBPCAP */
3005 /* register our pid if we are being run from a U3 device */
3008 profile_store_persconffiles (FALSE);
3010 #ifdef HAVE_GTKOSXAPPLICATION
3011 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
3012 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
3013 gtk_osxapplication_ready(theApp);
3016 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
3018 /* we'll enter the GTK loop now and hand the control over to GTK ... */
3020 /* ... back from GTK, we're going down now! */
3022 /* deregister our pid */
3023 u3_deregister_pid();
3027 #ifdef HAVE_AIRPDCAP
3028 AirPDcapDestroyContext(&airpdcap_ctx);
3032 /* hide the (unresponsive) main window, while asking the user to close the console window */
3033 gtk_widget_hide(top_level);
3035 #ifdef HAVE_GTKOSXAPPLICATION
3036 g_object_unref(theApp);
3039 /* Shutdown windows sockets */
3042 /* For some unknown reason, the "atexit()" call in "create_console()"
3043 doesn't arrange that "destroy_console()" be called when we exit,
3044 so we call it here if a console was created. */
3053 /* We build this as a GUI subsystem application on Win32, so
3054 "WinMain()", not "main()", gets called.
3056 Hack shamelessly stolen from the Win32 port of the GIMP. */
3058 #define _stdcall __attribute__((stdcall))
3062 WinMain (struct HINSTANCE__ *hInstance,
3063 struct HINSTANCE__ *hPrevInstance,
3067 INITCOMMONCONTROLSEX comm_ctrl;
3070 * Initialize our DLL search path. MUST be called before LoadLibrary
3073 ws_init_dll_search_path();
3075 /* Initialize our controls. Required for native Windows file dialogs. */
3076 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3077 comm_ctrl.dwSize = sizeof(comm_ctrl);
3078 /* Includes the animate, header, hot key, list view, progress bar,
3079 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3082 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3083 InitCommonControlsEx(&comm_ctrl);
3085 /* RichEd20.DLL is needed for filter entries. */
3086 ws_load_library("riched20.dll");
3088 has_console = FALSE;
3089 return main (__argc, __argv);
3092 /* The code to create and desstroy console windows should not be necessary,
3093 at least as I read the GLib source code, as it looks as if GLib is, on
3094 Win32, *supposed* to create a console window into which to display its
3097 That doesn't happen, however. I suspect there's something completely
3098 broken about that code in GLib-for-Win32, and that it may be related
3099 to the breakage that forces us to just call "printf()" on the message
3100 rather than passing the message on to "g_log_default_handler()"
3101 (which is the routine that does the aforementioned non-functional
3102 console window creation). */
3105 * If this application has no console window to which its standard output
3106 * would go, create one.
3109 create_console(void)
3111 if (stdin_capture) {
3112 /* We've been handed "-i -". Don't mess with stdio. */
3117 /* We have no console to which to print the version string, so
3118 create one and make it the standard input, output, and error. */
3119 if (!AllocConsole())
3120 return; /* couldn't create console */
3122 ws_freopen("CONIN$", "r", stdin);
3123 ws_freopen("CONOUT$", "w", stdout);
3124 ws_freopen("CONOUT$", "w", stderr);
3126 /* Well, we have a console now. */
3129 /* Now register "destroy_console()" as a routine to be called just
3130 before the application exits, so that we can destroy the console
3131 after the user has typed a key (so that the console doesn't just
3132 disappear out from under them, giving the user no chance to see
3133 the message(s) we put in there). */
3134 atexit(destroy_console);
3136 SetConsoleTitle(_T("Wireshark Debug Console"));
3141 destroy_console(void)
3144 printf("\n\nPress any key to exit\n");
3153 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3154 const char *message, gpointer user_data _U_)
3161 /* ignore log message, if log_level isn't interesting based
3162 upon the console log preferences.
3163 If the preferences haven't been loaded loaded yet, display the
3166 The default console_log_level preference value is such that only
3167 ERROR, CRITICAL and WARNING level messages are processed;
3168 MESSAGE, INFO and DEBUG level messages are ignored. */
3169 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3170 prefs.console_log_level != 0) {
3175 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3176 /* the user wants a console or the application will terminate immediately */
3180 /* For some unknown reason, the above doesn't appear to actually cause
3181 anything to be sent to the standard output, so we'll just splat the
3182 message out directly, just to make sure it gets out. */
3184 switch(log_level & G_LOG_LEVEL_MASK) {
3185 case G_LOG_LEVEL_ERROR:
3188 case G_LOG_LEVEL_CRITICAL:
3191 case G_LOG_LEVEL_WARNING:
3194 case G_LOG_LEVEL_MESSAGE:
3197 case G_LOG_LEVEL_INFO:
3200 case G_LOG_LEVEL_DEBUG:
3204 fprintf(stderr, "unknown log_level %u\n", log_level);
3206 g_assert_not_reached();
3209 /* create a "timestamp" */
3211 today = localtime(&curr);
3213 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3214 today->tm_hour, today->tm_min, today->tm_sec,
3215 log_domain != NULL ? log_domain : "",
3218 if(log_level & G_LOG_LEVEL_ERROR) {
3219 /* wait for a key press before the following error handler will terminate the program
3220 this way the user at least can read the error message */
3221 printf("\n\nPress any key to exit\n");
3225 /* XXX - on UN*X, should we just use g_log_default_handler()?
3226 We want the error messages to go to the standard output;
3227 on Mac OS X, that will cause them to show up in various
3228 per-user logs accessible through Console (details depend
3229 on whether you're running 10.0 through 10.4 or running
3230 10.5 and later), and, on other UN*X desktop environments,
3231 if they don't show up in some form of console log, that's
3232 a deficiency in that desktop environment. (Too bad
3233 Windows doesn't set the standard output and error for
3234 GUI apps to something that shows up in such a log.) */
3235 g_log_default_handler(log_domain, log_level, message, user_data);
3242 * Helper for main_widgets_rearrange()
3244 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3245 gtk_container_remove(GTK_CONTAINER(data), widget);
3248 static GtkWidget *main_widget_layout(gint layout_content)
3250 switch(layout_content) {
3251 case(layout_pane_content_none):
3253 case(layout_pane_content_plist):
3255 case(layout_pane_content_pdetails):
3257 case(layout_pane_content_pbytes):
3258 return byte_nb_ptr_gbl;
3260 g_assert_not_reached();
3267 * Rearrange the main window widgets
3269 void main_widgets_rearrange(void) {
3270 GtkWidget *first_pane_widget1, *first_pane_widget2;
3271 GtkWidget *second_pane_widget1, *second_pane_widget2;
3272 gboolean split_top_left;
3274 /* be a bit faster */
3275 gtk_widget_hide(main_vbox);
3277 /* be sure we don't lose a widget while rearranging */
3278 g_object_ref(G_OBJECT(menubar));
3279 g_object_ref(G_OBJECT(main_tb));
3280 g_object_ref(G_OBJECT(filter_tb));
3282 g_object_ref(G_OBJECT(airpcap_tb));
3284 g_object_ref(G_OBJECT(pkt_scrollw));
3285 g_object_ref(G_OBJECT(tv_scrollw));
3286 g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3287 g_object_ref(G_OBJECT(statusbar));
3288 g_object_ref(G_OBJECT(main_pane_v1));
3289 g_object_ref(G_OBJECT(main_pane_v2));
3290 g_object_ref(G_OBJECT(main_pane_h1));
3291 g_object_ref(G_OBJECT(main_pane_h2));
3292 g_object_ref(G_OBJECT(welcome_pane));
3294 /* empty all containers participating */
3295 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3296 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3297 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3298 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3299 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3301 statusbar_widgets_emptying(statusbar);
3303 /* add the menubar always at the top */
3304 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3307 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3309 /* filter toolbar in toolbar area */
3310 if (!prefs.filter_toolbar_show_in_statusbar) {
3311 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3315 /* airpcap toolbar */
3316 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3319 /* fill the main layout panes */
3320 switch(prefs.gui_layout_type) {
3321 case(layout_type_5):
3322 main_first_pane = main_pane_v1;
3323 main_second_pane = main_pane_v2;
3324 split_top_left = FALSE;
3326 case(layout_type_2):
3327 main_first_pane = main_pane_v1;
3328 main_second_pane = main_pane_h1;
3329 split_top_left = FALSE;
3331 case(layout_type_1):
3332 main_first_pane = main_pane_v1;
3333 main_second_pane = main_pane_h1;
3334 split_top_left = TRUE;
3336 case(layout_type_4):
3337 main_first_pane = main_pane_h1;
3338 main_second_pane = main_pane_v1;
3339 split_top_left = FALSE;
3341 case(layout_type_3):
3342 main_first_pane = main_pane_h1;
3343 main_second_pane = main_pane_v1;
3344 split_top_left = TRUE;
3346 case(layout_type_6):
3347 main_first_pane = main_pane_h1;
3348 main_second_pane = main_pane_h2;
3349 split_top_left = FALSE;
3352 main_first_pane = NULL;
3353 main_second_pane = NULL;
3354 split_top_left = FALSE;
3355 g_assert_not_reached();
3357 if (split_top_left) {
3358 first_pane_widget1 = main_second_pane;
3359 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3360 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3361 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3363 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3364 first_pane_widget2 = main_second_pane;
3365 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3366 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3368 if (first_pane_widget1 != NULL)
3369 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3370 if (first_pane_widget2 != NULL)
3371 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3372 if (second_pane_widget1 != NULL)
3373 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3374 if (second_pane_widget2 != NULL)
3375 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3377 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3380 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3383 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3385 /* filter toolbar in statusbar hbox */
3386 if (prefs.filter_toolbar_show_in_statusbar) {
3387 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3391 /* airpcap toolbar */
3392 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3395 /* statusbar widgets */
3396 statusbar_widgets_pack(statusbar);
3398 /* hide widgets on users recent settings */
3399 main_widgets_show_or_hide();
3401 gtk_widget_show(main_vbox);
3405 is_widget_visible(GtkWidget *widget, gpointer data)
3407 gboolean *is_visible = data;
3410 #if GTK_CHECK_VERSION(2,18,0)
3411 if (gtk_widget_get_visible(widget))
3413 if (GTK_WIDGET_VISIBLE(widget))
3421 main_widgets_show_or_hide(void)
3423 gboolean main_second_pane_show;
3425 if (recent.main_toolbar_show) {
3426 gtk_widget_show(main_tb);
3428 gtk_widget_hide(main_tb);
3431 statusbar_widgets_show_or_hide(statusbar);
3433 if (recent.filter_toolbar_show) {
3434 gtk_widget_show(filter_tb);
3436 gtk_widget_hide(filter_tb);
3440 if (recent.airpcap_toolbar_show) {
3441 gtk_widget_show(airpcap_tb);
3443 gtk_widget_hide(airpcap_tb);
3447 if (recent.packet_list_show && have_capture_file) {
3448 gtk_widget_show(pkt_scrollw);
3450 gtk_widget_hide(pkt_scrollw);
3453 if (recent.tree_view_show && have_capture_file) {
3454 gtk_widget_show(tv_scrollw);
3456 gtk_widget_hide(tv_scrollw);
3459 if (recent.byte_view_show && have_capture_file) {
3460 gtk_widget_show(byte_nb_ptr_gbl);
3462 gtk_widget_hide(byte_nb_ptr_gbl);
3465 if (have_capture_file) {
3466 gtk_widget_show(main_first_pane);
3468 gtk_widget_hide(main_first_pane);
3472 * Is anything in "main_second_pane" visible?
3473 * If so, show it, otherwise hide it.
3475 main_second_pane_show = FALSE;
3476 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3477 &main_second_pane_show);
3478 if (main_second_pane_show) {
3479 gtk_widget_show(main_second_pane);
3481 gtk_widget_hide(main_second_pane);
3484 if (!have_capture_file) {
3486 gtk_widget_show(welcome_pane);
3489 gtk_widget_hide(welcome_pane);
3492 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3493 #ifndef NEW_PACKET_LIST
3494 packet_list_freeze ();
3495 packet_list_thaw ();
3500 /* called, when the window state changes (minimized, maximized, ...) */
3502 window_state_event_cb (GtkWidget *widget _U_,
3506 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3508 if( (event->type) == (GDK_WINDOW_STATE)) {
3509 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3510 /* we might have dialogs popped up while we where iconified,
3512 display_queued_messages();
3520 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3522 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3524 if (event->keyval == GDK_F8) {
3525 #ifdef NEW_PACKET_LIST
3526 new_packet_list_next();
3531 } else if (event->keyval == GDK_F7) {
3532 #ifdef NEW_PACKET_LIST
3533 new_packet_list_prev();
3538 } else if (event->state & NO_SHIFT_MOD_MASK) {
3539 return FALSE; /* Skip control, alt, and other modifiers */
3541 * A comment in gdkkeysyms.h says that it's autogenerated from
3542 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3543 * don't explicitly say so, isprint() should work as expected
3546 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3547 /* Forward the keypress on to the display filter entry */
3548 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3549 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3550 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3558 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3560 GtkAccelGroup *accel;
3563 top_level = window_new(GTK_WINDOW_TOPLEVEL, "");
3564 set_main_window_name("The Wireshark Network Analyzer");
3566 gtk_widget_set_name(top_level, "main window");
3567 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3569 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3570 G_CALLBACK(window_state_event_cb), NULL);
3571 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3572 G_CALLBACK(top_level_key_pressed_cb), NULL );
3574 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3575 main_vbox = gtk_vbox_new(FALSE, 1);
3576 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 0);
3577 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3578 gtk_widget_show(main_vbox);
3581 menubar = main_menu_new(&accel);
3583 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined (HAVE_GTKOSXAPPLICATION)
3584 /* Mac OS X native menus are created and displayed by main_menu_new() */
3585 if(!prefs_p->gui_macosx_style) {
3587 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3588 gtk_widget_show(menubar);
3589 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined(HAVE_GTKOSXAPPLICATION)
3594 main_tb = toolbar_new();
3595 gtk_widget_show (main_tb);
3597 /* Filter toolbar */
3598 filter_tb = filter_toolbar_new();
3601 #ifdef NEW_PACKET_LIST
3602 pkt_scrollw = new_packet_list_create();
3603 gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3604 gtk_widget_show_all(pkt_scrollw);
3606 pkt_scrollw = packet_list_new(prefs_p);
3607 gtk_widget_set_size_request(packet_list, -1, pl_size);
3608 gtk_widget_show(pkt_scrollw);
3612 tv_scrollw = main_tree_view_new(prefs_p, &tree_view_gbl);
3613 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3614 gtk_widget_show(tv_scrollw);
3616 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3617 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3618 g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3619 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3620 gtk_widget_show(tree_view_gbl);
3623 byte_nb_ptr_gbl = byte_view_new();
3624 gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3625 gtk_widget_show(byte_nb_ptr_gbl);
3627 g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3628 g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3630 /* Panes for the packet list, tree, and byte view */
3631 main_pane_v1 = gtk_vpaned_new();
3632 gtk_widget_show(main_pane_v1);
3633 main_pane_v2 = gtk_vpaned_new();
3634 gtk_widget_show(main_pane_v2);
3635 main_pane_h1 = gtk_hpaned_new();
3636 gtk_widget_show(main_pane_h1);
3637 main_pane_h2 = gtk_hpaned_new();
3638 gtk_widget_show(main_pane_h2);
3640 airpcap_tb = airpcap_toolbar_new();
3641 gtk_widget_show(airpcap_tb);
3644 statusbar = statusbar_new();
3645 gtk_widget_show(statusbar);
3647 /* Pane for the welcome screen */
3648 welcome_pane = welcome_new();
3649 gtk_widget_show(welcome_pane);
3653 show_main_window(gboolean doing_work)
3655 main_set_for_capture_file(doing_work);
3657 /*** we have finished all init things, show the main window ***/
3658 gtk_widget_show(top_level);
3660 /* the window can be maximized only, if it's visible, so do it after show! */
3661 main_load_window_geometry(top_level);
3663 /* process all pending GUI events before continue */
3664 while (gtk_events_pending()) gtk_main_iteration();
3666 /* Pop up any queued-up alert boxes. */
3667 display_queued_messages();
3669 /* Move the main window to the front, in case it isn't already there */
3670 gdk_window_raise(top_level->window);
3673 airpcap_toolbar_show(airpcap_tb);
3674 #endif /* HAVE_AIRPCAP */
3677 /* Fill in capture options with values from the preferences */
3679 prefs_to_capture_opts(void)
3682 /* Set promiscuous mode from the preferences setting. */
3683 /* the same applies to other preferences settings as well. */
3684 global_capture_opts.promisc_mode = prefs.capture_prom_mode;
3685 global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
3686 global_capture_opts.show_info = prefs.capture_show_info;
3687 global_capture_opts.real_time_mode = prefs.capture_real_time;
3688 auto_scroll_live = prefs.capture_auto_scroll;
3689 #endif /* HAVE_LIBPCAP */
3691 /* Set the name resolution code's flags from the preferences. */
3692 gbl_resolv_flags = prefs.name_resolve;
3696 /* Change configuration profile */
3697 void change_configuration_profile (const gchar *profile_name)
3699 char *gdp_path, *dp_path;
3703 /* First check if profile exists */
3704 if (!profile_exists(profile_name)) {
3708 /* Get the current geometry, before writing it to disk */
3709 main_save_window_geometry(top_level);
3711 if (profile_exists(get_profile_name())) {
3712 /* Write recent file for profile we are leaving, if it still exists */
3713 write_profile_recent();
3716 /* Set profile name and update the status bar */
3717 set_profile_name (profile_name);
3718 profile_bar_update ();
3720 /* Reset current preferences and apply the new */
3724 (void) read_configuration_files (&gdp_path, &dp_path);
3726 recent_read_profile_static(&rf_path, &rf_open_errno);
3727 if (rf_path != NULL && rf_open_errno != 0) {
3728 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3729 "Could not open common recent file\n\"%s\": %s.",
3730 rf_path, strerror(rf_open_errno));
3732 if (recent.gui_fileopen_remembered_dir &&
3733 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
3734 set_last_open_dir(recent.gui_fileopen_remembered_dir);
3736 timestamp_set_type (recent.gui_time_format);
3737 timestamp_set_seconds_type (recent.gui_seconds_format);
3738 color_filters_enable(recent.packet_list_colorize);
3740 prefs_to_capture_opts();
3742 macros_post_update();
3744 /* Update window view and redraw the toolbar */
3745 update_main_window_title();
3746 toolbar_redraw_all();
3748 /* Enable all protocols and disable from the disabled list */
3750 if (gdp_path == NULL && dp_path == NULL) {
3751 set_disabled_protos_list();
3754 /* Reload color filters */
3755 color_filters_reload();
3757 /* Reload list of interfaces on welcome page */
3758 welcome_if_panel_reload();
3760 /* Recreate the packet list according to new preferences */
3761 #ifdef NEW_PACKET_LIST
3762 new_packet_list_recreate ();
3764 packet_list_recreate ();
3766 cfile.cinfo.columns_changed = FALSE; /* Reset value */
3769 /* Update menus with new recent values */
3770 menu_recent_read_finished();
3772 /* Reload pane geometry, must be done after recreating the list */
3773 main_pane_load_window_geometry();
3776 /** redissect packets and update UI */
3777 void redissect_packets(void)
3779 cf_redissect_packets(&cfile);
3780 status_expert_update();