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>
35 #if GTK_CHECK_VERSION(3,0,0)
36 # include <gdk/gdkkeysyms-compat.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 <wsutil/unicode-utils.h>
122 #include <commctrl.h>
123 #include <shellapi.h>
127 #include "gtk/file_dlg.h"
128 #include "gtk/gtkglobals.h"
129 #include "gtk/color_utils.h"
130 #include "gtk/gui_utils.h"
131 #include "gtk/color_dlg.h"
132 #include "gtk/filter_dlg.h"
133 #include "gtk/uat_gui.h"
134 #include "gtk/main.h"
135 #include "gtk/main_airpcap_toolbar.h"
136 #include "gtk/main_filter_toolbar.h"
137 #include "gtk/menus.h"
138 #include "gtk/macros_dlg.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_param_dlg.h"
159 #include "gtk/prefs_column.h"
160 #include "gtk/prefs_dlg.h"
161 #include "gtk/proto_help.h"
162 #include "gtk/new_packet_list.h"
165 #include "../image/wsicon16.xpm"
166 #include "../image/wsicon32.xpm"
167 #include "../image/wsicon48.xpm"
168 #include "../image/wsicon64.xpm"
169 #include "../image/wsiconcap16.xpm"
170 #include "../image/wsiconcap32.xpm"
171 #include "../image/wsiconcap48.xpm"
176 #include "airpcap_loader.h"
177 #include "airpcap_dlg.h"
178 #include "airpcap_gui_utils.h"
181 #include <epan/crypt/airpdcap_ws.h>
184 #ifdef HAVE_GTKOSXAPPLICATION
185 #include <igemacintegration/gtkosxapplication.h>
189 * Files under personal and global preferences directories in which
190 * GTK settings for Wireshark are stored.
192 #define RC_FILE "gtkrc"
196 /* "exported" main widgets */
197 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view_gbl, *byte_nb_ptr_gbl;
199 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
200 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
201 static GtkWidget *main_first_pane, *main_second_pane;
203 /* internally used widgets */
204 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
207 GtkWidget *airpcap_tb;
208 int airpcap_dll_ret_val = -1;
211 GString *comp_info_str, *runtime_info_str;
213 static gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
215 static guint tap_update_timer_id;
218 static gboolean has_console; /* TRUE if app has console */
219 static gboolean console_wait; /* "Press any key..." */
220 static void destroy_console(void);
221 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
223 static void console_log_handler(const char *log_domain,
224 GLogLevelFlags log_level, const char *message, gpointer user_data);
227 capture_options global_capture_opts;
231 static void create_main_window(gint, gint, gint, e_prefs*);
232 static void show_main_window(gboolean);
233 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
234 static void main_save_window_geometry(GtkWidget *widget);
237 /* Match selected byte pattern */
239 match_selected_cb_do(gpointer data, int action, gchar *text)
241 GtkWidget *filter_te;
242 char *cur_filter, *new_filter;
244 if ((!text) || (0 == strlen(text))) {
245 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
250 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
253 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
255 switch (action&MATCH_SELECTED_MASK) {
257 case MATCH_SELECTED_REPLACE:
258 new_filter = g_strdup(text);
261 case MATCH_SELECTED_AND:
262 if ((!cur_filter) || (0 == strlen(cur_filter)))
263 new_filter = g_strdup(text);
265 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
268 case MATCH_SELECTED_OR:
269 if ((!cur_filter) || (0 == strlen(cur_filter)))
270 new_filter = g_strdup(text);
272 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
275 case MATCH_SELECTED_NOT:
276 new_filter = g_strconcat("!(", text, ")", NULL);
279 case MATCH_SELECTED_AND_NOT:
280 if ((!cur_filter) || (0 == strlen(cur_filter)))
281 new_filter = g_strconcat("!(", text, ")", NULL);
283 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
286 case MATCH_SELECTED_OR_NOT:
287 if ((!cur_filter) || (0 == strlen(cur_filter)))
288 new_filter = g_strconcat("!(", text, ")", NULL);
290 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
294 g_assert_not_reached();
299 /* Free up the copy we got of the old filter text. */
302 /* Don't change the current display filter if we only want to copy the filter */
303 if (action&MATCH_SELECTED_COPY_ONLY) {
304 GString *gtk_text_str = g_string_new("");
305 g_string_append(gtk_text_str, new_filter);
306 copy_to_clipboard(gtk_text_str);
307 g_string_free(gtk_text_str, TRUE);
309 /* create a new one and set the display filter entry accordingly */
310 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
312 /* Run the display filter so it goes in effect. */
313 if (action&MATCH_SELECTED_APPLY_NOW)
314 main_filter_packets(&cfile, new_filter, FALSE);
317 /* Free up the new filter text. */
322 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
326 if (cfile.finfo_selected) {
327 filter = proto_construct_match_selected_string(cfile.finfo_selected,
329 match_selected_cb_do((data ? data : w), action, filter);
334 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
338 if (cfile.finfo_selected) {
339 filter = proto_construct_match_selected_string(cfile.finfo_selected,
341 if ((!filter) || (0 == strlen(filter))) {
342 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
343 "Could not acquire information to build a filter!\n"
344 "Try expanding or choosing another item.");
349 color_display_with_filter(filter);
352 color_filters_reset_tmp();
354 color_filters_set_tmp(filt_nr,filter, FALSE);
356 new_packet_list_colorize_packets();
362 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
364 gchar *selected_proto_url;
365 gchar *proto_abbrev = data;
370 if (cfile.finfo_selected) {
371 /* open wiki page using the protocol abbreviation */
372 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
373 browser_open_url(selected_proto_url);
374 g_free(selected_proto_url);
377 case(ESD_BTN_CANCEL):
380 g_assert_not_reached();
386 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
389 const gchar *proto_abbrev;
393 if (cfile.finfo_selected) {
394 /* convert selected field to protocol abbreviation */
395 /* XXX - could this conversion be simplified? */
396 field_id = cfile.finfo_selected->hfinfo->id;
397 /* if the selected field isn't a protocol, get it's parent */
398 if(!proto_registrar_is_protocol(field_id)) {
399 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
402 proto_abbrev = proto_registrar_get_abbrev(field_id);
404 if (!proto_is_private(field_id)) {
405 /* ask the user if the wiki page really should be opened */
406 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
407 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
409 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
411 "The Wireshark Wiki is a collaborative approach to provide information "
412 "about Wireshark in several ways (not limited to protocol specifics).\n"
414 "This Wiki is new, so the page of the selected protocol "
415 "may not exist and/or may not contain valuable information.\n"
417 "As everyone can edit the Wiki and add new content (or extend existing), "
418 "you are encouraged to add information if you can.\n"
420 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
422 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
423 "which will save you a lot of editing and will give a consistent look over the pages.",
424 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
425 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
427 /* appologize to the user that the wiki page cannot be opened */
428 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
429 "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
431 "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
433 "Since this is a private protocol, such information is not available in "
434 "a public wiki. Therefore this wiki entry is blocked.\n"
436 "Sorry for the inconvenience.\n",
437 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
442 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
444 gchar *selected_proto_url;
445 gchar *proto_abbrev = data;
449 if (cfile.finfo_selected) {
450 /* open reference page using the protocol abbreviation */
451 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
452 browser_open_url(selected_proto_url);
453 g_free(selected_proto_url);
456 case(ESD_BTN_CANCEL):
459 g_assert_not_reached();
464 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
467 const gchar *proto_abbrev;
471 if (cfile.finfo_selected) {
472 /* convert selected field to protocol abbreviation */
473 /* XXX - could this conversion be simplified? */
474 field_id = cfile.finfo_selected->hfinfo->id;
475 /* if the selected field isn't a protocol, get it's parent */
476 if(!proto_registrar_is_protocol(field_id)) {
477 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
480 proto_abbrev = proto_registrar_get_abbrev(field_id);
482 if (!proto_is_private(field_id)) {
483 /* ask the user if the wiki page really should be opened */
484 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
485 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
487 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
489 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
490 simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
492 /* appologize to the user that the wiki page cannot be opened */
493 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
494 "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
496 "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
498 "Since this is a private protocol, such information is not available on "
499 "a public website. Therefore this filter entry is blocked.\n"
501 "Sorry for the inconvenience.\n",
502 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
508 is_address_column (gint column)
510 if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
511 (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
512 (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
513 (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
514 strlen(cfile.cinfo.col_expr.col_expr_val[column]))
523 get_ip_address_list_from_packet_list_row(gpointer data)
525 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
526 gint column = new_packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
529 GList *addr_list = NULL;
531 fdata = (frame_data *) new_packet_list_get_row_data(row);
536 if (!cf_read_frame (&cfile, fdata))
537 return NULL; /* error reading the frame */
539 epan_dissect_init(&edt, FALSE, FALSE);
540 col_custom_prime_edt(&edt, &cfile.cinfo);
542 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
543 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
545 /* First check selected column */
546 if (is_address_column (column)) {
547 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
550 for (col = 0; col < cfile.cinfo.num_cols; col++) {
551 /* Then check all columns except the selected */
552 if ((col != column) && (is_address_column (col))) {
553 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
557 epan_dissect_cleanup(&edt);
564 get_filter_from_packet_list_row_and_column(gpointer data)
566 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
567 gint column = new_packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
571 fdata = (frame_data *) new_packet_list_get_row_data(row);
576 if (!cf_read_frame(&cfile, fdata))
577 return NULL; /* error reading the frame */
578 /* proto tree, visible. We need a proto tree if there's custom columns */
579 epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
580 col_custom_prime_edt(&edt, &cfile.cinfo);
582 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata,
584 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
586 if ((cfile.cinfo.col_custom_occurrence[column]) ||
587 (strchr (cfile.cinfo.col_expr.col_expr_val[column], ',') == NULL))
589 /* Only construct the filter when a single occurrence is displayed
590 * otherwise we might end up with a filter like "ip.proto==1,6".
592 * Or do we want to be able to filter on multiple occurrences so that
593 * the filter might be calculated as "ip.proto==1 && ip.proto==6"
596 if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
597 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
598 /* leak a little but safer than ep_ here */
599 if (cfile.cinfo.col_fmt[column] == COL_CUSTOM) {
600 header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[column]);
601 if (hfi->parent == -1) {
603 buf = se_strdup(cfile.cinfo.col_expr.col_expr[column]);
604 } else if (hfi->type == FT_STRING) {
605 /* Custom string, add quotes */
606 buf = se_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
607 cfile.cinfo.col_expr.col_expr_val[column]);
611 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
612 cfile.cinfo.col_expr.col_expr_val[column]);
617 epan_dissect_cleanup(&edt);
624 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
626 match_selected_cb_do(data,
628 get_filter_from_packet_list_row_and_column(data));
631 /* This function allows users to right click in the details window and copy the text
632 * information to the operating systems clipboard.
634 * We first check to see if a string representation is setup in the tree and then
635 * read the string. If not available then we try to grab the value. If all else
636 * fails we display a message to the user to indicate the copy could not be completed.
639 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
641 GString *gtk_text_str = g_string_new("");
642 char labelstring[256];
643 char *stringpointer = labelstring;
647 case COPY_SELECTED_DESCRIPTION:
648 if (cfile.finfo_selected->rep &&
649 strlen (cfile.finfo_selected->rep->representation) > 0) {
650 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
653 case COPY_SELECTED_FIELDNAME:
654 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
655 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
658 case COPY_SELECTED_VALUE:
659 if (cfile.edt !=0 ) {
660 g_string_append(gtk_text_str,
661 get_node_field_value(cfile.finfo_selected, cfile.edt));
668 if (gtk_text_str->len == 0) {
669 /* If no representation then... Try to read the value */
670 proto_item_fill_label(cfile.finfo_selected, stringpointer);
671 g_string_append(gtk_text_str, stringpointer);
674 if (gtk_text_str->len == 0) {
675 /* Could not get item so display error msg */
676 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
678 /* Copy string to clipboard */
679 copy_to_clipboard(gtk_text_str);
681 g_string_free(gtk_text_str, TRUE); /* Free the memory */
685 /* mark as reference time frame */
687 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
691 frame->flags.ref_time=1;
692 cfile.ref_time_count++;
694 frame->flags.ref_time=0;
695 cfile.ref_time_count--;
697 cf_reftime_packets(&cfile);
698 if (!frame->flags.ref_time && !frame->flags.passed_dfilter) {
699 new_packet_list_freeze();
700 cfile.displayed_count--;
701 new_packet_list_recreate_visible_rows();
702 new_packet_list_thaw();
704 new_packet_list_queue_draw();
708 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
712 timestamp_set_type(TS_RELATIVE);
713 recent.gui_time_format = TS_RELATIVE;
714 cf_timestamp_auto_precision(&cfile);
715 new_packet_list_queue_draw();
720 g_assert_not_reached();
723 if (cfile.current_frame) {
724 set_frame_reftime(!cfile.current_frame->flags.ref_time,
725 cfile.current_frame, cfile.current_row);
731 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
733 static GtkWidget *reftime_dialog = NULL;
737 if (cfile.current_frame) {
738 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
739 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
740 "%sSwitch to the appropriate Time Display Format?%s\n\n"
741 "Time References don't work well with the currently selected Time Display Format.\n\n"
742 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
743 simple_dialog_primary_start(), simple_dialog_primary_end());
744 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
746 set_frame_reftime(!cfile.current_frame->flags.ref_time,
747 cfile.current_frame, cfile.current_row);
751 case REFTIME_FIND_NEXT:
752 cf_find_packet_time_reference(&cfile, SD_FORWARD);
754 case REFTIME_FIND_PREV:
755 cf_find_packet_time_reference(&cfile, SD_BACKWARD);
761 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
763 cf_find_packet_marked(&cfile, SD_FORWARD);
767 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
769 cf_find_packet_marked(&cfile, SD_BACKWARD);
773 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
776 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
778 gboolean has_blurb = FALSE;
779 guint length = 0, byte_len;
780 GtkWidget *byte_view;
781 const guint8 *byte_data;
786 /* if nothing is selected */
787 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
790 * Which byte view is displaying the current protocol tree
793 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
794 if (byte_view == NULL)
797 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
798 if (byte_data == NULL)
801 cf_unselect_field(&cfile);
802 packet_hex_print(byte_view, byte_data,
803 cfile.current_frame, NULL, byte_len);
804 proto_help_menu_modify(sel, &cfile);
807 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
810 set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
812 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
813 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
814 g_assert(byte_data != NULL);
816 cfile.finfo_selected = finfo;
817 set_menus_for_selected_tree_row(&cfile);
820 if (finfo->hfinfo->blurb != NULL &&
821 finfo->hfinfo->blurb[0] != '\0') {
823 length = (guint) strlen(finfo->hfinfo->blurb);
825 length = (guint) strlen(finfo->hfinfo->name);
827 finfo_length = finfo->length + finfo->appendix_length;
829 if (finfo_length == 0) {
831 } else if (finfo_length == 1) {
832 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
834 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
836 statusbar_pop_field_msg(); /* get rid of current help msg */
838 statusbar_push_field_msg(" %s (%s)%s",
839 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
840 finfo->hfinfo->abbrev, len_str);
843 * Don't show anything if the field name is zero-length;
844 * the pseudo-field for "proto_tree_add_text()" is such
845 * a field, and we don't want "Text (text)" showing up
846 * on the status line if you've selected such a field.
848 * XXX - there are zero-length fields for which we *do*
849 * want to show the field name.
851 * XXX - perhaps the name and abbrev field should be null
852 * pointers rather than null strings for that pseudo-field,
853 * but we'd have to add checks for null pointers in some
854 * places if we did that.
856 * Or perhaps protocol tree items added with
857 * "proto_tree_add_text()" should have -1 as the field index,
858 * with no pseudo-field being used, but that might also
859 * require special checks for -1 to be added.
861 statusbar_push_field_msg("%s", "");
864 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
866 proto_help_menu_modify(sel, &cfile);
869 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
871 collapse_all_tree(cfile.edt->tree, tree_view_gbl);
874 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
876 expand_all_tree(cfile.edt->tree, tree_view_gbl);
879 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
881 if (cfile.finfo_selected) {
882 column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
883 cfile.finfo_selected->hfinfo->abbrev,0);
884 /* Recreate the packet list according to new preferences */
885 new_packet_list_recreate ();
886 if (!prefs.gui_use_pref_save) {
889 cfile.cinfo.columns_changed = FALSE; /* Reset value */
893 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
896 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
898 /* the mouse position is at an entry, expand that one */
899 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
900 gtk_tree_path_free(path);
904 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
905 if (cfile.edt->tree) {
906 guint32 tmp = gbl_resolv_flags;
907 gbl_resolv_flags = RESOLV_ALL;
908 proto_tree_draw(cfile.edt->tree, tree_view_gbl);
909 gbl_resolv_flags = tmp;
914 main_set_for_capture_file(gboolean have_capture_file_in)
916 have_capture_file = have_capture_file_in;
918 main_widgets_show_or_hide();
924 /* get the current geometry, before writing it to disk */
925 main_save_window_geometry(top_level);
927 /* write user's recent file to disk
928 * It is no problem to write this file, even if we do not quit */
929 write_profile_recent();
932 /* XXX - should we check whether the capture file is an
933 unsaved temporary file for a live capture and, if so,
934 pop up a "do you want to exit without saving the capture
935 file?" dialog, and then just return, leaving said dialog
936 box to forcibly quit if the user clicks "OK"?
938 If so, note that this should be done in a subroutine that
939 returns TRUE if we do so, and FALSE otherwise, and if it
940 returns TRUE we should return TRUE without nuking anything.
942 Note that, if we do that, we might also want to check if
943 an "Update list of packets in real time" capture is in
944 progress and, if so, ask whether they want to terminate
945 the capture and discard it, and return TRUE, before nuking
946 any child capture, if they say they don't want to do so. */
949 /* Nuke any child capture in progress. */
950 capture_kill_child(&global_capture_opts);
953 /* Are we in the middle of reading a capture? */
954 if (cfile.state == FILE_READ_IN_PROGRESS) {
955 /* Yes, so we can't just close the file and quit, as
956 that may yank the rug out from under the read in
957 progress; instead, just set the state to
958 "FILE_READ_ABORTED" and return - the code doing the read
959 will check for that and, if it sees that, will clean
961 cfile.state = FILE_READ_ABORTED;
963 /* Say that the window should *not* be deleted;
964 that'll be done by the code that cleans up. */
967 /* Close any capture file we have open; on some OSes, you
968 can't unlink a temporary capture file if you have it
970 "cf_close()" will unlink it after closing it if
971 it's a temporary file.
973 We do this here, rather than after the main loop returns,
974 as, after the main loop returns, the main window may have
975 been destroyed (if this is called due to a "destroy"
976 even on the main window rather than due to the user
977 selecting a menu item), and there may be a crash
978 or other problem when "cf_close()" tries to
979 clean up stuff in the main window.
981 XXX - is there a better place to put this?
982 Or should we have a routine that *just* closes the
983 capture file, and doesn't do anything with the UI,
984 which we'd call here, and another routine that
985 calls that routine and also cleans up the UI, which
986 we'd call elsewhere? */
989 /* Exit by leaving the main loop, so that any quit functions
990 we registered get called. */
993 /* Say that the window should be deleted. */
999 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1003 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1004 gtk_window_present(GTK_WINDOW(top_level));
1005 /* user didn't saved his current file, ask him */
1006 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1007 "%sSave capture file before program quit?%s\n\n"
1008 "If you quit the program without saving, your capture data will be discarded.",
1009 simple_dialog_primary_start(), simple_dialog_primary_end());
1010 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1013 /* unchanged file, just exit */
1014 /* "main_do_quit()" indicates whether the main window should be deleted. */
1015 return main_do_quit();
1021 main_pane_load_window_geometry(void)
1023 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1024 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1025 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
1026 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1032 main_load_window_geometry(GtkWidget *widget)
1034 window_geometry_t geom;
1036 geom.set_pos = prefs.gui_geometry_save_position;
1037 geom.x = recent.gui_geometry_main_x;
1038 geom.y = recent.gui_geometry_main_y;
1039 geom.set_size = prefs.gui_geometry_save_size;
1040 if (recent.gui_geometry_main_width > 0 &&
1041 recent.gui_geometry_main_height > 0) {
1042 geom.width = recent.gui_geometry_main_width;
1043 geom.height = recent.gui_geometry_main_height;
1044 geom.set_maximized = prefs.gui_geometry_save_maximized;
1046 /* We assume this means the width and height weren't set in
1047 the "recent" file (or that there is no "recent" file),
1048 and weren't set to a default value, so we don't set the
1049 size. (The "recent" file code rejects non-positive width
1050 and height values.) */
1051 geom.set_size = FALSE;
1053 geom.maximized = recent.gui_geometry_main_maximized;
1055 window_set_geometry(widget, &geom);
1057 main_pane_load_window_geometry();
1058 statusbar_load_window_geometry();
1063 main_save_window_geometry(GtkWidget *widget)
1065 window_geometry_t geom;
1067 window_get_geometry(widget, &geom);
1069 if (prefs.gui_geometry_save_position) {
1070 recent.gui_geometry_main_x = geom.x;
1071 recent.gui_geometry_main_y = geom.y;
1074 if (prefs.gui_geometry_save_size) {
1075 recent.gui_geometry_main_width = geom.width;
1076 recent.gui_geometry_main_height = geom.height;
1079 if(prefs.gui_geometry_save_maximized) {
1080 recent.gui_geometry_main_maximized = geom.maximized;
1083 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1084 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1085 statusbar_save_window_geometry();
1088 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1092 /* save file first */
1093 file_save_as_cmd(after_save_exit, NULL);
1095 case(ESD_BTN_QUIT_DONT_SAVE):
1098 case(ESD_BTN_CANCEL):
1101 g_assert_not_reached();
1106 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1110 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1111 /* user didn't saved his current file, ask him */
1112 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1113 "%sSave capture file before program quit?%s\n\n"
1114 "If you quit the program without saving, your capture data will be discarded.",
1115 simple_dialog_primary_start(), simple_dialog_primary_end());
1116 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1118 /* unchanged file, just exit */
1124 print_usage(gboolean print_ver) {
1134 fprintf(output, "Wireshark " VERSION "%s\n"
1135 "Interactively dump and analyze network traffic.\n"
1136 "See http://www.wireshark.org for more information.\n"
1139 wireshark_svnversion, get_copyright_info());
1143 fprintf(output, "\n");
1144 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1145 fprintf(output, "\n");
1148 fprintf(output, "Capture interface:\n");
1149 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1150 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1151 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1152 fprintf(output, " -p don't capture in promiscuous mode\n");
1153 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1154 fprintf(output, " -Q quit Wireshark after capturing\n");
1155 fprintf(output, " -S update packet display when new packets are captured\n");
1156 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1157 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
1158 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1160 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1161 fprintf(output, " -D print list of interfaces and exit\n");
1162 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1163 fprintf(output, "\n");
1164 fprintf(output, "Capture stop conditions:\n");
1165 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1166 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1167 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1168 fprintf(output, " files:NUM - stop after NUM files\n");
1169 /*fprintf(output, "\n");*/
1170 fprintf(output, "Capture output:\n");
1171 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1172 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1173 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1174 #endif /* HAVE_LIBPCAP */
1176 /*fprintf(output, "\n");*/
1177 fprintf(output, "Input file:\n");
1178 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1180 fprintf(output, "\n");
1181 fprintf(output, "Processing:\n");
1182 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1183 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1184 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1186 fprintf(output, "\n");
1187 fprintf(output, "User interface:\n");
1188 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1189 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1190 fprintf(output, " -J <jump filter> jump to the first packet matching the (display)\n");
1191 fprintf(output, " filter\n");
1192 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
1193 fprintf(output, " -m <font> set the font name used for most text\n");
1194 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1195 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
1196 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1197 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1199 fprintf(output, "\n");
1200 fprintf(output, "Output:\n");
1201 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1203 fprintf(output, "\n");
1204 fprintf(output, "Miscellaneous:\n");
1205 fprintf(output, " -h display this help and exit\n");
1206 fprintf(output, " -v display version info and exit\n");
1207 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1208 fprintf(output, " persdata:path - personal data files\n");
1209 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1210 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1212 fprintf(output, " --display=DISPLAY X display to use\n");
1227 printf(PACKAGE " " VERSION "%s\n"
1234 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1235 runtime_info_str->str);
1243 * Print to the standard error. On Windows, create a console for the
1244 * standard error to show up on, if necessary.
1245 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1246 * terminal isn't the standard error?
1249 vfprintf_stderr(const char *fmt, va_list ap)
1254 vfprintf(stderr, fmt, ap);
1258 fprintf_stderr(const char *fmt, ...)
1263 vfprintf_stderr(fmt, ap);
1268 * Report an error in command-line arguments.
1269 * Creates a console on Windows.
1272 cmdarg_err(const char *fmt, ...)
1276 fprintf_stderr("wireshark: ");
1278 vfprintf_stderr(fmt, ap);
1280 fprintf_stderr("\n");
1284 * Report additional information for an error in command-line arguments.
1285 * Creates a console on Windows.
1286 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1287 * terminal isn't the standard error?
1290 cmdarg_err_cont(const char *fmt, ...)
1295 vfprintf_stderr(fmt, ap);
1296 fprintf_stderr("\n");
1301 Once every 3 seconds we get a callback here which we use to update
1305 tap_update_cb(gpointer data _U_)
1307 draw_tap_listeners(FALSE);
1311 /* Restart the tap update display timer with new configured interval */
1312 void reset_tap_update_timer(void)
1314 g_source_remove(tap_update_timer_id);
1315 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1319 protect_thread_critical_region(void)
1321 /* Threading support for TAP:s removed
1322 * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
1323 * See the commit for removed code:
1324 * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
1328 unprotect_thread_critical_region(void)
1330 /* Threading support for TAP:s removed
1331 * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
1337 * Periodically process outstanding hostname lookups. If we have new items,
1338 * redraw the packet list and tree view.
1342 resolv_update_cb(gpointer data _U_)
1344 /* Anything new show up? */
1345 if (host_name_lookup_process(NULL)) {
1346 #if GTK_CHECK_VERSION(2,14,0)
1347 if (gtk_widget_get_window(pkt_scrollw))
1348 gdk_window_invalidate_rect(gtk_widget_get_window(pkt_scrollw), NULL, TRUE);
1349 if (gtk_widget_get_window(tv_scrollw))
1350 gdk_window_invalidate_rect(gtk_widget_get_window(tv_scrollw), NULL, TRUE);
1352 if (pkt_scrollw->window)
1353 gdk_window_invalidate_rect(pkt_scrollw->window, NULL, TRUE);
1354 if (tv_scrollw->window)
1355 gdk_window_invalidate_rect(tv_scrollw->window, NULL, TRUE);
1359 /* Always check. Even if we don't do async lookups we could still get
1360 passive updates, e.g. from DNS packets. */
1365 /* Set main_window_name and it's icon title to the capture filename */
1367 set_display_filename(capture_file *cf)
1372 window_name = g_strdup_printf("%s", cf_get_display_name(cf));
1373 set_main_window_name(window_name);
1374 g_free(window_name);
1376 set_main_window_name("The Wireshark Network Analyzer");
1380 static GtkWidget *close_dlg = NULL;
1383 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1385 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1390 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1392 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1397 main_cf_cb_file_closing(capture_file *cf)
1400 /* if we have more than 10000 packets, show a splash screen while closing */
1401 /* XXX - don't know a better way to decide whether to show or not,
1402 * as most of the time is spend in a single eth_clist_clear function,
1403 * so we can't use a progress bar here! */
1404 if(cf->count > 10000) {
1405 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1406 "%sClosing file!%s\n\nPlease wait ...",
1407 simple_dialog_primary_start(),
1408 simple_dialog_primary_end());
1409 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1412 /* Destroy all windows, which refer to the
1413 capture file we're closing. */
1414 destroy_packet_wins();
1415 file_save_as_destroy();
1417 /* Restore the standard title bar message. */
1418 set_main_window_name("The Wireshark Network Analyzer");
1420 /* Disable all menu items that make sense only if you have a capture. */
1421 set_menus_for_capture_file(NULL);
1422 set_menus_for_captured_packets(FALSE);
1423 set_menus_for_selected_packet(cf);
1424 set_menus_for_capture_in_progress(FALSE);
1425 set_capture_if_dialog_for_capture_in_progress(FALSE);
1426 set_menus_for_selected_tree_row(cf);
1428 /* Set up main window for no capture file. */
1429 main_set_for_capture_file(FALSE);
1431 main_window_update();
1435 main_cf_cb_file_closed(capture_file *cf _U_)
1437 if(close_dlg != NULL) {
1438 splash_destroy(close_dlg);
1445 main_cf_cb_file_read_started(capture_file *cf _U_)
1447 tap_param_dlg_update();
1449 /* Set up main window for a capture file. */
1450 main_set_for_capture_file(TRUE);
1454 main_cf_cb_file_read_finished(capture_file *cf)
1458 if (!cf->is_tempfile && cf->filename) {
1459 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1460 add_menu_recent_capture_file(cf->filename);
1462 /* Remember folder for next Open dialog and save it in recent */
1463 dir_path = get_dirname(g_strdup(cf->filename));
1464 set_last_open_dir(dir_path);
1467 set_display_filename(cf);
1469 /* Enable menu items that make sense if you have a capture file you've
1470 finished reading. */
1471 set_menus_for_capture_file(cf);
1473 /* Enable menu items that make sense if you have some captured packets. */
1474 set_menus_for_captured_packets(TRUE);
1478 static GList *icon_list_create(
1479 const char **icon16_xpm,
1480 const char **icon32_xpm,
1481 const char **icon48_xpm,
1482 const char **icon64_xpm)
1484 GList *icon_list = NULL;
1485 GdkPixbuf * pixbuf16;
1486 GdkPixbuf * pixbuf32;
1487 GdkPixbuf * pixbuf48;
1488 GdkPixbuf * pixbuf64;
1491 if(icon16_xpm != NULL) {
1492 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1494 icon_list = g_list_append(icon_list, pixbuf16);
1497 if(icon32_xpm != NULL) {
1498 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1500 icon_list = g_list_append(icon_list, pixbuf32);
1503 if(icon48_xpm != NULL) {
1504 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1506 icon_list = g_list_append(icon_list, pixbuf48);
1509 if(icon64_xpm != NULL) {
1510 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1512 icon_list = g_list_append(icon_list, pixbuf64);
1519 main_capture_set_main_window_title(capture_options *capture_opts)
1521 GString *title = g_string_new("");
1523 g_string_append(title, "Capturing ");
1524 g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1525 set_main_window_name(title->str);
1526 g_string_free(title, TRUE);
1530 main_capture_cb_capture_prepared(capture_options *capture_opts)
1532 static GList *icon_list = NULL;
1534 main_capture_set_main_window_title(capture_opts);
1536 if(icon_list == NULL) {
1537 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1539 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1541 /* Disable menu items that make no sense if you're currently running
1543 set_menus_for_capture_in_progress(TRUE);
1544 set_capture_if_dialog_for_capture_in_progress(TRUE);
1546 /* Don't set up main window for a capture file. */
1547 main_set_for_capture_file(FALSE);
1551 main_capture_cb_capture_update_started(capture_options *capture_opts)
1553 /* We've done this in "prepared" above, but it will be cleared while
1554 switching to the next multiple file. */
1555 main_capture_set_main_window_title(capture_opts);
1557 set_menus_for_capture_in_progress(TRUE);
1558 set_capture_if_dialog_for_capture_in_progress(TRUE);
1560 /* Enable menu items that make sense if you have some captured
1561 packets (yes, I know, we don't have any *yet*). */
1562 set_menus_for_captured_packets(TRUE);
1564 /* Set up main window for a capture file. */
1565 main_set_for_capture_file(TRUE);
1569 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1571 capture_file *cf = capture_opts->cf;
1572 static GList *icon_list = NULL;
1574 if (!cf->is_tempfile && cf->filename) {
1575 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1576 add_menu_recent_capture_file(cf->filename);
1578 set_display_filename(cf);
1580 /* Enable menu items that make sense if you're not currently running
1582 set_menus_for_capture_in_progress(FALSE);
1583 set_capture_if_dialog_for_capture_in_progress(FALSE);
1585 /* Enable menu items that make sense if you have a capture file
1586 you've finished reading. */
1587 set_menus_for_capture_file(cf);
1589 /* Set up main window for a capture file. */
1590 main_set_for_capture_file(TRUE);
1592 if(icon_list == NULL) {
1593 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1595 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1597 if(global_capture_opts.quit_after_cap) {
1598 /* command line asked us to quit after the capture */
1599 /* don't pop up a dialog to ask for unsaved files etc. */
1605 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1607 /* Don't set up main window for a capture file. */
1608 main_set_for_capture_file(FALSE);
1612 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1615 capture_file *cf = capture_opts->cf;
1617 static GList *icon_list = NULL;
1619 /*set_display_filename(cf);*/
1621 /* Enable menu items that make sense if you're not currently running
1623 set_menus_for_capture_in_progress(FALSE);
1624 set_capture_if_dialog_for_capture_in_progress(FALSE);
1626 /* Restore the standard title bar message */
1627 /* (just in case we have trouble opening the capture file). */
1628 set_main_window_name("The Wireshark Network Analyzer");
1630 if(icon_list == NULL) {
1631 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1633 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1635 /* We don't have loaded the capture file, this will be done later.
1636 * For now we still have simply a blank screen. */
1638 if(global_capture_opts.quit_after_cap) {
1639 /* command line asked us to quit after the capture */
1640 /* don't pop up a dialog to ask for unsaved files etc. */
1645 #endif /* HAVE_LIBPCAP */
1648 main_cf_cb_packet_selected(gpointer data)
1650 capture_file *cf = data;
1652 /* Display the GUI protocol tree and packet bytes.
1653 XXX - why do we dump core if we call "proto_tree_draw()"
1654 before calling "add_byte_views()"? */
1655 add_main_byte_views(cf->edt);
1656 main_proto_tree_draw(cf->edt->tree);
1658 /* Note: Both string and hex value searches in the packet data produce a non-zero
1659 search_pos if successful */
1660 if(cf->search_in_progress &&
1661 (cf->search_pos != 0 || (cf->string && cf->decode_data))) {
1662 highlight_field(cf->edt->tvb, cf->search_pos,
1663 (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1666 /* A packet is selected. */
1667 set_menus_for_selected_packet(cf);
1671 main_cf_cb_packet_unselected(capture_file *cf)
1673 /* Clear out the display of that packet. */
1674 clear_tree_and_hex_views();
1676 /* No packet is selected. */
1677 set_menus_for_selected_packet(cf);
1681 main_cf_cb_field_unselected(capture_file *cf)
1683 set_menus_for_selected_tree_row(cf);
1687 main_cf_cb_file_save_reload_finished(gpointer data _U_)
1689 set_display_filename(&cfile);
1690 set_menus_for_capture_file(&cfile);
1694 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1697 case(cf_cb_file_closing):
1698 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1699 main_cf_cb_file_closing(data);
1701 case(cf_cb_file_closed):
1702 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1703 main_cf_cb_file_closed(data);
1705 case(cf_cb_file_read_started):
1706 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1707 main_cf_cb_file_read_started(data);
1709 case(cf_cb_file_read_finished):
1710 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1711 main_cf_cb_file_read_finished(data);
1713 case(cf_cb_packet_selected):
1714 main_cf_cb_packet_selected(data);
1716 case(cf_cb_packet_unselected):
1717 main_cf_cb_packet_unselected(data);
1719 case(cf_cb_field_unselected):
1720 main_cf_cb_field_unselected(data);
1722 case(cf_cb_file_save_started):
1723 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1725 case(cf_cb_file_save_finished):
1726 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1728 case(cf_cb_file_save_reload_finished):
1729 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1730 main_cf_cb_file_save_reload_finished(data);
1732 case(cf_cb_file_save_failed):
1733 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1736 g_warning("main_cf_callback: event %u unknown", event);
1737 g_assert_not_reached();
1743 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1745 #ifdef HAVE_GTKOSXAPPLICATION
1746 GtkOSXApplication *theApp;
1749 case(capture_cb_capture_prepared):
1750 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1751 main_capture_cb_capture_prepared(capture_opts);
1753 case(capture_cb_capture_update_started):
1754 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1755 main_capture_cb_capture_update_started(capture_opts);
1756 #ifdef HAVE_GTKOSXAPPLICATION
1757 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1758 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsiconcap48_xpm));
1761 case(capture_cb_capture_update_continue):
1762 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1764 case(capture_cb_capture_update_finished):
1765 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1766 main_capture_cb_capture_update_finished(capture_opts);
1768 case(capture_cb_capture_fixed_started):
1769 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1770 main_capture_cb_capture_fixed_started(capture_opts);
1772 case(capture_cb_capture_fixed_continue):
1773 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1775 case(capture_cb_capture_fixed_finished):
1776 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1777 main_capture_cb_capture_fixed_finished(capture_opts);
1779 case(capture_cb_capture_stopping):
1780 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1781 /* Beware: this state won't be called, if the capture child
1782 * closes the capturing on it's own! */
1783 #ifdef HAVE_GTKOSXAPPLICATION
1784 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1785 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
1789 g_warning("main_capture_callback: event %u unknown", event);
1790 g_assert_not_reached();
1796 get_gtk_compiled_info(GString *str)
1798 g_string_append(str, "with ");
1799 g_string_append_printf(str,
1800 #ifdef GTK_MAJOR_VERSION
1801 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1804 "GTK+ (version unknown)");
1806 g_string_append(str, ", ");
1810 get_gui_compiled_info(GString *str)
1812 epan_get_compiled_version_info(str);
1814 g_string_append(str, ", ");
1815 #ifdef HAVE_LIBPORTAUDIO
1816 #ifdef PORTAUDIO_API_1
1817 g_string_append(str, "with PortAudio <= V18");
1818 #else /* PORTAUDIO_API_1 */
1819 g_string_append(str, "with ");
1820 g_string_append(str, Pa_GetVersionText());
1821 #endif /* PORTAUDIO_API_1 */
1822 #else /* HAVE_LIBPORTAUDIO */
1823 g_string_append(str, "without PortAudio");
1824 #endif /* HAVE_LIBPORTAUDIO */
1826 g_string_append(str, ", ");
1828 get_compiled_airpcap_version(str);
1830 g_string_append(str, "without AirPcap");
1835 get_gui_runtime_info(GString *str)
1837 epan_get_runtime_version_info(str);
1840 g_string_append(str, ", ");
1841 get_runtime_airpcap_version(str);
1845 g_string_append(str, ", ");
1846 u3_runtime_info(str);
1851 read_configuration_files(char **gdp_path, char **dp_path)
1853 int gpf_open_errno, gpf_read_errno;
1854 int cf_open_errno, df_open_errno;
1855 int gdp_open_errno, gdp_read_errno;
1856 int dp_open_errno, dp_read_errno;
1857 char *gpf_path, *pf_path;
1858 char *cf_path, *df_path;
1859 int pf_open_errno, pf_read_errno;
1862 /* Read the preference files. */
1863 prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1864 &pf_open_errno, &pf_read_errno, &pf_path);
1866 if (gpf_path != NULL) {
1867 if (gpf_open_errno != 0) {
1868 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1869 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1870 g_strerror(gpf_open_errno));
1872 if (gpf_read_errno != 0) {
1873 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1874 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1875 g_strerror(gpf_read_errno));
1878 if (pf_path != NULL) {
1879 if (pf_open_errno != 0) {
1880 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1881 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1882 g_strerror(pf_open_errno));
1884 if (pf_read_errno != 0) {
1885 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1886 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1887 g_strerror(pf_read_errno));
1894 /* if the user wants a console to be always there, well, we should open one for him */
1895 if (prefs_p->gui_console_open == console_open_always) {
1900 /* Read the capture filter file. */
1901 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1902 if (cf_path != NULL) {
1903 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1904 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1905 g_strerror(cf_open_errno));
1909 /* Read the display filter file. */
1910 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1911 if (df_path != NULL) {
1912 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1913 "Could not open your display filter file\n\"%s\": %s.", df_path,
1914 g_strerror(df_open_errno));
1918 /* Read the disabled protocols file. */
1919 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1920 dp_path, &dp_open_errno, &dp_read_errno);
1921 if (*gdp_path != NULL) {
1922 if (gdp_open_errno != 0) {
1923 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1924 "Could not open global disabled protocols file\n\"%s\": %s.",
1925 *gdp_path, g_strerror(gdp_open_errno));
1927 if (gdp_read_errno != 0) {
1928 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1929 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1930 *gdp_path, g_strerror(gdp_read_errno));
1935 if (*dp_path != NULL) {
1936 if (dp_open_errno != 0) {
1937 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1938 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1939 g_strerror(dp_open_errno));
1941 if (dp_read_errno != 0) {
1942 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1943 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1944 g_strerror(dp_read_errno));
1953 /* Check if there's something important to tell the user during startup.
1954 * We want to do this *after* showing the main window so that any windows
1955 * we pop up will be above the main window.
1959 check_and_warn_user_startup(gchar *cf_name)
1961 check_and_warn_user_startup(gchar *cf_name _U_)
1964 gchar *cur_user, *cur_group;
1965 gpointer priv_warning_dialog;
1967 /* Tell the user not to run as root. */
1968 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
1969 cur_user = get_cur_username();
1970 cur_group = get_cur_groupname();
1971 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1972 "Running as user \"%s\" and group \"%s\".\n"
1973 "This could be dangerous.", cur_user, cur_group);
1976 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1977 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
1981 /* Warn the user if npf.sys isn't loaded. */
1982 if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
1983 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1984 "The NPF driver isn't running. You may have trouble\n"
1985 "capturing or listing interfaces.");
1986 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1987 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
1994 /* And now our feature presentation... [ fade to music ] */
1996 main(int argc, char *argv[])
1998 char *init_progfile_dir_error;
2001 gboolean arg_error = FALSE;
2003 extern int info_update_freq; /* Found in about_dlg.c. */
2004 const gchar *filter;
2012 char *gdp_path, *dp_path;
2015 gboolean start_capture = FALSE;
2016 gboolean list_link_layer_types = FALSE;
2020 gboolean capture_option_specified = FALSE;
2027 gint pl_size = 280, tv_size = 95, bv_size = 75;
2028 gchar *rc_file, *cf_name = NULL, *rfilter = NULL, *jfilter = NULL;
2029 dfilter_t *rfcode = NULL;
2030 gboolean rfilter_parse_failed = FALSE;
2033 GtkWidget *splash_win = NULL;
2034 GLogLevelFlags log_flags;
2035 guint go_to_packet = 0;
2036 gboolean jump_backwards = FALSE;
2037 dfilter_t *jump_to_filter = NULL;
2040 #ifdef HAVE_GTKOSXAPPLICATION
2041 GtkOSXApplication *theApp;
2045 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2046 #define OPTSTRING_B "B:"
2048 #define OPTSTRING_B ""
2049 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2050 #else /* HAVE_LIBPCAP */
2051 #define OPTSTRING_B ""
2052 #endif /* HAVE_LIBPCAP */
2054 #ifdef HAVE_PCAP_CREATE
2055 #define OPTSTRING_I "I"
2057 #define OPTSTRING_I ""
2060 #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:"
2062 static const char optstring[] = OPTSTRING;
2064 /* Set the C-language locale to the native environment. */
2065 setlocale(LC_ALL, "");
2067 arg_list_utf_16to8(argc, argv);
2071 * Get credential information for later use, and drop privileges
2072 * before doing anything else.
2073 * Let the user know if anything happened.
2075 init_process_policies();
2076 relinquish_special_privs_perm();
2079 * Attempt to get the pathname of the executable file.
2081 init_progfile_dir_error = init_progfile_dir(argv[0], main);
2083 /* initialize the funnel mini-api */
2084 initialize_funnel_ops();
2086 AirPDcapInitContext(&airpdcap_ctx);
2089 /* Load wpcap if possible. Do this before collecting the run-time version information */
2092 /* ... and also load the packet.dll from wpcap */
2093 wpcap_packet_load();
2096 /* Load the airpcap.dll. This must also be done before collecting
2097 * run-time version information. */
2098 airpcap_dll_ret_val = load_airpcap();
2100 switch (airpcap_dll_ret_val) {
2101 case AIRPCAP_DLL_OK:
2102 /* load the airpcap interfaces */
2103 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2105 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2106 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2107 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2110 airpcap_if_active = NULL;
2114 /* select the first ad default (THIS SHOULD BE CHANGED) */
2115 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2120 * XXX - Maybe we need to warn the user if one of the following happens???
2122 case AIRPCAP_DLL_OLD:
2123 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2126 case AIRPCAP_DLL_ERROR:
2127 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2130 case AIRPCAP_DLL_NOT_FOUND:
2131 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2135 #endif /* HAVE_AIRPCAP */
2137 /* Start windows sockets */
2138 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2141 profile_store_persconffiles (TRUE);
2143 /* Assemble the compile-time version information string */
2144 comp_info_str = g_string_new("Compiled ");
2146 get_compiled_version_info(comp_info_str, get_gtk_compiled_info, get_gui_compiled_info);
2148 /* Assemble the run-time version information string */
2149 runtime_info_str = g_string_new("Running ");
2150 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2152 /* Read the profile independent recent file. We have to do this here so we can */
2153 /* set the profile before it can be set from the command line parameterts */
2154 recent_read_static(&rf_path, &rf_open_errno);
2155 if (rf_path != NULL && rf_open_errno != 0) {
2156 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2157 "Could not open common recent file\n\"%s\": %s.",
2158 rf_path, g_strerror(rf_open_errno));
2161 /* "pre-scan" the command line parameters, if we have "console only"
2162 parameters. We do this so we don't start GTK+ if we're only showing
2163 command-line help or version information.
2165 XXX - this pre-scan is done before we start GTK+, so we haven't
2166 run gtk_init() on the arguments. That means that GTK+ arguments
2167 have not been removed from the argument list; those arguments
2168 begin with "--", and will be treated as an error by getopt().
2170 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2173 optind_initial = optind;
2174 while ((opt = getopt(argc, argv, optstring)) != -1) {
2176 case 'C': /* Configuration Profile */
2177 if (profile_exists (optarg, FALSE)) {
2178 set_profile_name (optarg);
2180 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2184 case 'D': /* Print a list of capture devices and exit */
2186 if_list = capture_interface_list(&err, &err_str);
2187 if (if_list == NULL) {
2189 case CANT_GET_INTERFACE_LIST:
2190 cmdarg_err("%s", err_str);
2194 case NO_INTERFACES_FOUND:
2195 cmdarg_err("There are no interfaces on which a capture can be done");
2200 capture_opts_print_interfaces(if_list);
2201 free_interface_list(if_list);
2204 capture_option_specified = TRUE;
2208 case 'h': /* Print help and exit */
2214 if (strcmp(optarg, "-") == 0)
2215 stdin_capture = TRUE;
2218 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2219 status = filesystem_opt(opt, optarg);
2221 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2225 case 'v': /* Show version and exit */
2231 * Extension command line options have to be processed before
2232 * we call epan_init() as they are supposed to be used by dissectors
2233 * or taps very early in the registration process.
2237 case '?': /* Ignore errors - the "real" scan will catch them. */
2242 /* Init the "Open file" dialog directory */
2243 /* (do this after the path settings are processed) */
2245 /* Read the profile dependent (static part) of the recent file. */
2246 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2247 /* recent lists which is done in the dynamic part. */
2248 /* We have to do this already here, so command line parameters can overwrite these values. */
2249 recent_read_profile_static(&rf_path, &rf_open_errno);
2250 if (rf_path != NULL && rf_open_errno != 0) {
2251 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2252 "Could not open recent file\n\"%s\": %s.",
2253 rf_path, g_strerror(rf_open_errno));
2256 if (recent.gui_fileopen_remembered_dir &&
2257 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
2258 set_last_open_dir(recent.gui_fileopen_remembered_dir);
2260 set_last_open_dir(get_persdatafile_dir());
2263 /* Set getopt index back to initial value, so it will start with the
2264 first command line parameter again. Also reset opterr to 1, so that
2265 error messages are printed by getopt().
2267 XXX - this seems to work on most platforms, but time will tell.
2268 The Single UNIX Specification says "The getopt() function need
2269 not be reentrant", so this isn't guaranteed to work. The Mac
2270 OS X 10.4[.x] getopt() man page says
2272 In order to use getopt() to evaluate multiple sets of arguments, or to
2273 evaluate a single set of arguments multiple times, the variable optreset
2274 must be set to 1 before the second and each additional set of calls to
2275 getopt(), and the variable optind must be reinitialized.
2279 The optreset variable was added to make it possible to call the getopt()
2280 function multiple times. This is an extension to the IEEE Std 1003.2
2281 (``POSIX.2'') specification.
2283 which I think comes from one of the other BSDs.
2285 XXX - if we want to control all the command-line option errors, so
2286 that we can display them where we choose (e.g., in a window), we'd
2287 want to leave opterr as 0, and produce our own messages using optopt.
2288 We'd have to check the value of optopt to see if it's a valid option
2289 letter, in which case *presumably* the error is "this option requires
2290 an argument but none was specified", or not a valid option letter,
2291 in which case *presumably* the error is "this option isn't valid".
2292 Some versions of getopt() let you supply a option string beginning
2293 with ':', which means that getopt() will return ':' rather than '?'
2294 for "this option requires an argument but none was specified", but
2296 optind = optind_initial;
2299 /* Set the current locale according to the program environment.
2300 * We haven't localized anything, but some GTK widgets are localized
2301 * (the file selection dialogue, for example).
2302 * This also sets the C-language locale to the native environment. */
2305 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2306 gtk_init (&argc, &argv);
2308 cf_callback_add(main_cf_callback, NULL);
2310 capture_callback_add(main_capture_callback, NULL);
2312 cf_callback_add(statusbar_cf_callback, NULL);
2314 capture_callback_add(statusbar_capture_callback, NULL);
2317 /* Arrange that if we have no console window, and a GLib message logging
2318 routine is called to log a message, we pop up a console window.
2320 We do that by inserting our own handler for all messages logged
2321 to the default domain; that handler pops up a console if necessary,
2322 and then calls the default handler. */
2324 /* We might want to have component specific log levels later ... */
2328 G_LOG_LEVEL_CRITICAL|
2329 G_LOG_LEVEL_WARNING|
2330 G_LOG_LEVEL_MESSAGE|
2333 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2335 g_log_set_handler(NULL,
2337 console_log_handler, NULL /* user_data */);
2338 g_log_set_handler(LOG_DOMAIN_MAIN,
2340 console_log_handler, NULL /* user_data */);
2343 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2345 console_log_handler, NULL /* user_data */);
2346 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2348 console_log_handler, NULL /* user_data */);
2350 /* Set the initial values in the capture options. This might be overwritten
2351 by preference settings and then again by the command line parameters. */
2352 capture_opts_init(&global_capture_opts, &cfile);
2355 /* Initialize whatever we need to allocate colors for GTK+ */
2358 /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2359 filter = get_conn_cfilter();
2360 if ( *filter != '\0' ) {
2361 info_update_freq = 1000; /* Milliseconds */
2364 /* We won't come till here, if we had a "console only" command line parameter. */
2365 splash_win = splash_new("Loading Wireshark ...");
2366 if (init_progfile_dir_error != NULL) {
2367 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2368 "Can't get pathname of Wireshark: %s.\n"
2369 "It won't be possible to capture traffic.\n"
2370 "Report this to the Wireshark developers.",
2371 init_progfile_dir_error);
2372 g_free(init_progfile_dir_error);
2375 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2377 /* Register all dissectors; we must do this before checking for the
2378 "-G" flag, as the "-G" flag dumps information registered by the
2379 dissectors, and we must do it before we read the preferences, in
2380 case any dissectors register preferences. */
2381 epan_init(register_all_protocols,register_all_protocol_handoffs,
2382 splash_update, (gpointer) splash_win,
2383 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2384 write_failure_alert_box);
2386 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2388 /* Register all tap listeners; we do this before we parse the arguments,
2389 as the "-z" argument can specify a registered tap. */
2391 /* we register the plugin taps before the other taps because
2392 stats_tree taps plugins will be registered as tap listeners
2393 by stats_tree_stat.c and need to registered before that */
2396 register_all_plugin_tap_listeners();
2399 register_all_tap_listeners();
2401 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2403 /* Now register the preferences for any non-dissector modules.
2404 We must do that before we read the preferences as well. */
2405 prefs_register_modules();
2407 prefs_p = read_configuration_files (&gdp_path, &dp_path);
2408 /* Removed thread code:
2409 * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
2412 /* this is to keep tap extensions updating once every 3 seconds */
2413 tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2415 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2417 cap_file_init(&cfile);
2419 /* Fill in capture options with values from the preferences */
2420 prefs_to_capture_opts();
2422 /* Now get our args */
2423 while ((opt = getopt(argc, argv, optstring)) != -1) {
2425 /*** capture option specific ***/
2426 case 'a': /* autostop criteria */
2427 case 'b': /* Ringbuffer option */
2428 case 'c': /* Capture xxx packets */
2429 case 'f': /* capture filter */
2430 case 'k': /* Start capture immediately */
2431 case 'H': /* Hide capture info dialog box */
2432 case 'i': /* Use interface xxx */
2433 case 'p': /* Don't capture in promiscuous mode */
2434 #ifdef HAVE_PCAP_CREATE
2435 case 'I': /* Capture in monitor mode, if available */
2437 case 'Q': /* Quit after capture (just capture to file) */
2438 case 's': /* Set the snapshot (capture) length */
2439 case 'S': /* "Sync" mode: used for following file ala tail -f */
2440 case 'w': /* Write to capture file xxx */
2441 case 'y': /* Set the pcap data link type */
2442 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2443 case 'B': /* Buffer size */
2444 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2446 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2452 capture_option_specified = TRUE;
2457 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2458 case 'K': /* Kerberos keytab file */
2459 read_keytab_file(optarg);
2463 /*** all non capture option specific ***/
2465 /* Configuration profile settings were already processed just ignore them this time*/
2467 case 'j': /* Search backwards for a matching packet from filter in option J */
2468 jump_backwards = TRUE;
2470 case 'g': /* Go to packet with the given packet number */
2471 go_to_packet = get_positive_int(optarg, "go to packet");
2473 case 'J': /* Jump to the first packet which matches the filter criteria */
2476 case 'l': /* Automatic scrolling in live capture mode */
2478 auto_scroll_live = TRUE;
2480 capture_option_specified = TRUE;
2484 case 'L': /* Print list of link-layer types and exit */
2486 list_link_layer_types = TRUE;
2488 capture_option_specified = TRUE;
2492 case 'm': /* Fixed-width font for the display */
2493 g_free(prefs_p->gui_font_name);
2494 prefs_p->gui_font_name = g_strdup(optarg);
2496 case 'n': /* No name resolution */
2497 gbl_resolv_flags = RESOLV_NONE;
2499 case 'N': /* Select what types of addresses/port #s to resolve */
2500 if (gbl_resolv_flags == RESOLV_ALL)
2501 gbl_resolv_flags = RESOLV_NONE;
2502 badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
2503 if (badopt != '\0') {
2504 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2509 case 'o': /* Override preference from command line */
2510 switch (prefs_set_pref(optarg)) {
2513 case PREFS_SET_SYNTAX_ERR:
2514 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2517 case PREFS_SET_NO_SUCH_PREF:
2518 /* not a preference, might be a recent setting */
2519 switch (recent_set_arg(optarg)) {
2522 case PREFS_SET_SYNTAX_ERR:
2523 /* shouldn't happen, checked already above */
2524 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2527 case PREFS_SET_NO_SUCH_PREF:
2528 case PREFS_SET_OBSOLETE:
2529 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2534 g_assert_not_reached();
2537 case PREFS_SET_OBSOLETE:
2538 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2543 g_assert_not_reached();
2547 /* Path settings were already processed just ignore them this time*/
2549 case 'r': /* Read capture file xxx */
2550 /* We may set "last_open_dir" to "cf_name", and if we change
2551 "last_open_dir" later, we free the old value, so we have to
2552 set "cf_name" to something that's been allocated. */
2553 cf_name = g_strdup(optarg);
2555 case 'R': /* Read file filter */
2558 case 't': /* Time stamp type */
2559 if (strcmp(optarg, "r") == 0)
2560 timestamp_set_type(TS_RELATIVE);
2561 else if (strcmp(optarg, "a") == 0)
2562 timestamp_set_type(TS_ABSOLUTE);
2563 else if (strcmp(optarg, "ad") == 0)
2564 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2565 else if (strcmp(optarg, "d") == 0)
2566 timestamp_set_type(TS_DELTA);
2567 else if (strcmp(optarg, "dd") == 0)
2568 timestamp_set_type(TS_DELTA_DIS);
2569 else if (strcmp(optarg, "e") == 0)
2570 timestamp_set_type(TS_EPOCH);
2571 else if (strcmp(optarg, "u") == 0)
2572 timestamp_set_type(TS_UTC);
2573 else if (strcmp(optarg, "ud") == 0)
2574 timestamp_set_type(TS_UTC_WITH_DATE);
2576 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2577 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2578 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2582 case 'u': /* Seconds type */
2583 if (strcmp(optarg, "s") == 0)
2584 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
2585 else if (strcmp(optarg, "hms") == 0)
2586 timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
2588 cmdarg_err("Invalid seconds type \"%s\"", optarg);
2589 cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
2594 /* ext ops were already processed just ignore them this time*/
2597 /* We won't call the init function for the stat this soon
2598 as it would disallow MATE's fields (which are registered
2599 by the preferences set callback) from being used as
2600 part of a tap filter. Instead, we just add the argument
2601 to a list of stat arguments. */
2602 if (!process_stat_cmd_arg(optarg)) {
2603 cmdarg_err("Invalid -z argument.");
2604 cmdarg_err_cont(" -z argument must be one of :");
2605 list_stat_cmd_args();
2610 case '?': /* Bad flag - print usage message */
2619 if (cf_name != NULL) {
2621 * Input file name specified with "-r" *and* specified as a regular
2622 * command-line argument.
2624 cmdarg_err("File name specified both with -r and regular argument");
2628 * Input file name not specified with "-r", and a command-line argument
2629 * was specified; treat it as the input file name.
2631 * Yes, this is different from tshark, where non-flag command-line
2632 * arguments are a filter, but this works better on GUI desktops
2633 * where a command can be specified to be run to open a particular
2634 * file - yes, you could have "-r" as the last part of the command,
2635 * but that's a bit ugly.
2637 cf_name = g_strdup(argv[0]);
2645 * Extra command line arguments were specified; complain.
2647 cmdarg_err("Invalid argument: %s", argv[0]);
2652 #ifndef HAVE_LIBPCAP
2653 if (capture_option_specified) {
2654 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2662 if (start_capture && list_link_layer_types) {
2663 /* Specifying *both* is bogus. */
2664 cmdarg_err("You can't specify both -L and a live capture.");
2668 if (list_link_layer_types) {
2669 /* We're supposed to list the link-layer types for an interface;
2670 did the user also specify a capture file to be read? */
2672 /* Yes - that's bogus. */
2673 cmdarg_err("You can't specify -L and a capture file to be read.");
2676 /* No - did they specify a ring buffer option? */
2677 if (global_capture_opts.multi_files_on) {
2678 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2682 /* We're supposed to do a live capture; did the user also specify
2683 a capture file to be read? */
2684 if (start_capture && cf_name) {
2685 /* Yes - that's bogus. */
2686 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2690 /* No - was the ring buffer option specified and, if so, does it make
2692 if (global_capture_opts.multi_files_on) {
2693 /* Ring buffer works only under certain conditions:
2694 a) ring buffer does not work with temporary files;
2695 b) real_time_mode and multi_files_on are mutually exclusive -
2696 real_time_mode takes precedence;
2697 c) it makes no sense to enable the ring buffer if the maximum
2698 file size is set to "infinite". */
2699 if (global_capture_opts.save_file == NULL) {
2700 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2701 global_capture_opts.multi_files_on = FALSE;
2703 /* if (global_capture_opts.real_time_mode) {
2704 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2705 global_capture_opts.multi_files_on = FALSE;
2707 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2708 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2709 /* XXX - this must be redesigned as the conditions changed */
2710 /* global_capture_opts.multi_files_on = FALSE;*/
2715 if (start_capture || list_link_layer_types) {
2716 /* Did the user specify an interface to use? */
2717 if (!capture_opts_trim_iface(&global_capture_opts,
2718 (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2723 if (list_link_layer_types) {
2724 /* Get the list of link-layer types for the capture devices. */
2725 if_capabilities_t *caps;
2727 interface_options interface_opts;
2729 for (i = 0; i < global_capture_opts.ifaces->len; i++) {
2731 interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
2732 caps = capture_get_if_capabilities(interface_opts.name, interface_opts.monitor_mode, &err_str);
2734 cmdarg_err("%s", err_str);
2738 if (caps->data_link_types == NULL) {
2739 cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name);
2742 capture_opts_print_if_capabilities(caps, interface_opts.name, interface_opts.monitor_mode);
2743 free_if_capabilities(caps);
2748 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2749 capture_opts_trim_ring_num_files(&global_capture_opts);
2750 #endif /* HAVE_LIBPCAP */
2752 /* Notify all registered modules that have had any of their preferences
2753 changed either from one of the preferences file or from the command
2754 line that their preferences have changed. */
2757 /* disabled protocols as per configuration file */
2758 if (gdp_path == NULL && dp_path == NULL) {
2759 set_disabled_protos_list();
2762 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2764 /* read in rc file from global and personal configuration paths. */
2765 rc_file = get_datafile_path(RC_FILE);
2766 gtk_rc_parse(rc_file);
2768 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2769 gtk_rc_parse(rc_file);
2778 /* close the splash screen, as we are going to open the main window now */
2779 splash_destroy(splash_win);
2781 /************************************************************************/
2782 /* Everything is prepared now, preferences and command line was read in */
2784 /* Pop up the main window. */
2785 create_main_window(pl_size, tv_size, bv_size, prefs_p);
2787 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2788 recent_read_dynamic(&rf_path, &rf_open_errno);
2789 if (rf_path != NULL && rf_open_errno != 0) {
2790 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2791 "Could not open recent file\n\"%s\": %s.",
2792 rf_path, g_strerror(rf_open_errno));
2795 color_filters_enable(recent.packet_list_colorize);
2797 /* rearrange all the widgets as we now have all recent settings ready for this */
2798 main_widgets_rearrange();
2800 /* Fill in column titles. This must be done after the top level window
2803 XXX - is that still true, with fixed-width columns? */
2805 menu_recent_read_finished();
2807 menu_auto_scroll_live_changed(auto_scroll_live);
2810 switch (user_font_apply()) {
2813 case FA_FONT_NOT_RESIZEABLE:
2814 /* "user_font_apply()" popped up an alert box. */
2815 /* turn off zooming - font can't be resized */
2816 case FA_FONT_NOT_AVAILABLE:
2817 /* XXX - did we successfully load the un-zoomed version earlier?
2818 If so, this *probably* means the font is available, but not at
2819 this particular zoom level, but perhaps some other failure
2820 occurred; I'm not sure you can determine which is the case,
2822 /* turn off zooming - zoom level is unavailable */
2824 /* in any other case than FA_SUCCESS, turn off zooming */
2825 recent.gui_zoom_level = 0;
2826 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2829 dnd_init(top_level);
2831 color_filters_init();
2834 /* the window can be sized only, if it's not already shown, so do it now! */
2835 main_load_window_geometry(top_level);
2837 g_timeout_add(info_update_freq, resolv_update_cb, NULL);
2840 /* If we were given the name of a capture file, read it in now;
2841 we defer it until now, so that, if we can't open it, and pop
2842 up an alert box, the alert box is more likely to come up on
2843 top of the main window - but before the preference-file-error
2844 alert box, so, if we get one of those, it's more likely to come
2847 show_main_window(TRUE);
2848 check_and_warn_user_startup(cf_name);
2849 if (rfilter != NULL) {
2850 if (!dfilter_compile(rfilter, &rfcode)) {
2851 bad_dfilter_alert_box(rfilter);
2852 rfilter_parse_failed = TRUE;
2855 if (!rfilter_parse_failed) {
2856 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2857 /* "cf_open()" succeeded, so it closed the previous
2858 capture file, and thus destroyed any previous read filter
2859 attached to "cf". */
2861 cfile.rfcode = rfcode;
2862 /* Open stat windows; we do so after creating the main window,
2863 to avoid GTK warnings, and after successfully opening the
2864 capture file, so we know we have something to compute stats
2865 on, and after registering all dissectors, so that MATE will
2866 have registered its field array and we can have a tap filter
2867 with one of MATE's late-registered fields as part of the
2869 start_requested_stats();
2871 /* Read the capture file. */
2872 switch (cf_read(&cfile, FALSE)) {
2876 /* Just because we got an error, that doesn't mean we were unable
2877 to read any of the file; we handle what we could get from the
2879 /* if the user told us to jump to a specific packet, do it now */
2880 if(go_to_packet != 0) {
2881 /* Jump to the specified frame number, kept for backward
2883 cf_goto_frame(&cfile, go_to_packet);
2884 } else if (jfilter != NULL) {
2885 /* try to compile given filter */
2886 if (!dfilter_compile(jfilter, &jump_to_filter)) {
2887 bad_dfilter_alert_box(jfilter);
2889 /* Filter ok, jump to the first packet matching the filter
2890 conditions. Default search direction is forward, but if
2891 option d was given, search backwards */
2892 cf_find_packet_dfilter(&cfile, jump_to_filter, jump_backwards);
2897 case CF_READ_ABORTED:
2903 /* If the filename is not the absolute path, prepend the current dir. This happens
2904 when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */
2905 if (!g_path_is_absolute(cf_name)) {
2906 char *old_cf_name = cf_name;
2907 char *pwd = g_get_current_dir();
2908 cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name);
2909 g_free(old_cf_name);
2913 /* Save the name of the containing directory specified in the
2914 path name, if any; we can write over cf_name, which is a
2915 good thing, given that "get_dirname()" does write over its
2917 s = get_dirname(cf_name);
2918 set_last_open_dir(s);
2923 dfilter_free(rfcode);
2924 cfile.rfcode = NULL;
2925 show_main_window(FALSE);
2926 /* Don't call check_and_warn_user_startup(): we did it above */
2927 set_menus_for_capture_in_progress(FALSE);
2928 set_capture_if_dialog_for_capture_in_progress(FALSE);
2933 if (start_capture) {
2934 if (global_capture_opts.save_file != NULL) {
2935 /* Save the directory name for future file dialogs. */
2936 /* (get_dirname overwrites filename) */
2937 s = get_dirname(g_strdup(global_capture_opts.save_file));
2938 set_last_open_dir(s);
2941 /* "-k" was specified; start a capture. */
2942 show_main_window(TRUE);
2943 check_and_warn_user_startup(cf_name);
2944 if (capture_start(&global_capture_opts)) {
2945 /* The capture started. Open stat windows; we do so after creating
2946 the main window, to avoid GTK warnings, and after successfully
2947 opening the capture file, so we know we have something to compute
2948 stats on, and after registering all dissectors, so that MATE will
2949 have registered its field array and we can have a tap filter with
2950 one of MATE's late-registered fields as part of the filter. */
2951 start_requested_stats();
2955 show_main_window(FALSE);
2956 check_and_warn_user_startup(cf_name);
2957 set_menus_for_capture_in_progress(FALSE);
2958 set_capture_if_dialog_for_capture_in_progress(FALSE);
2961 /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
2962 if (!start_capture && !global_capture_opts.default_options.cfilter) {
2963 global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
2965 #else /* HAVE_LIBPCAP */
2966 show_main_window(FALSE);
2967 check_and_warn_user_startup(cf_name);
2968 set_menus_for_capture_in_progress(FALSE);
2969 set_capture_if_dialog_for_capture_in_progress(FALSE);
2970 #endif /* HAVE_LIBPCAP */
2973 /* register our pid if we are being run from a U3 device */
2976 profile_store_persconffiles (FALSE);
2978 #ifdef HAVE_GTKOSXAPPLICATION
2979 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
2980 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
2981 gtk_osxapplication_ready(theApp);
2984 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
2986 /* we'll enter the GTK loop now and hand the control over to GTK ... */
2988 /* ... back from GTK, we're going down now! */
2990 /* deregister our pid */
2991 u3_deregister_pid();
2995 AirPDcapDestroyContext(&airpdcap_ctx);
2998 /* hide the (unresponsive) main window, while asking the user to close the console window */
2999 gtk_widget_hide(top_level);
3001 #ifdef HAVE_GTKOSXAPPLICATION
3002 g_object_unref(theApp);
3005 /* Shutdown windows sockets */
3008 /* For some unknown reason, the "atexit()" call in "create_console()"
3009 doesn't arrange that "destroy_console()" be called when we exit,
3010 so we call it here if a console was created. */
3019 /* We build this as a GUI subsystem application on Win32, so
3020 "WinMain()", not "main()", gets called.
3022 Hack shamelessly stolen from the Win32 port of the GIMP. */
3024 #define _stdcall __attribute__((stdcall))
3028 WinMain (struct HINSTANCE__ *hInstance,
3029 struct HINSTANCE__ *hPrevInstance,
3033 INITCOMMONCONTROLSEX comm_ctrl;
3036 * Initialize our DLL search path. MUST be called before LoadLibrary
3039 ws_init_dll_search_path();
3041 /* Initialize our controls. Required for native Windows file dialogs. */
3042 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3043 comm_ctrl.dwSize = sizeof(comm_ctrl);
3044 /* Includes the animate, header, hot key, list view, progress bar,
3045 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3048 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3049 InitCommonControlsEx(&comm_ctrl);
3051 /* RichEd20.DLL is needed for filter entries. */
3052 ws_load_library("riched20.dll");
3054 has_console = FALSE;
3055 console_wait = FALSE;
3056 return main (__argc, __argv);
3059 /* The code to create and desstroy console windows should not be necessary,
3060 at least as I read the GLib source code, as it looks as if GLib is, on
3061 Win32, *supposed* to create a console window into which to display its
3064 That doesn't happen, however. I suspect there's something completely
3065 broken about that code in GLib-for-Win32, and that it may be related
3066 to the breakage that forces us to just call "printf()" on the message
3067 rather than passing the message on to "g_log_default_handler()"
3068 (which is the routine that does the aforementioned non-functional
3069 console window creation). */
3072 * If this application has no console window to which its standard output
3073 * would go, create one.
3076 create_console(void)
3078 if (stdin_capture) {
3079 /* We've been handed "-i -". Don't mess with stdio. */
3084 /* We have no console to which to print the version string, so
3085 create one and make it the standard input, output, and error. */
3088 * See if we have an existing console (i.e. we were run from a
3091 if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
3092 if (AllocConsole()) {
3093 console_wait = TRUE;
3094 SetConsoleTitle(_T("Wireshark Debug Console"));
3096 return; /* couldn't create console */
3100 ws_freopen("CONIN$", "r", stdin);
3101 ws_freopen("CONOUT$", "w", stdout);
3102 ws_freopen("CONOUT$", "w", stderr);
3103 fprintf(stdout, "\n");
3104 fprintf(stderr, "\n");
3106 /* Now register "destroy_console()" as a routine to be called just
3107 before the application exits, so that we can destroy the console
3108 after the user has typed a key (so that the console doesn't just
3109 disappear out from under them, giving the user no chance to see
3110 the message(s) we put in there). */
3111 atexit(destroy_console);
3113 /* Well, we have a console now. */
3119 destroy_console(void)
3122 printf("\n\nPress any key to exit\n");
3131 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3132 const char *message, gpointer user_data _U_)
3139 /* ignore log message, if log_level isn't interesting based
3140 upon the console log preferences.
3141 If the preferences haven't been loaded loaded yet, display the
3144 The default console_log_level preference value is such that only
3145 ERROR, CRITICAL and WARNING level messages are processed;
3146 MESSAGE, INFO and DEBUG level messages are ignored. */
3147 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3148 prefs.console_log_level != 0) {
3153 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3154 /* the user wants a console or the application will terminate immediately */
3158 /* For some unknown reason, the above doesn't appear to actually cause
3159 anything to be sent to the standard output, so we'll just splat the
3160 message out directly, just to make sure it gets out. */
3162 switch(log_level & G_LOG_LEVEL_MASK) {
3163 case G_LOG_LEVEL_ERROR:
3166 case G_LOG_LEVEL_CRITICAL:
3169 case G_LOG_LEVEL_WARNING:
3172 case G_LOG_LEVEL_MESSAGE:
3175 case G_LOG_LEVEL_INFO:
3178 case G_LOG_LEVEL_DEBUG:
3182 fprintf(stderr, "unknown log_level %u\n", log_level);
3184 g_assert_not_reached();
3187 /* create a "timestamp" */
3189 today = localtime(&curr);
3191 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3192 today->tm_hour, today->tm_min, today->tm_sec,
3193 log_domain != NULL ? log_domain : "",
3196 if(log_level & G_LOG_LEVEL_ERROR) {
3197 /* wait for a key press before the following error handler will terminate the program
3198 this way the user at least can read the error message */
3199 printf("\n\nPress any key to exit\n");
3203 /* XXX - on UN*X, should we just use g_log_default_handler()?
3204 We want the error messages to go to the standard output;
3205 on Mac OS X, that will cause them to show up in various
3206 per-user logs accessible through Console (details depend
3207 on whether you're running 10.0 through 10.4 or running
3208 10.5 and later), and, on other UN*X desktop environments,
3209 if they don't show up in some form of console log, that's
3210 a deficiency in that desktop environment. (Too bad
3211 Windows doesn't set the standard output and error for
3212 GUI apps to something that shows up in such a log.) */
3213 g_log_default_handler(log_domain, log_level, message, user_data);
3220 * Helper for main_widgets_rearrange()
3222 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3223 gtk_container_remove(GTK_CONTAINER(data), widget);
3226 static GtkWidget *main_widget_layout(gint layout_content)
3228 switch(layout_content) {
3229 case(layout_pane_content_none):
3231 case(layout_pane_content_plist):
3233 case(layout_pane_content_pdetails):
3235 case(layout_pane_content_pbytes):
3236 return byte_nb_ptr_gbl;
3238 g_assert_not_reached();
3245 * Rearrange the main window widgets
3247 void main_widgets_rearrange(void) {
3248 GtkWidget *first_pane_widget1, *first_pane_widget2;
3249 GtkWidget *second_pane_widget1, *second_pane_widget2;
3250 gboolean split_top_left;
3252 /* be a bit faster */
3253 gtk_widget_hide(main_vbox);
3255 /* be sure we don't lose a widget while rearranging */
3256 g_object_ref(G_OBJECT(menubar));
3257 g_object_ref(G_OBJECT(main_tb));
3258 g_object_ref(G_OBJECT(filter_tb));
3260 g_object_ref(G_OBJECT(airpcap_tb));
3262 g_object_ref(G_OBJECT(pkt_scrollw));
3263 g_object_ref(G_OBJECT(tv_scrollw));
3264 g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3265 g_object_ref(G_OBJECT(statusbar));
3266 g_object_ref(G_OBJECT(main_pane_v1));
3267 g_object_ref(G_OBJECT(main_pane_v2));
3268 g_object_ref(G_OBJECT(main_pane_h1));
3269 g_object_ref(G_OBJECT(main_pane_h2));
3270 g_object_ref(G_OBJECT(welcome_pane));
3272 /* empty all containers participating */
3273 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3274 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3275 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3276 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3277 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3279 statusbar_widgets_emptying(statusbar);
3281 /* add the menubar always at the top */
3282 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3285 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3287 /* filter toolbar in toolbar area */
3288 if (!prefs.filter_toolbar_show_in_statusbar) {
3289 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3293 /* airpcap toolbar */
3294 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3297 /* fill the main layout panes */
3298 switch(prefs.gui_layout_type) {
3299 case(layout_type_5):
3300 main_first_pane = main_pane_v1;
3301 main_second_pane = main_pane_v2;
3302 split_top_left = FALSE;
3304 case(layout_type_2):
3305 main_first_pane = main_pane_v1;
3306 main_second_pane = main_pane_h1;
3307 split_top_left = FALSE;
3309 case(layout_type_1):
3310 main_first_pane = main_pane_v1;
3311 main_second_pane = main_pane_h1;
3312 split_top_left = TRUE;
3314 case(layout_type_4):
3315 main_first_pane = main_pane_h1;
3316 main_second_pane = main_pane_v1;
3317 split_top_left = FALSE;
3319 case(layout_type_3):
3320 main_first_pane = main_pane_h1;
3321 main_second_pane = main_pane_v1;
3322 split_top_left = TRUE;
3324 case(layout_type_6):
3325 main_first_pane = main_pane_h1;
3326 main_second_pane = main_pane_h2;
3327 split_top_left = FALSE;
3330 main_first_pane = NULL;
3331 main_second_pane = NULL;
3332 split_top_left = FALSE;
3333 g_assert_not_reached();
3335 if (split_top_left) {
3336 first_pane_widget1 = main_second_pane;
3337 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3338 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3339 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3341 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3342 first_pane_widget2 = main_second_pane;
3343 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3344 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3346 if (first_pane_widget1 != NULL)
3347 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3348 if (first_pane_widget2 != NULL)
3349 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3350 if (second_pane_widget1 != NULL)
3351 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3352 if (second_pane_widget2 != NULL)
3353 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3355 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3358 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3361 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3363 /* filter toolbar in statusbar hbox */
3364 if (prefs.filter_toolbar_show_in_statusbar) {
3365 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3368 /* statusbar widgets */
3369 statusbar_widgets_pack(statusbar);
3371 /* hide widgets on users recent settings */
3372 main_widgets_show_or_hide();
3374 gtk_widget_show(main_vbox);
3378 is_widget_visible(GtkWidget *widget, gpointer data)
3380 gboolean *is_visible = data;
3383 #if GTK_CHECK_VERSION(2,18,0)
3384 if (gtk_widget_get_visible(widget))
3386 if (GTK_WIDGET_VISIBLE(widget))
3394 main_widgets_show_or_hide(void)
3396 gboolean main_second_pane_show;
3398 if (recent.main_toolbar_show) {
3399 gtk_widget_show(main_tb);
3401 gtk_widget_hide(main_tb);
3404 statusbar_widgets_show_or_hide(statusbar);
3406 if (recent.filter_toolbar_show) {
3407 gtk_widget_show(filter_tb);
3409 gtk_widget_hide(filter_tb);
3413 if (recent.airpcap_toolbar_show) {
3414 gtk_widget_show(airpcap_tb);
3416 gtk_widget_hide(airpcap_tb);
3420 if (recent.packet_list_show && have_capture_file) {
3421 gtk_widget_show(pkt_scrollw);
3423 gtk_widget_hide(pkt_scrollw);
3426 if (recent.tree_view_show && have_capture_file) {
3427 gtk_widget_show(tv_scrollw);
3429 gtk_widget_hide(tv_scrollw);
3432 if (recent.byte_view_show && have_capture_file) {
3433 gtk_widget_show(byte_nb_ptr_gbl);
3435 gtk_widget_hide(byte_nb_ptr_gbl);
3438 if (have_capture_file) {
3439 gtk_widget_show(main_first_pane);
3441 gtk_widget_hide(main_first_pane);
3445 * Is anything in "main_second_pane" visible?
3446 * If so, show it, otherwise hide it.
3448 main_second_pane_show = FALSE;
3449 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3450 &main_second_pane_show);
3451 if (main_second_pane_show) {
3452 gtk_widget_show(main_second_pane);
3454 gtk_widget_hide(main_second_pane);
3457 if (!have_capture_file) {
3459 gtk_widget_show(welcome_pane);
3460 welcome_if_tree_load();
3463 gtk_widget_hide(welcome_pane);
3468 /* called, when the window state changes (minimized, maximized, ...) */
3470 window_state_event_cb (GtkWidget *widget _U_,
3474 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3476 if( (event->type) == (GDK_WINDOW_STATE)) {
3477 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3478 /* we might have dialogs popped up while we where iconified,
3480 display_queued_messages();
3488 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3490 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3492 if (event->keyval == GDK_F8) {
3493 new_packet_list_next();
3495 } else if (event->keyval == GDK_F7) {
3496 new_packet_list_prev();
3498 } else if (event->state & NO_SHIFT_MOD_MASK) {
3499 return FALSE; /* Skip control, alt, and other modifiers */
3501 * A comment in gdkkeysyms.h says that it's autogenerated from
3502 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3503 * don't explicitly say so, isprint() should work as expected
3506 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3507 /* Forward the keypress on to the display filter entry */
3508 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3509 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3510 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3518 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3520 GtkAccelGroup *accel;
3523 top_level = window_new(GTK_WINDOW_TOPLEVEL, "");
3524 set_main_window_name("The Wireshark Network Analyzer");
3526 gtk_widget_set_name(top_level, "main window");
3527 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3529 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3530 G_CALLBACK(window_state_event_cb), NULL);
3531 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3532 G_CALLBACK(top_level_key_pressed_cb), NULL );
3534 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3535 main_vbox = gtk_vbox_new(FALSE, 1);
3536 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 0);
3537 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3538 gtk_widget_show(main_vbox);
3541 menubar = main_menu_new(&accel);
3543 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined (HAVE_GTKOSXAPPLICATION)
3544 /* Mac OS X native menus are created and displayed by main_menu_new() */
3545 if(!prefs_p->gui_macosx_style) {
3547 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3548 gtk_widget_show(menubar);
3549 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined(HAVE_GTKOSXAPPLICATION)
3554 main_tb = toolbar_new();
3555 gtk_widget_show (main_tb);
3557 /* Filter toolbar */
3558 filter_tb = filter_toolbar_new();
3561 pkt_scrollw = new_packet_list_create();
3562 gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3563 gtk_widget_show_all(pkt_scrollw);
3566 tv_scrollw = main_tree_view_new(prefs_p, &tree_view_gbl);
3567 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3568 gtk_widget_show(tv_scrollw);
3570 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3571 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3572 g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3573 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3574 gtk_widget_show(tree_view_gbl);
3577 byte_nb_ptr_gbl = byte_view_new();
3578 gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3579 gtk_widget_show(byte_nb_ptr_gbl);
3581 g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3582 g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3584 /* Panes for the packet list, tree, and byte view */
3585 main_pane_v1 = gtk_vpaned_new();
3586 gtk_widget_show(main_pane_v1);
3587 main_pane_v2 = gtk_vpaned_new();
3588 gtk_widget_show(main_pane_v2);
3589 main_pane_h1 = gtk_hpaned_new();
3590 gtk_widget_show(main_pane_h1);
3591 main_pane_h2 = gtk_hpaned_new();
3592 gtk_widget_show(main_pane_h2);
3594 airpcap_tb = airpcap_toolbar_new();
3595 gtk_widget_show(airpcap_tb);
3598 statusbar = statusbar_new();
3599 gtk_widget_show(statusbar);
3601 /* Pane for the welcome screen */
3602 welcome_pane = welcome_new();
3603 gtk_widget_show(welcome_pane);
3607 show_main_window(gboolean doing_work)
3609 main_set_for_capture_file(doing_work);
3611 /*** we have finished all init things, show the main window ***/
3612 gtk_widget_show(top_level);
3614 /* the window can be maximized only, if it's visible, so do it after show! */
3615 main_load_window_geometry(top_level);
3617 /* process all pending GUI events before continue */
3618 while (gtk_events_pending()) gtk_main_iteration();
3620 /* Pop up any queued-up alert boxes. */
3621 display_queued_messages();
3623 /* Move the main window to the front, in case it isn't already there */
3624 #if GTK_CHECK_VERSION(2,14,0)
3625 gdk_window_raise(gtk_widget_get_window(top_level));
3627 gdk_window_raise(top_level->window);
3631 airpcap_toolbar_show(airpcap_tb);
3632 #endif /* HAVE_AIRPCAP */
3635 /* Fill in capture options with values from the preferences */
3637 prefs_to_capture_opts(void)
3640 /* Set promiscuous mode from the preferences setting. */
3641 /* the same applies to other preferences settings as well. */
3642 global_capture_opts.default_options.promisc_mode = prefs.capture_prom_mode;
3643 global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
3644 global_capture_opts.show_info = prefs.capture_show_info;
3645 global_capture_opts.real_time_mode = prefs.capture_real_time;
3646 auto_scroll_live = prefs.capture_auto_scroll;
3647 #endif /* HAVE_LIBPCAP */
3649 /* Set the name resolution code's flags from the preferences. */
3650 gbl_resolv_flags = prefs.name_resolve;
3653 static void copy_global_profile (const gchar *profile_name)
3655 char *pf_dir_path, *pf_dir_path2, *pf_filename;
3657 if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) {
3658 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3659 "Can't create directory\n\"%s\":\n%s.",
3660 pf_dir_path, g_strerror(errno));
3662 g_free(pf_dir_path);
3665 if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename,
3666 &pf_dir_path, &pf_dir_path2) == -1) {
3667 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3668 "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
3669 pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
3671 g_free(pf_filename);
3672 g_free(pf_dir_path);
3673 g_free(pf_dir_path2);
3677 /* Change configuration profile */
3678 void change_configuration_profile (const gchar *profile_name)
3680 char *gdp_path, *dp_path;
3684 /* First check if profile exists */
3685 if (!profile_exists(profile_name, FALSE)) {
3686 if (profile_exists(profile_name, TRUE)) {
3687 /* Copy from global profile */
3688 copy_global_profile (profile_name);
3690 /* No personal and no global profile exists */
3695 /* Then check if changing to another profile */
3696 if (profile_name && strcmp (profile_name, get_profile_name()) == 0) {
3700 /* Get the current geometry, before writing it to disk */
3701 main_save_window_geometry(top_level);
3703 if (profile_exists(get_profile_name(), FALSE)) {
3704 /* Write recent file for profile we are leaving, if it still exists */
3705 write_profile_recent();
3708 /* Set profile name and update the status bar */
3709 set_profile_name (profile_name);
3710 profile_bar_update ();
3712 /* Reset current preferences and apply the new */
3716 (void) read_configuration_files (&gdp_path, &dp_path);
3718 recent_read_profile_static(&rf_path, &rf_open_errno);
3719 if (rf_path != NULL && rf_open_errno != 0) {
3720 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3721 "Could not open common recent file\n\"%s\": %s.",
3722 rf_path, g_strerror(rf_open_errno));
3724 if (recent.gui_fileopen_remembered_dir &&
3725 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
3726 set_last_open_dir(recent.gui_fileopen_remembered_dir);
3728 timestamp_set_type (recent.gui_time_format);
3729 timestamp_set_seconds_type (recent.gui_seconds_format);
3730 color_filters_enable(recent.packet_list_colorize);
3732 prefs_to_capture_opts();
3734 macros_post_update();
3736 /* Update window view and redraw the toolbar */
3737 update_main_window_title();
3738 toolbar_redraw_all();
3740 /* Enable all protocols and disable from the disabled list */
3742 if (gdp_path == NULL && dp_path == NULL) {
3743 set_disabled_protos_list();
3746 /* Reload color filters */
3747 color_filters_reload();
3749 /* Reload list of interfaces on welcome page */
3750 welcome_if_panel_reload();
3752 /* Recreate the packet list according to new preferences */
3753 new_packet_list_recreate ();
3754 cfile.cinfo.columns_changed = FALSE; /* Reset value */
3757 /* Update menus with new recent values */
3758 menu_recent_read_finished();
3760 /* Reload pane geometry, must be done after recreating the list */
3761 main_pane_load_window_geometry();
3764 /** redissect packets and update UI */
3765 void redissect_packets(void)
3767 cf_redissect_packets(&cfile);
3768 status_expert_update();