5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10 * needed by dissect routines
11 * Jeff Foster, 2001/03/12, added support tabbed hex display windowss
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <gdk/gdkkeysyms.h>
44 #ifdef NEED_STRERROR_H
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/emem.h>
84 #include <epan/column.h>
86 /* general (not GTK specific) */
88 #include "../summary.h"
89 #include "../filters.h"
90 #include "../disabled_protos.h"
92 #include "../color_filters.h"
94 #include "../simple_dialog.h"
95 #include "../register.h"
96 #include "../ringbuffer.h"
97 #include "../ui_util.h"
99 #include "../clopts_common.h"
100 #include "../cmdarg_err.h"
101 #include "../version_info.h"
102 #include "../merge.h"
103 #include "../alert_box.h"
104 #include "../capture_ui_utils.h"
106 #include <wsutil/file_util.h>
110 #include "../capture-pcap-util.h"
111 #include "../capture.h"
112 #include "../capture_sync.h"
116 #include "../capture-wpcap.h"
117 #include "../capture_wpcap_packet.h"
118 #include <tchar.h> /* Needed for Unicode */
119 #include <commctrl.h>
123 #include "gtk/file_dlg.h"
124 #include "gtk/gtkglobals.h"
125 #include "gtk/color_utils.h"
126 #include "gtk/gui_utils.h"
127 #include "gtk/color_dlg.h"
128 #include "gtk/filter_dlg.h"
129 #include "gtk/uat_gui.h"
131 #include "gtk/main.h"
132 #include "gtk/main_airpcap_toolbar.h"
133 #include "gtk/main_filter_toolbar.h"
134 #include "gtk/menus.h"
135 #include "gtk/main_packet_list.h"
136 #include "gtk/main_statusbar.h"
137 #include "gtk/main_statusbar_private.h"
138 #include "gtk/main_toolbar.h"
139 #include "gtk/main_welcome.h"
140 #include "gtk/drag_and_drop.h"
141 #include "gtk/capture_file_dlg.h"
142 #include "gtk/main_proto_draw.h"
143 #include "gtk/keys.h"
144 #include "gtk/packet_win.h"
145 #include "gtk/stock_icons.h"
146 #include "gtk/find_dlg.h"
147 #include "gtk/recent.h"
148 #include "gtk/follow_tcp.h"
149 #include "gtk/font_utils.h"
150 #include "gtk/about_dlg.h"
151 #include "gtk/help_dlg.h"
152 #include "gtk/decode_as_dlg.h"
153 #include "gtk/webbrowser.h"
154 #include "gtk/capture_dlg.h"
155 #include "gtk/capture_if_dlg.h"
156 #include "gtk/tap_dfilter_dlg.h"
157 #include "gtk/prefs_column.h"
160 #include "../image/wsicon16.xpm"
161 #include "../image/wsicon32.xpm"
162 #include "../image/wsicon48.xpm"
163 #include "../image/wsicon64.xpm"
164 #include "../image/wsiconcap16.xpm"
165 #include "../image/wsiconcap32.xpm"
166 #include "../image/wsiconcap48.xpm"
171 #include "airpcap_loader.h"
172 #include "airpcap_dlg.h"
173 #include "airpcap_gui_utils.h"
177 #include <epan/crypt/airpdcap_ws.h>
180 #ifdef NEW_PACKET_LIST
181 #include "gtk/new_packet_list.h"
185 * Files under personal and global preferences directories in which
186 * GTK settings for Wireshark are stored.
188 #define RC_FILE "gtkrc"
192 /* "exported" main widgets */
193 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view, *byte_nb_ptr;
195 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
196 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
197 static GtkWidget *main_first_pane, *main_second_pane;
199 /* internally used widgets */
200 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
203 GtkWidget *airpcap_tb;
204 int airpcap_dll_ret_val = -1;
207 GString *comp_info_str, *runtime_info_str;
208 gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
210 guint tap_update_timer_id;
213 static gboolean has_console; /* TRUE if app has console */
214 static void destroy_console(void);
215 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
217 static void console_log_handler(const char *log_domain,
218 GLogLevelFlags log_level, const char *message, gpointer user_data);
221 capture_options global_capture_opts;
225 static void create_main_window(gint, gint, gint, e_prefs*);
226 static void show_main_window(gboolean);
227 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
228 static void main_save_window_geometry(GtkWidget *widget);
231 /* Match selected byte pattern */
233 match_selected_cb_do(gpointer data, int action, gchar *text)
235 GtkWidget *filter_te;
236 char *cur_filter, *new_filter;
238 if ((!text) || (0 == strlen(text))) {
239 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
244 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
247 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
249 switch (action&MATCH_SELECTED_MASK) {
251 case MATCH_SELECTED_REPLACE:
252 new_filter = g_strdup(text);
255 case MATCH_SELECTED_AND:
256 if ((!cur_filter) || (0 == strlen(cur_filter)))
257 new_filter = g_strdup(text);
259 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
262 case MATCH_SELECTED_OR:
263 if ((!cur_filter) || (0 == strlen(cur_filter)))
264 new_filter = g_strdup(text);
266 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
269 case MATCH_SELECTED_NOT:
270 new_filter = g_strconcat("!(", text, ")", NULL);
273 case MATCH_SELECTED_AND_NOT:
274 if ((!cur_filter) || (0 == strlen(cur_filter)))
275 new_filter = g_strconcat("!(", text, ")", NULL);
277 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
280 case MATCH_SELECTED_OR_NOT:
281 if ((!cur_filter) || (0 == strlen(cur_filter)))
282 new_filter = g_strconcat("!(", text, ")", NULL);
284 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
288 g_assert_not_reached();
293 /* Free up the copy we got of the old filter text. */
296 /* Don't change the current display filter if we only want to copy the filter */
297 if (action&MATCH_SELECTED_COPY_ONLY) {
298 GString *gtk_text_str = g_string_new("");
299 g_string_append(gtk_text_str, new_filter);
300 copy_to_clipboard(gtk_text_str);
301 g_string_free(gtk_text_str, TRUE);
303 /* create a new one and set the display filter entry accordingly */
304 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
306 /* Run the display filter so it goes in effect. */
307 if (action&MATCH_SELECTED_APPLY_NOW)
308 main_filter_packets(&cfile, new_filter, FALSE);
311 /* Free up the new filter text. */
316 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
320 if (cfile.finfo_selected) {
321 filter = proto_construct_match_selected_string(cfile.finfo_selected,
323 match_selected_cb_do((data ? data : w), action, filter);
328 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
332 if (cfile.finfo_selected) {
333 filter = proto_construct_match_selected_string(cfile.finfo_selected,
335 if ((!filter) || (0 == strlen(filter))) {
336 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
337 "Could not acquire information to build a filter!\n"
338 "Try expanding or choosing another item.");
343 color_display_with_filter(filter);
346 color_filters_reset_tmp();
348 color_filters_set_tmp(filt_nr,filter, FALSE);
350 cf_colorize_packets(&cfile);
356 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
358 gchar *selected_proto_url;
359 gchar *proto_abbrev = data;
364 if (cfile.finfo_selected) {
365 /* open wiki page using the protocol abbreviation */
366 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
367 browser_open_url(selected_proto_url);
368 g_free(selected_proto_url);
371 case(ESD_BTN_CANCEL):
374 g_assert_not_reached();
380 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
383 const gchar *proto_abbrev;
387 if (cfile.finfo_selected) {
388 /* convert selected field to protocol abbreviation */
389 /* XXX - could this conversion be simplified? */
390 field_id = cfile.finfo_selected->hfinfo->id;
391 /* if the selected field isn't a protocol, get it's parent */
392 if(!proto_registrar_is_protocol(field_id)) {
393 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
396 proto_abbrev = proto_registrar_get_abbrev(field_id);
398 if (!proto_is_private(field_id)) {
399 /* ask the user if the wiki page really should be opened */
400 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
401 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
403 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
405 "The Wireshark Wiki is a collaborative approach to provide information "
406 "about Wireshark in several ways (not limited to protocol specifics).\n"
408 "This Wiki is new, so the page of the selected protocol "
409 "may not exist and/or may not contain valuable information.\n"
411 "As everyone can edit the Wiki and add new content (or extend existing), "
412 "you are encouraged to add information if you can.\n"
414 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
416 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
417 "which will save you a lot of editing and will give a consistent look over the pages.",
418 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
419 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
421 /* appologize to the user that the wiki page cannot be opened */
422 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
423 "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
425 "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
427 "Since this is a private protocol, such information is not available in "
428 "a public wiki. Therefore this wiki entry is blocked.\n"
430 "Sorry for the inconvenience.\n",
431 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
436 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
438 gchar *selected_proto_url;
439 gchar *proto_abbrev = data;
443 if (cfile.finfo_selected) {
444 /* open reference page using the protocol abbreviation */
445 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
446 browser_open_url(selected_proto_url);
447 g_free(selected_proto_url);
450 case(ESD_BTN_CANCEL):
453 g_assert_not_reached();
458 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
461 const gchar *proto_abbrev;
465 if (cfile.finfo_selected) {
466 /* convert selected field to protocol abbreviation */
467 /* XXX - could this conversion be simplified? */
468 field_id = cfile.finfo_selected->hfinfo->id;
469 /* if the selected field isn't a protocol, get it's parent */
470 if(!proto_registrar_is_protocol(field_id)) {
471 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
474 proto_abbrev = proto_registrar_get_abbrev(field_id);
476 if (!proto_is_private(field_id)) {
477 /* ask the user if the wiki page really should be opened */
478 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
479 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
481 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
483 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
484 simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
486 /* appologize to the user that the wiki page cannot be opened */
487 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
488 "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
490 "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
492 "Since this is a private protocol, such information is not available on "
493 "a public website. Therefore this filter entry is blocked.\n"
495 "Sorry for the inconvenience.\n",
496 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
502 get_filter_from_packet_list_row_and_column(gpointer data)
504 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
505 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
511 #ifdef NEW_PACKET_LIST
512 fdata = (frame_data *) new_packet_list_get_row_data(row);
514 fdata = (frame_data *) packet_list_get_row_data(row);
520 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
521 cfile.pd, fdata->cap_len, &err, &err_info)) {
522 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
523 cf_read_error_message(err, err_info), cfile.filename);
526 /* proto tree, visible. We need a proto tree if there's custom columns */
527 epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
528 col_custom_prime_edt(&edt, &cfile.cinfo);
530 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata,
532 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
534 if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
535 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
536 /* leak a little but safer than ep_ here*/
537 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
538 cfile.cinfo.col_expr.col_expr_val[column]);
541 epan_dissect_cleanup(&edt);
548 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
550 match_selected_cb_do(data,
552 get_filter_from_packet_list_row_and_column(data));
555 /* This function allows users to right click in the details window and copy the text
556 * information to the operating systems clipboard.
558 * We first check to see if a string representation is setup in the tree and then
559 * read the string. If not available then we try to grab the value. If all else
560 * fails we display a message to the user to indicate the copy could not be completed.
563 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
565 GString *gtk_text_str = g_string_new("");
566 char labelstring[256];
567 char *stringpointer = labelstring;
571 case COPY_SELECTED_DESCRIPTION:
572 if (cfile.finfo_selected->rep->representation != 0) {
573 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
576 case COPY_SELECTED_FIELDNAME:
577 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
578 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
581 case COPY_SELECTED_VALUE:
582 if (cfile.edt !=0 ) {
583 g_string_append(gtk_text_str,
584 get_node_field_value(cfile.finfo_selected, cfile.edt));
591 if (gtk_text_str->len == 0) {
592 /* If no representation then... Try to read the value */
593 proto_item_fill_label(cfile.finfo_selected, stringpointer);
594 g_string_append(gtk_text_str, stringpointer);
597 if (gtk_text_str->len == 0) {
598 /* Could not get item so display error msg */
599 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
601 /* Copy string to clipboard */
602 copy_to_clipboard(gtk_text_str);
604 g_string_free(gtk_text_str, TRUE); /* Free the memory */
608 /* mark as reference time frame */
610 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
614 frame->flags.ref_time=1;
616 frame->flags.ref_time=0;
618 cf_reftime_packets(&cfile);
619 #ifdef NEW_PACKET_LIST
620 new_packet_list_queue_draw();
625 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
629 timestamp_set_type(TS_RELATIVE);
630 recent.gui_time_format = TS_RELATIVE;
631 #ifdef NEW_PACKET_LIST
632 cf_timestamp_auto_precision(&cfile);
633 new_packet_list_queue_draw();
635 cf_change_time_formats(&cfile);
641 g_assert_not_reached();
644 if (cfile.current_frame) {
645 set_frame_reftime(!cfile.current_frame->flags.ref_time,
646 cfile.current_frame, cfile.current_row);
652 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
654 static GtkWidget *reftime_dialog = NULL;
658 if (cfile.current_frame) {
659 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
660 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
661 "%sSwitch to the appropriate Time Display Format?%s\n\n"
662 "Time References don't work well with the currently selected Time Display Format.\n\n"
663 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
664 simple_dialog_primary_start(), simple_dialog_primary_end());
665 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
667 set_frame_reftime(!cfile.current_frame->flags.ref_time,
668 cfile.current_frame, cfile.current_row);
672 case REFTIME_FIND_NEXT:
673 find_previous_next_frame_with_filter("frame.ref_time", FALSE);
675 case REFTIME_FIND_PREV:
676 find_previous_next_frame_with_filter("frame.ref_time", TRUE);
682 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
684 find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
688 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
690 find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
694 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
697 gchar *help_str = NULL;
698 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
700 gboolean has_blurb = FALSE;
701 guint length = 0, byte_len;
702 GtkWidget *byte_view;
703 const guint8 *byte_data;
708 /* if nothing is selected */
709 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
712 * Which byte view is displaying the current protocol tree
715 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
716 if (byte_view == NULL)
719 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
720 if (byte_data == NULL)
723 cf_unselect_field(&cfile);
724 packet_hex_print(byte_view, byte_data,
725 cfile.current_frame, NULL, byte_len);
728 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
731 set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
733 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
734 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
735 g_assert(byte_data != NULL);
737 cfile.finfo_selected = finfo;
738 set_menus_for_selected_tree_row(&cfile);
741 if (finfo->hfinfo->blurb != NULL &&
742 finfo->hfinfo->blurb[0] != '\0') {
744 length = (guint) strlen(finfo->hfinfo->blurb);
746 length = (guint) strlen(finfo->hfinfo->name);
748 finfo_length = finfo->length + finfo->appendix_length;
750 if (finfo_length == 0) {
752 } else if (finfo_length == 1) {
753 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
755 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
757 statusbar_pop_field_msg(); /* get rid of current help msg */
759 help_str = g_strdup_printf(" %s (%s)%s",
760 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
761 finfo->hfinfo->abbrev, len_str);
762 statusbar_push_field_msg(help_str);
766 * Don't show anything if the field name is zero-length;
767 * the pseudo-field for "proto_tree_add_text()" is such
768 * a field, and we don't want "Text (text)" showing up
769 * on the status line if you've selected such a field.
771 * XXX - there are zero-length fields for which we *do*
772 * want to show the field name.
774 * XXX - perhaps the name and abbrev field should be null
775 * pointers rather than null strings for that pseudo-field,
776 * but we'd have to add checks for null pointers in some
777 * places if we did that.
779 * Or perhaps protocol tree items added with
780 * "proto_tree_add_text()" should have -1 as the field index,
781 * with no pseudo-field being used, but that might also
782 * require special checks for -1 to be added.
784 statusbar_push_field_msg("");
787 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
791 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
793 collapse_all_tree(cfile.edt->tree, tree_view);
796 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
798 expand_all_tree(cfile.edt->tree, tree_view);
801 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
803 if (cfile.finfo_selected) {
804 column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
805 cfile.finfo_selected->hfinfo->abbrev);
806 /* Recreate the packet list according to new preferences */
807 #ifdef NEW_PACKET_LIST
808 new_packet_list_recreate ();
810 packet_list_recreate ();
812 cfile.cinfo.columns_changed = FALSE; /* Reset value */
816 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
819 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view), cfile.finfo_selected);
821 /* the mouse position is at an entry, expand that one */
822 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
823 gtk_tree_path_free(path);
827 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
828 if (cfile.edt->tree) {
829 guint32 tmp = g_resolv_flags;
830 g_resolv_flags = RESOLV_ALL;
831 proto_tree_draw(cfile.edt->tree, tree_view);
832 g_resolv_flags = tmp;
837 main_set_for_capture_file(gboolean have_capture_file_in)
839 have_capture_file = have_capture_file_in;
841 main_widgets_show_or_hide();
847 /* get the current geometry, before writing it to disk */
848 main_save_window_geometry(top_level);
850 /* write user's recent file to disk
851 * It is no problem to write this file, even if we do not quit */
852 write_profile_recent();
855 /* XXX - should we check whether the capture file is an
856 unsaved temporary file for a live capture and, if so,
857 pop up a "do you want to exit without saving the capture
858 file?" dialog, and then just return, leaving said dialog
859 box to forcibly quit if the user clicks "OK"?
861 If so, note that this should be done in a subroutine that
862 returns TRUE if we do so, and FALSE otherwise, and if it
863 returns TRUE we should return TRUE without nuking anything.
865 Note that, if we do that, we might also want to check if
866 an "Update list of packets in real time" capture is in
867 progress and, if so, ask whether they want to terminate
868 the capture and discard it, and return TRUE, before nuking
869 any child capture, if they say they don't want to do so. */
872 /* Nuke any child capture in progress. */
873 capture_kill_child(&global_capture_opts);
876 /* Are we in the middle of reading a capture? */
877 if (cfile.state == FILE_READ_IN_PROGRESS) {
878 /* Yes, so we can't just close the file and quit, as
879 that may yank the rug out from under the read in
880 progress; instead, just set the state to
881 "FILE_READ_ABORTED" and return - the code doing the read
882 will check for that and, if it sees that, will clean
884 cfile.state = FILE_READ_ABORTED;
886 /* Say that the window should *not* be deleted;
887 that'll be done by the code that cleans up. */
890 /* Close any capture file we have open; on some OSes, you
891 can't unlink a temporary capture file if you have it
893 "cf_close()" will unlink it after closing it if
894 it's a temporary file.
896 We do this here, rather than after the main loop returns,
897 as, after the main loop returns, the main window may have
898 been destroyed (if this is called due to a "destroy"
899 even on the main window rather than due to the user
900 selecting a menu item), and there may be a crash
901 or other problem when "cf_close()" tries to
902 clean up stuff in the main window.
904 XXX - is there a better place to put this?
905 Or should we have a routine that *just* closes the
906 capture file, and doesn't do anything with the UI,
907 which we'd call here, and another routine that
908 calls that routine and also cleans up the UI, which
909 we'd call elsewhere? */
912 /* Exit by leaving the main loop, so that any quit functions
913 we registered get called. */
916 /* Say that the window should be deleted. */
922 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
926 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
927 gtk_window_present(GTK_WINDOW(top_level));
928 /* user didn't saved his current file, ask him */
929 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
930 "%sSave capture file before program quit?%s\n\n"
931 "If you quit the program without saving, your capture data will be discarded.",
932 simple_dialog_primary_start(), simple_dialog_primary_end());
933 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
936 /* unchanged file, just exit */
937 /* "main_do_quit()" indicates whether the main window should be deleted. */
938 return main_do_quit();
944 main_pane_load_window_geometry(void)
946 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
947 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
948 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
949 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
955 main_load_window_geometry(GtkWidget *widget)
957 window_geometry_t geom;
959 geom.set_pos = prefs.gui_geometry_save_position;
960 geom.x = recent.gui_geometry_main_x;
961 geom.y = recent.gui_geometry_main_y;
962 geom.set_size = prefs.gui_geometry_save_size;
963 if (recent.gui_geometry_main_width > 0 &&
964 recent.gui_geometry_main_height > 0) {
965 geom.width = recent.gui_geometry_main_width;
966 geom.height = recent.gui_geometry_main_height;
967 geom.set_maximized = prefs.gui_geometry_save_maximized;
969 /* We assume this means the width and height weren't set in
970 the "recent" file (or that there is no "recent" file),
971 and weren't set to a default value, so we don't set the
972 size. (The "recent" file code rejects non-positive width
973 and height values.) */
974 geom.set_size = FALSE;
976 geom.maximized = recent.gui_geometry_main_maximized;
978 window_set_geometry(widget, &geom);
980 main_pane_load_window_geometry();
981 statusbar_load_window_geometry();
986 main_save_window_geometry(GtkWidget *widget)
988 window_geometry_t geom;
990 window_get_geometry(widget, &geom);
992 if (prefs.gui_geometry_save_position) {
993 recent.gui_geometry_main_x = geom.x;
994 recent.gui_geometry_main_y = geom.y;
997 if (prefs.gui_geometry_save_size) {
998 recent.gui_geometry_main_width = geom.width;
999 recent.gui_geometry_main_height = geom.height;
1002 if(prefs.gui_geometry_save_maximized) {
1003 recent.gui_geometry_main_maximized = geom.maximized;
1006 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1007 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1008 statusbar_save_window_geometry();
1011 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1015 /* save file first */
1016 file_save_as_cmd(after_save_exit, NULL);
1018 case(ESD_BTN_QUIT_DONT_SAVE):
1021 case(ESD_BTN_CANCEL):
1024 g_assert_not_reached();
1029 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1033 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1034 /* user didn't saved his current file, ask him */
1035 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1036 "%sSave capture file before program quit?%s\n\n"
1037 "If you quit the program without saving, your capture data will be discarded.",
1038 simple_dialog_primary_start(), simple_dialog_primary_end());
1039 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1041 /* unchanged file, just exit */
1047 print_usage(gboolean print_ver) {
1057 fprintf(output, "Wireshark " VERSION "%s\n"
1058 "Interactively dump and analyze network traffic.\n"
1059 "See http://www.wireshark.org for more information.\n"
1062 wireshark_svnversion, get_copyright_info());
1066 fprintf(output, "\n");
1067 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1068 fprintf(output, "\n");
1071 fprintf(output, "Capture interface:\n");
1072 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1073 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1074 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1075 fprintf(output, " -p don't capture in promiscuous mode\n");
1076 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1077 fprintf(output, " -Q quit Wireshark after capturing\n");
1078 fprintf(output, " -S update packet display when new packets are captured\n");
1079 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1081 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1083 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1084 fprintf(output, " -D print list of interfaces and exit\n");
1085 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1086 fprintf(output, "\n");
1087 fprintf(output, "Capture stop conditions:\n");
1088 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1089 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1090 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1091 fprintf(output, " files:NUM - stop after NUM files\n");
1092 /*fprintf(output, "\n");*/
1093 fprintf(output, "Capture output:\n");
1094 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1095 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1096 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1097 #endif /* HAVE_LIBPCAP */
1099 /*fprintf(output, "\n");*/
1100 fprintf(output, "Input file:\n");
1101 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1103 fprintf(output, "\n");
1104 fprintf(output, "Processing:\n");
1105 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1106 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1107 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1109 fprintf(output, "\n");
1110 fprintf(output, "User interface:\n");
1111 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1112 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1113 fprintf(output, " -m <font> set the font name used for most text\n");
1114 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1115 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1116 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1118 fprintf(output, "\n");
1119 fprintf(output, "Output:\n");
1120 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1122 fprintf(output, "\n");
1123 fprintf(output, "Miscellaneous:\n");
1124 fprintf(output, " -h display this help and exit\n");
1125 fprintf(output, " -v display version info and exit\n");
1126 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1127 fprintf(output, " persdata:path - personal data files\n");
1128 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1129 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1131 fprintf(output, " --display=DISPLAY X display to use\n");
1146 printf(PACKAGE " " VERSION "%s\n"
1153 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1154 runtime_info_str->str);
1162 * Report an error in command-line arguments.
1163 * Creates a console on Windows.
1164 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1165 * terminal isn't the standard error?
1168 cmdarg_err(const char *fmt, ...)
1176 fprintf(stderr, "wireshark: ");
1177 vfprintf(stderr, fmt, ap);
1178 fprintf(stderr, "\n");
1183 * Report additional information for an error in command-line arguments.
1184 * Creates a console on Windows.
1185 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1186 * terminal isn't the standard error?
1189 cmdarg_err_cont(const char *fmt, ...)
1197 vfprintf(stderr, fmt, ap);
1198 fprintf(stderr, "\n");
1202 #if defined(_WIN32) || ! defined USE_THREADS
1204 Once every 3 seconds we get a callback here which we use to update
1205 the tap extensions. Since Gtk1 is single threaded we dont have to
1206 worry about any locking or critical regions.
1209 update_cb(gpointer data _U_)
1211 draw_tap_listeners(FALSE);
1215 /* Restart the tap update display timer with new configured interval */
1216 void reset_tap_update_timer(void)
1218 g_source_remove(tap_update_timer_id);
1219 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, update_cb, NULL);
1224 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1225 use threads all update_thread_mutex can be dropped and protect/unprotect
1226 would just be empty functions.
1228 This allows gtk2-rpcstat.c and friends to be copied unmodified to
1229 gtk1-wireshark and it will just work.
1231 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1233 update_thread(gpointer data _U_)
1237 g_get_current_time(&tv1);
1238 g_static_mutex_lock(&update_thread_mutex);
1239 gdk_threads_enter();
1240 draw_tap_listeners(FALSE);
1241 gdk_threads_leave();
1242 g_static_mutex_unlock(&update_thread_mutex);
1244 g_get_current_time(&tv2);
1246 /* Assuming it took less than configured time to update tap listeners... */
1247 if( (tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) >
1248 (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1249 /* Wait for remainder of configured time */
1250 g_usleep((tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) -
1251 (tv2.tv_sec * 1000000 + tv2.tv_usec));
1258 protect_thread_critical_region(void)
1260 #if !defined(_WIN32) && defined USE_THREADS
1261 g_static_mutex_lock(&update_thread_mutex);
1265 unprotect_thread_critical_region(void)
1267 #if !defined(_WIN32) && defined USE_THREADS
1268 g_static_mutex_unlock(&update_thread_mutex);
1272 /* Set the file name in the name for the main window and in the name for the main window's icon. */
1274 set_display_filename(capture_file *cf)
1278 if (!cf->is_tempfile && cf->filename) {
1279 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1280 add_menu_recent_capture_file(cf->filename);
1284 win_name = g_strdup_printf("%s - Wireshark", cf_get_display_name(cf));
1285 set_main_window_name(win_name);
1289 GtkWidget *close_dlg = NULL;
1292 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1294 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1299 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1301 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1306 main_cf_cb_file_closing(capture_file *cf)
1309 /* if we have more than 10000 packets, show a splash screen while closing */
1310 /* XXX - don't know a better way to decide whether to show or not,
1311 * as most of the time is spend in a single eth_clist_clear function,
1312 * so we can't use a progress bar here! */
1313 if(cf->count > 10000) {
1314 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1315 "%sClosing file!%s\n\nPlease wait ...",
1316 simple_dialog_primary_start(),
1317 simple_dialog_primary_end());
1318 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1321 /* Destroy all windows, which refer to the
1322 capture file we're closing. */
1323 destroy_packet_wins();
1324 file_save_as_destroy();
1326 /* Restore the standard title bar message. */
1327 set_main_window_name("The Wireshark Network Analyzer");
1329 /* Disable all menu items that make sense only if you have a capture. */
1330 set_menus_for_capture_file(NULL);
1331 set_menus_for_captured_packets(FALSE);
1332 set_menus_for_selected_packet(cf);
1333 set_menus_for_capture_in_progress(FALSE);
1334 set_capture_if_dialog_for_capture_in_progress(FALSE);
1335 set_menus_for_selected_tree_row(cf);
1337 /* Set up main window for no capture file. */
1338 main_set_for_capture_file(FALSE);
1340 main_window_update();
1344 main_cf_cb_file_closed(capture_file *cf _U_)
1346 if(close_dlg != NULL) {
1347 splash_destroy(close_dlg);
1354 main_cf_cb_file_read_start(capture_file *cf _U_)
1356 tap_dfilter_dlg_update();
1358 /* Set up main window for a capture file. */
1359 main_set_for_capture_file(TRUE);
1363 main_cf_cb_file_read_finished(capture_file *cf)
1365 set_display_filename(cf);
1367 /* Enable menu items that make sense if you have a capture file you've
1368 finished reading. */
1369 set_menus_for_capture_file(cf);
1371 /* Enable menu items that make sense if you have some captured packets. */
1372 set_menus_for_captured_packets(TRUE);
1376 static GList *icon_list_create(
1377 const char **icon16_xpm,
1378 const char **icon32_xpm,
1379 const char **icon48_xpm,
1380 const char **icon64_xpm)
1382 GList *icon_list = NULL;
1383 GdkPixbuf * pixbuf16;
1384 GdkPixbuf * pixbuf32;
1385 GdkPixbuf * pixbuf48;
1386 GdkPixbuf * pixbuf64;
1389 if(icon16_xpm != NULL) {
1390 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1392 icon_list = g_list_append(icon_list, pixbuf16);
1395 if(icon32_xpm != NULL) {
1396 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1398 icon_list = g_list_append(icon_list, pixbuf32);
1401 if(icon48_xpm != NULL) {
1402 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1404 icon_list = g_list_append(icon_list, pixbuf48);
1407 if(icon64_xpm != NULL) {
1408 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1410 icon_list = g_list_append(icon_list, pixbuf64);
1417 main_capture_cb_capture_prepared(capture_options *capture_opts)
1420 static GList *icon_list = NULL;
1423 if(capture_opts->iface) {
1424 title = g_strdup_printf("%s: Capturing - Wireshark",
1425 get_iface_description(capture_opts));
1427 title = g_strdup_printf("Capturing - Wireshark");
1429 set_main_window_name(title);
1432 if(icon_list == NULL) {
1433 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1435 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1437 /* Disable menu items that make no sense if you're currently running
1439 set_menus_for_capture_in_progress(TRUE);
1440 set_capture_if_dialog_for_capture_in_progress(TRUE);
1442 /* Don't set up main window for a capture file. */
1443 main_set_for_capture_file(FALSE);
1447 main_capture_cb_capture_update_started(capture_options *capture_opts)
1451 /* We've done this in "prepared" above, but it will be cleared while
1452 switching to the next multiple file. */
1453 if(capture_opts->iface) {
1454 title = g_strdup_printf("%s: Capturing - Wireshark",
1455 get_iface_description(capture_opts));
1457 title = g_strdup_printf("Capturing - Wireshark");
1459 set_main_window_name(title);
1462 set_menus_for_capture_in_progress(TRUE);
1463 set_capture_if_dialog_for_capture_in_progress(TRUE);
1465 /* Enable menu items that make sense if you have some captured
1466 packets (yes, I know, we don't have any *yet*). */
1467 set_menus_for_captured_packets(TRUE);
1469 /* Set up main window for a capture file. */
1470 main_set_for_capture_file(TRUE);
1474 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1476 capture_file *cf = capture_opts->cf;
1477 static GList *icon_list = NULL;
1479 set_display_filename(cf);
1481 /* Enable menu items that make sense if you're not currently running
1483 set_menus_for_capture_in_progress(FALSE);
1484 set_capture_if_dialog_for_capture_in_progress(FALSE);
1486 /* Enable menu items that make sense if you have a capture file
1487 you've finished reading. */
1488 set_menus_for_capture_file(cf);
1490 /* Set up main window for a capture file. */
1491 main_set_for_capture_file(TRUE);
1493 if(icon_list == NULL) {
1494 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1496 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1498 if(global_capture_opts.quit_after_cap) {
1499 /* command line asked us to quit after the capture */
1500 /* don't pop up a dialog to ask for unsaved files etc. */
1506 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1508 /* Don't set up main window for a capture file. */
1509 main_set_for_capture_file(FALSE);
1513 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1516 capture_file *cf = capture_opts->cf;
1518 static GList *icon_list = NULL;
1520 /*set_display_filename(cf);*/
1522 /* Enable menu items that make sense if you're not currently running
1524 set_menus_for_capture_in_progress(FALSE);
1525 set_capture_if_dialog_for_capture_in_progress(FALSE);
1527 /* Restore the standard title bar message */
1528 /* (just in case we have trouble opening the capture file). */
1529 set_main_window_name("The Wireshark Network Analyzer");
1531 if(icon_list == NULL) {
1532 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1534 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1536 /* We don't have loaded the capture file, this will be done later.
1537 * For now we still have simply a blank screen. */
1539 if(global_capture_opts.quit_after_cap) {
1540 /* command line asked us to quit after the capture */
1541 /* don't pop up a dialog to ask for unsaved files etc. */
1546 #endif /* HAVE_LIBPCAP */
1549 main_cf_cb_packet_selected(gpointer data)
1551 capture_file *cf = data;
1553 /* Display the GUI protocol tree and packet bytes.
1554 XXX - why do we dump core if we call "proto_tree_draw()"
1555 before calling "add_byte_views()"? */
1556 add_main_byte_views(cf->edt);
1557 main_proto_tree_draw(cf->edt->tree);
1559 /* The user is searching for a string in the data or a hex value,
1560 * highlight the field that is found in the tree and hex displays. */
1561 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1562 highlight_field(cf->edt->tvb, cfile.search_pos,
1563 (GtkTreeView *)tree_view, cf->edt->tree);
1564 cfile.search_pos = 0; /* Reset the position */
1567 /* A packet is selected. */
1568 set_menus_for_selected_packet(cf);
1572 main_cf_cb_packet_unselected(capture_file *cf)
1574 /* Clear out the display of that packet. */
1575 clear_tree_and_hex_views();
1577 /* No packet is selected. */
1578 set_menus_for_selected_packet(cf);
1582 main_cf_cb_field_unselected(capture_file *cf)
1584 set_menus_for_selected_tree_row(cf);
1588 main_cf_cb_file_safe_reload_finished(gpointer data _U_)
1590 set_menus_for_capture_file(&cfile);
1594 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1597 case(cf_cb_file_closing):
1598 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1599 main_cf_cb_file_closing(data);
1601 case(cf_cb_file_closed):
1602 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1603 main_cf_cb_file_closed(data);
1605 case(cf_cb_file_read_start):
1606 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read start");
1607 main_cf_cb_file_read_start(data);
1609 case(cf_cb_file_read_finished):
1610 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1611 main_cf_cb_file_read_finished(data);
1613 case(cf_cb_packet_selected):
1614 main_cf_cb_packet_selected(data);
1616 case(cf_cb_packet_unselected):
1617 main_cf_cb_packet_unselected(data);
1619 case(cf_cb_field_unselected):
1620 main_cf_cb_field_unselected(data);
1622 case(cf_cb_file_safe_started):
1623 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe started");
1625 case(cf_cb_file_safe_finished):
1626 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe finished");
1628 case(cf_cb_file_safe_reload_finished):
1629 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: reload finished");
1630 main_cf_cb_file_safe_reload_finished(data);
1632 case(cf_cb_file_safe_failed):
1633 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe failed");
1636 g_warning("main_cf_callback: event %u unknown", event);
1637 g_assert_not_reached();
1643 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1646 case(capture_cb_capture_prepared):
1647 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1648 main_capture_cb_capture_prepared(capture_opts);
1650 case(capture_cb_capture_update_started):
1651 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1652 main_capture_cb_capture_update_started(capture_opts);
1654 case(capture_cb_capture_update_continue):
1655 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1657 case(capture_cb_capture_update_finished):
1658 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1659 main_capture_cb_capture_update_finished(capture_opts);
1661 case(capture_cb_capture_fixed_started):
1662 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1663 main_capture_cb_capture_fixed_started(capture_opts);
1665 case(capture_cb_capture_fixed_continue):
1666 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1668 case(capture_cb_capture_fixed_finished):
1669 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1670 main_capture_cb_capture_fixed_finished(capture_opts);
1672 case(capture_cb_capture_stopping):
1673 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1674 /* Beware: this state won't be called, if the capture child
1675 * closes the capturing on it's own! */
1678 g_warning("main_capture_callback: event %u unknown", event);
1679 g_assert_not_reached();
1685 get_gui_compiled_info(GString *str)
1687 get_epan_compiled_version_info(str);
1689 g_string_append(str, ", ");
1690 #ifdef HAVE_LIBPORTAUDIO
1691 #ifdef PORTAUDIO_API_1
1692 g_string_append(str, "with PortAudio <= V18");
1693 #else /* PORTAUDIO_API_1 */
1694 g_string_append(str, "with ");
1695 g_string_append(str, Pa_GetVersionText());
1696 #endif /* PORTAUDIO_API_1 */
1697 #else /* HAVE_LIBPORTAUDIO */
1698 g_string_append(str, "without PortAudio");
1699 #endif /* HAVE_LIBPORTAUDIO */
1701 g_string_append(str, ", ");
1703 get_compiled_airpcap_version(str);
1705 g_string_append(str, "without AirPcap");
1707 #ifdef NEW_PACKET_LIST
1708 g_string_append(str, ", with new_packet_list");
1713 get_gui_runtime_info(GString *str)
1716 g_string_append(str, ", ");
1717 get_runtime_airpcap_version(str);
1721 g_string_append(str, ", ");
1722 u3_runtime_info(str);
1728 read_configuration_files(char **gdp_path, char **dp_path)
1730 int gpf_open_errno, gpf_read_errno;
1731 int cf_open_errno, df_open_errno;
1732 int gdp_open_errno, gdp_read_errno;
1733 int dp_open_errno, dp_read_errno;
1734 char *gpf_path, *pf_path;
1735 char *cf_path, *df_path;
1736 int pf_open_errno, pf_read_errno;
1739 /* Read the preference files. */
1740 prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1741 &pf_open_errno, &pf_read_errno, &pf_path);
1743 if (gpf_path != NULL) {
1744 if (gpf_open_errno != 0) {
1745 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1746 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1747 strerror(gpf_open_errno));
1749 if (gpf_read_errno != 0) {
1750 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1751 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1752 strerror(gpf_read_errno));
1755 if (pf_path != NULL) {
1756 if (pf_open_errno != 0) {
1757 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1758 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1759 strerror(pf_open_errno));
1761 if (pf_read_errno != 0) {
1762 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1763 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1764 strerror(pf_read_errno));
1771 /* if the user wants a console to be always there, well, we should open one for him */
1772 if (prefs->gui_console_open == console_open_always) {
1777 /* Read the capture filter file. */
1778 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1779 if (cf_path != NULL) {
1780 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1781 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1782 strerror(cf_open_errno));
1786 /* Read the display filter file. */
1787 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1788 if (df_path != NULL) {
1789 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1790 "Could not open your display filter file\n\"%s\": %s.", df_path,
1791 strerror(df_open_errno));
1795 /* Read the disabled protocols file. */
1796 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1797 dp_path, &dp_open_errno, &dp_read_errno);
1798 if (*gdp_path != NULL) {
1799 if (gdp_open_errno != 0) {
1800 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1801 "Could not open global disabled protocols file\n\"%s\": %s.",
1802 *gdp_path, strerror(gdp_open_errno));
1804 if (gdp_read_errno != 0) {
1805 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1806 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1807 *gdp_path, strerror(gdp_read_errno));
1812 if (*dp_path != NULL) {
1813 if (dp_open_errno != 0) {
1814 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1815 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1816 strerror(dp_open_errno));
1818 if (dp_read_errno != 0) {
1819 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1820 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1821 strerror(dp_read_errno));
1830 /* And now our feature presentation... [ fade to music ] */
1832 main(int argc, char *argv[])
1834 char *init_progfile_dir_error;
1837 gboolean arg_error = FALSE;
1839 extern int splash_register_freq; /* Found in about_dlg.c */
1840 const gchar *filter;
1848 char *gdp_path, *dp_path;
1851 gboolean start_capture = FALSE;
1852 gboolean list_link_layer_types = FALSE;
1854 gboolean capture_option_specified = FALSE;
1856 gint pl_size = 280, tv_size = 95, bv_size = 75;
1857 gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
1858 dfilter_t *rfcode = NULL;
1859 gboolean rfilter_parse_failed = FALSE;
1862 GtkWidget *splash_win = NULL;
1863 gpointer priv_warning_dialog;
1864 GLogLevelFlags log_flags;
1865 guint go_to_packet = 0;
1868 gchar *cur_user, *cur_group;
1876 #define OPTSTRING_INIT "a:b:c:C:Df:g:Hhi:kK:lLm:nN:o:P:pQr:R:Ss:t:vw:X:y:z:"
1878 #if defined HAVE_LIBPCAP && defined _WIN32
1879 #define OPTSTRING_WIN32 "B:"
1881 #define OPTSTRING_WIN32 ""
1884 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
1885 OPTSTRING_INIT OPTSTRING_WIN32;
1888 * Get credential information for later use, and drop privileges
1889 * before doing anything else.
1890 * Let the user know if anything happened.
1892 get_credential_info();
1893 relinquish_special_privs_perm();
1896 * Attempt to get the pathname of the executable file.
1898 init_progfile_dir_error = init_progfile_dir(argv[0], main);
1900 /* initialize the funnel mini-api */
1901 initialize_funnel_ops();
1903 #ifdef HAVE_AIRPDCAP
1904 AirPDcapInitContext(&airpdcap_ctx);
1908 /* Load wpcap if possible. Do this before collecting the run-time version information */
1911 /* ... and also load the packet.dll from wpcap */
1912 wpcap_packet_load();
1915 /* Load the airpcap.dll. This must also be done before collecting
1916 * run-time version information. */
1917 airpcap_dll_ret_val = load_airpcap();
1919 switch (airpcap_dll_ret_val) {
1920 case AIRPCAP_DLL_OK:
1921 /* load the airpcap interfaces */
1922 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
1924 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
1925 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
1926 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
1929 airpcap_if_active = NULL;
1933 /* select the first ad default (THIS SHOULD BE CHANGED) */
1934 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
1939 * XXX - Maybe we need to warn the user if one of the following happens???
1941 case AIRPCAP_DLL_OLD:
1942 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
1945 case AIRPCAP_DLL_ERROR:
1946 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
1949 case AIRPCAP_DLL_NOT_FOUND:
1950 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
1954 #endif /* HAVE_AIRPCAP */
1956 /* Start windows sockets */
1957 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
1960 /* Assemble the compile-time version information string */
1961 comp_info_str = g_string_new("Compiled ");
1963 g_string_append(comp_info_str, "with ");
1964 g_string_append_printf(comp_info_str,
1965 #ifdef GTK_MAJOR_VERSION
1966 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1969 "GTK+ (version unknown)");
1971 g_string_append(comp_info_str, ", ");
1973 get_compiled_version_info(comp_info_str, get_gui_compiled_info);
1975 /* Assemble the run-time version information string */
1976 runtime_info_str = g_string_new("Running ");
1977 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
1979 /* Read the profile independent recent file. We have to do this here so we can */
1980 /* set the profile before it can be set from the command line parameterts */
1981 recent_read_static(&rf_path, &rf_open_errno);
1982 if (rf_path != NULL && rf_open_errno != 0) {
1983 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1984 "Could not open common recent file\n\"%s\": %s.",
1985 rf_path, strerror(rf_open_errno));
1988 /* "pre-scan" the command line parameters, if we have "console only"
1989 parameters. We do this so we don't start GTK+ if we're only showing
1990 command-line help or version information.
1992 XXX - this pre-scan is done before we start GTK+, so we haven't
1993 run gtk_init() on the arguments. That means that GTK+ arguments
1994 have not been removed from the argument list; those arguments
1995 begin with "--", and will be treated as an error by getopt().
1997 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2000 optind_initial = optind;
2001 while ((opt = getopt(argc, argv, optstring)) != -1) {
2003 case 'C': /* Configuration Profile */
2004 if (profile_exists (optarg)) {
2005 set_profile_name (optarg);
2007 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2011 case 'h': /* Print help and exit */
2017 if (strcmp(optarg, "-") == 0)
2018 stdin_capture = TRUE;
2021 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2022 status = filesystem_opt(opt, optarg);
2024 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2028 case 'v': /* Show version and exit */
2034 * Extension command line options have to be processed before
2035 * we call epan_init() as they are supposed to be used by dissectors
2036 * or taps very early in the registration process.
2040 case '?': /* Ignore errors - the "real" scan will catch them. */
2045 /* Init the "Open file" dialog directory */
2046 /* (do this after the path settings are processed) */
2047 set_last_open_dir(get_persdatafile_dir());
2049 /* Set getopt index back to initial value, so it will start with the
2050 first command line parameter again. Also reset opterr to 1, so that
2051 error messages are printed by getopt().
2053 XXX - this seems to work on most platforms, but time will tell.
2054 The Single UNIX Specification says "The getopt() function need
2055 not be reentrant", so this isn't guaranteed to work. The Mac
2056 OS X 10.4[.x] getopt() man page says
2058 In order to use getopt() to evaluate multiple sets of arguments, or to
2059 evaluate a single set of arguments multiple times, the variable optreset
2060 must be set to 1 before the second and each additional set of calls to
2061 getopt(), and the variable optind must be reinitialized.
2065 The optreset variable was added to make it possible to call the getopt()
2066 function multiple times. This is an extension to the IEEE Std 1003.2
2067 (``POSIX.2'') specification.
2069 which I think comes from one of the other BSDs.
2071 XXX - if we want to control all the command-line option errors, so
2072 that we can display them where we choose (e.g., in a window), we'd
2073 want to leave opterr as 0, and produce our own messages using optopt.
2074 We'd have to check the value of optopt to see if it's a valid option
2075 letter, in which case *presumably* the error is "this option requires
2076 an argument but none was specified", or not a valid option letter,
2077 in which case *presumably* the error is "this option isn't valid".
2078 Some versions of getopt() let you supply a option string beginning
2079 with ':', which means that getopt() will return ':' rather than '?'
2080 for "this option requires an argument but none was specified", but
2082 optind = optind_initial;
2085 /* Set the current locale according to the program environment.
2086 * We haven't localized anything, but some GTK widgets are localized
2087 * (the file selection dialogue, for example).
2088 * This also sets the C-language locale to the native environment. */
2091 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2092 gtk_init (&argc, &argv);
2094 cf_callback_add(main_cf_callback, NULL);
2096 capture_callback_add(main_capture_callback, NULL);
2098 cf_callback_add(statusbar_cf_callback, NULL);
2100 capture_callback_add(statusbar_capture_callback, NULL);
2103 /* Arrange that if we have no console window, and a GLib message logging
2104 routine is called to log a message, we pop up a console window.
2106 We do that by inserting our own handler for all messages logged
2107 to the default domain; that handler pops up a console if necessary,
2108 and then calls the default handler. */
2110 /* We might want to have component specific log levels later ... */
2114 G_LOG_LEVEL_CRITICAL|
2115 G_LOG_LEVEL_WARNING|
2116 G_LOG_LEVEL_MESSAGE|
2119 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2121 g_log_set_handler(NULL,
2123 console_log_handler, NULL /* user_data */);
2124 g_log_set_handler(LOG_DOMAIN_MAIN,
2126 console_log_handler, NULL /* user_data */);
2129 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2131 console_log_handler, NULL /* user_data */);
2132 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2134 console_log_handler, NULL /* user_data */);
2136 /* Set the initial values in the capture options. This might be overwritten
2137 by preference settings and then again by the command line parameters. */
2138 capture_opts_init(&global_capture_opts, &cfile);
2140 global_capture_opts.snaplen = MIN_PACKET_SIZE;
2141 global_capture_opts.has_ring_num_files = TRUE;
2144 /* Initialize whatever we need to allocate colors for GTK+ */
2147 /* Non-blank filter means we're remote. Throttle splash screen updates. */
2148 filter = get_conn_cfilter();
2149 if ( *filter != '\0' )
2150 splash_register_freq = 1000; /* Milliseconds */
2152 /* We won't come till here, if we had a "console only" command line parameter. */
2153 splash_win = splash_new("Loading Wireshark ...");
2154 if (init_progfile_dir_error != NULL) {
2155 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2156 "Can't get pathname of Wireshark: %s.\n"
2157 "It won't be possible to capture traffic.\n"
2158 "Report this to the Wireshark developers.",
2159 init_progfile_dir_error);
2160 g_free(init_progfile_dir_error);
2163 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2165 /* Register all dissectors; we must do this before checking for the
2166 "-G" flag, as the "-G" flag dumps information registered by the
2167 dissectors, and we must do it before we read the preferences, in
2168 case any dissectors register preferences. */
2169 epan_init(register_all_protocols,register_all_protocol_handoffs,
2170 splash_update, (gpointer) splash_win,
2171 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2172 write_failure_alert_box);
2174 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2176 /* Register all tap listeners; we do this before we parse the arguments,
2177 as the "-z" argument can specify a registered tap. */
2179 /* we register the plugin taps before the other taps because
2180 stats_tree taps plugins will be registered as tap listeners
2181 by stats_tree_stat.c and need to registered before that */
2184 register_all_plugin_tap_listeners();
2187 register_all_tap_listeners();
2189 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2191 /* Now register the preferences for any non-dissector modules.
2192 We must do that before we read the preferences as well. */
2193 prefs_register_modules();
2195 prefs = read_configuration_files (&gdp_path, &dp_path);
2197 /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2198 #if !defined(_WIN32) && defined(G_THREADS_ENABLED) && defined USE_THREADS
2201 g_thread_init(NULL);
2203 ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2204 g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2206 #else /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2207 /* this is to keep tap extensions updating once every 3 seconds */
2208 tap_update_timer_id = g_timeout_add(prefs->tap_update_interval, update_cb, NULL);
2209 #endif /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2211 #if HAVE_GNU_ADNS || HAVE_C_ARES
2212 g_timeout_add(750, host_name_lookup_process, NULL);
2215 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2218 /* Read the profile dependent (static part) of the recent file. */
2219 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2220 /* recent lists which is done in the dynamic part. */
2221 /* We have to do this already here, so command line parameters can overwrite these values. */
2222 recent_read_profile_static(&rf_path, &rf_open_errno);
2223 if (rf_path != NULL && rf_open_errno != 0) {
2224 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2225 "Could not open recent file\n\"%s\": %s.",
2226 rf_path, strerror(rf_open_errno));
2229 cap_file_init(&cfile);
2231 /* Fill in capture options with values from the preferences */
2232 prefs_to_capture_opts();
2234 /* Now get our args */
2235 while ((opt = getopt(argc, argv, optstring)) != -1) {
2237 /*** capture option specific ***/
2238 case 'a': /* autostop criteria */
2239 case 'b': /* Ringbuffer option */
2240 case 'c': /* Capture xxx packets */
2241 case 'f': /* capture filter */
2242 case 'k': /* Start capture immediately */
2243 case 'H': /* Hide capture info dialog box */
2244 case 'i': /* Use interface xxx */
2245 case 'p': /* Don't capture in promiscuous mode */
2246 case 'Q': /* Quit after capture (just capture to file) */
2247 case 's': /* Set the snapshot (capture) length */
2248 case 'S': /* "Sync" mode: used for following file ala tail -f */
2249 case 'w': /* Write to capture file xxx */
2250 case 'y': /* Set the pcap data link type */
2252 case 'B': /* Buffer size */
2255 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2261 capture_option_specified = TRUE;
2266 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2267 case 'K': /* Kerberos keytab file */
2268 read_keytab_file(optarg);
2272 /*** all non capture option specific ***/
2274 /* Configuration profile settings were already processed just ignore them this time*/
2276 case 'D': /* Print a list of capture devices and exit */
2278 capture_opts_list_interfaces(FALSE);
2281 capture_option_specified = TRUE;
2285 case 'g': /* Go to packet */
2286 go_to_packet = get_positive_int(optarg, "go to packet");
2288 case 'l': /* Automatic scrolling in live capture mode */
2290 auto_scroll_live = TRUE;
2292 capture_option_specified = TRUE;
2296 case 'L': /* Print list of link-layer types and exit */
2298 list_link_layer_types = TRUE;
2300 capture_option_specified = TRUE;
2304 case 'm': /* Fixed-width font for the display */
2305 g_free(prefs->gui_font_name);
2306 prefs->gui_font_name = g_strdup(optarg);
2308 case 'n': /* No name resolution */
2309 g_resolv_flags = RESOLV_NONE;
2311 case 'N': /* Select what types of addresses/port #s to resolve */
2312 if (g_resolv_flags == RESOLV_ALL)
2313 g_resolv_flags = RESOLV_NONE;
2314 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2315 if (badopt != '\0') {
2316 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2321 case 'o': /* Override preference from command line */
2322 switch (prefs_set_pref(optarg)) {
2325 case PREFS_SET_SYNTAX_ERR:
2326 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2329 case PREFS_SET_NO_SUCH_PREF:
2330 /* not a preference, might be a recent setting */
2331 switch (recent_set_arg(optarg)) {
2334 case PREFS_SET_SYNTAX_ERR:
2335 /* shouldn't happen, checked already above */
2336 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2339 case PREFS_SET_NO_SUCH_PREF:
2340 case PREFS_SET_OBSOLETE:
2341 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2346 g_assert_not_reached();
2349 case PREFS_SET_OBSOLETE:
2350 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2355 g_assert_not_reached();
2359 /* Path settings were already processed just ignore them this time*/
2361 case 'r': /* Read capture file xxx */
2362 /* We may set "last_open_dir" to "cf_name", and if we change
2363 "last_open_dir" later, we free the old value, so we have to
2364 set "cf_name" to something that's been allocated. */
2365 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2366 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2367 cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2369 cf_name = g_strdup(optarg);
2372 case 'R': /* Read file filter */
2375 case 't': /* Time stamp type */
2376 if (strcmp(optarg, "r") == 0)
2377 timestamp_set_type(TS_RELATIVE);
2378 else if (strcmp(optarg, "a") == 0)
2379 timestamp_set_type(TS_ABSOLUTE);
2380 else if (strcmp(optarg, "ad") == 0)
2381 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2382 else if (strcmp(optarg, "d") == 0)
2383 timestamp_set_type(TS_DELTA);
2384 else if (strcmp(optarg, "dd") == 0)
2385 timestamp_set_type(TS_DELTA_DIS);
2386 else if (strcmp(optarg, "e") == 0)
2387 timestamp_set_type(TS_EPOCH);
2389 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2390 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2391 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2396 /* ext ops were already processed just ignore them this time*/
2399 /* We won't call the init function for the stat this soon
2400 as it would disallow MATE's fields (which are registered
2401 by the preferences set callback) from being used as
2402 part of a tap filter. Instead, we just add the argument
2403 to a list of stat arguments. */
2404 if (!process_stat_cmd_arg(optarg)) {
2405 cmdarg_err("Invalid -z argument.");
2406 cmdarg_err_cont(" -z argument must be one of :");
2407 list_stat_cmd_args();
2412 case '?': /* Bad flag - print usage message */
2420 if (cf_name != NULL) {
2422 * Input file name specified with "-r" *and* specified as a regular
2423 * command-line argument.
2425 cmdarg_err("File name specified both with -r and regular argument");
2429 * Input file name not specified with "-r", and a command-line argument
2430 * was specified; treat it as the input file name.
2432 * Yes, this is different from tshark, where non-flag command-line
2433 * arguments are a filter, but this works better on GUI desktops
2434 * where a command can be specified to be run to open a particular
2435 * file - yes, you could have "-r" as the last part of the command,
2436 * but that's a bit ugly.
2438 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2439 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2440 cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2442 cf_name = g_strdup(argv[0]);
2453 * Extra command line arguments were specified; complain.
2455 cmdarg_err("Invalid argument: %s", argv[0]);
2460 #ifndef HAVE_LIBPCAP
2461 if (capture_option_specified) {
2462 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2470 if (start_capture && list_link_layer_types) {
2471 /* Specifying *both* is bogus. */
2472 cmdarg_err("You can't specify both -L and a live capture.");
2476 if (list_link_layer_types) {
2477 /* We're supposed to list the link-layer types for an interface;
2478 did the user also specify a capture file to be read? */
2480 /* Yes - that's bogus. */
2481 cmdarg_err("You can't specify -L and a capture file to be read.");
2484 /* No - did they specify a ring buffer option? */
2485 if (global_capture_opts.multi_files_on) {
2486 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2490 /* We're supposed to do a live capture; did the user also specify
2491 a capture file to be read? */
2492 if (start_capture && cf_name) {
2493 /* Yes - that's bogus. */
2494 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2498 /* No - was the ring buffer option specified and, if so, does it make
2500 if (global_capture_opts.multi_files_on) {
2501 /* Ring buffer works only under certain conditions:
2502 a) ring buffer does not work with temporary files;
2503 b) real_time_mode and multi_files_on are mutually exclusive -
2504 real_time_mode takes precedence;
2505 c) it makes no sense to enable the ring buffer if the maximum
2506 file size is set to "infinite". */
2507 if (global_capture_opts.save_file == NULL) {
2508 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2509 global_capture_opts.multi_files_on = FALSE;
2511 /* if (global_capture_opts.real_time_mode) {
2512 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2513 global_capture_opts.multi_files_on = FALSE;
2515 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2516 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2517 /* XXX - this must be redesigned as the conditions changed */
2518 /* global_capture_opts.multi_files_on = FALSE;*/
2523 if (start_capture || list_link_layer_types) {
2524 /* Did the user specify an interface to use? */
2525 if (!capture_opts_trim_iface(&global_capture_opts,
2526 (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
2531 if (list_link_layer_types) {
2532 status = capture_opts_list_link_layer_types(&global_capture_opts, FALSE);
2536 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2537 capture_opts_trim_ring_num_files(&global_capture_opts);
2538 #endif /* HAVE_LIBPCAP */
2540 /* Notify all registered modules that have had any of their preferences
2541 changed either from one of the preferences file or from the command
2542 line that their preferences have changed. */
2545 /* disabled protocols as per configuration file */
2546 if (gdp_path == NULL && dp_path == NULL) {
2547 set_disabled_protos_list();
2550 build_column_format_array(&cfile.cinfo, prefs->num_cols, TRUE);
2552 /* read in rc file from global and personal configuration paths. */
2553 rc_file = get_datafile_path(RC_FILE);
2554 gtk_rc_parse(rc_file);
2556 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2557 gtk_rc_parse(rc_file);
2564 /* close the splash screen, as we are going to open the main window now */
2565 splash_destroy(splash_win);
2567 /************************************************************************/
2568 /* Everything is prepared now, preferences and command line was read in */
2570 /* Pop up the main window. */
2571 create_main_window(pl_size, tv_size, bv_size, prefs);
2573 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2574 recent_read_dynamic(&rf_path, &rf_open_errno);
2575 if (rf_path != NULL && rf_open_errno != 0) {
2576 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2577 "Could not open recent file\n\"%s\": %s.",
2578 rf_path, strerror(rf_open_errno));
2581 color_filters_enable(recent.packet_list_colorize);
2583 /* rearrange all the widgets as we now have all recent settings ready for this */
2584 main_widgets_rearrange();
2586 /* Fill in column titles. This must be done after the top level window
2589 XXX - is that still true, with fixed-width columns? */
2590 #ifndef NEW_PACKET_LIST
2591 packet_list_set_column_titles();
2594 menu_recent_read_finished();
2596 menu_auto_scroll_live_changed(auto_scroll_live);
2599 switch (user_font_apply()) {
2602 case FA_FONT_NOT_RESIZEABLE:
2603 /* "user_font_apply()" popped up an alert box. */
2604 /* turn off zooming - font can't be resized */
2605 case FA_FONT_NOT_AVAILABLE:
2606 /* XXX - did we successfully load the un-zoomed version earlier?
2607 If so, this *probably* means the font is available, but not at
2608 this particular zoom level, but perhaps some other failure
2609 occurred; I'm not sure you can determine which is the case,
2611 /* turn off zooming - zoom level is unavailable */
2613 /* in any other case than FA_SUCCESS, turn off zooming */
2614 recent.gui_zoom_level = 0;
2615 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2618 dnd_init(top_level);
2620 color_filters_init();
2623 /* the window can be sized only, if it's not already shown, so do it now! */
2624 main_load_window_geometry(top_level);
2626 /* Tell the user not to run as root. */
2627 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
2628 cur_user = get_cur_username();
2629 cur_group = get_cur_groupname();
2630 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2631 "Running as user \"%s\" and group \"%s\".\n"
2632 "This could be dangerous.", cur_user, cur_group);
2635 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2636 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
2640 /* Warn the user if npf.sys isn't loaded. */
2641 if (!npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
2642 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2643 "The NPF driver isn't running. You may have trouble\n"
2644 "capturing or listing interfaces.");
2645 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2646 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
2650 /* If we were given the name of a capture file, read it in now;
2651 we defer it until now, so that, if we can't open it, and pop
2652 up an alert box, the alert box is more likely to come up on
2653 top of the main window - but before the preference-file-error
2654 alert box, so, if we get one of those, it's more likely to come
2657 show_main_window(TRUE);
2658 if (rfilter != NULL) {
2659 if (!dfilter_compile(rfilter, &rfcode)) {
2660 bad_dfilter_alert_box(rfilter);
2661 rfilter_parse_failed = TRUE;
2664 if (!rfilter_parse_failed) {
2665 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2666 /* "cf_open()" succeeded, so it closed the previous
2667 capture file, and thus destroyed any previous read filter
2668 attached to "cf". */
2670 cfile.rfcode = rfcode;
2671 /* Open stat windows; we do so after creating the main window,
2672 to avoid GTK warnings, and after successfully opening the
2673 capture file, so we know we have something to compute stats
2674 on, and after registering all dissectors, so that MATE will
2675 have registered its field array and we can have a tap filter
2676 with one of MATE's late-registered fields as part of the
2678 start_requested_stats();
2680 /* Read the capture file. */
2681 switch (cf_read(&cfile)) {
2685 /* Just because we got an error, that doesn't mean we were unable
2686 to read any of the file; we handle what we could get from the
2688 /* if the user told us to jump to a specific packet, do it now */
2689 if(go_to_packet != 0) {
2690 cf_goto_frame(&cfile, go_to_packet);
2694 case CF_READ_ABORTED:
2699 /* Save the name of the containing directory specified in the
2700 path name, if any; we can write over cf_name, which is a
2701 good thing, given that "get_dirname()" does write over its
2703 s = get_dirname(cf_name);
2704 set_last_open_dir(s);
2709 dfilter_free(rfcode);
2710 cfile.rfcode = NULL;
2711 show_main_window(FALSE);
2712 set_menus_for_capture_in_progress(FALSE);
2713 set_capture_if_dialog_for_capture_in_progress(FALSE);
2718 if (start_capture) {
2719 if (global_capture_opts.save_file != NULL) {
2720 /* Save the directory name for future file dialogs. */
2721 /* (get_dirname overwrites filename) */
2722 s = get_dirname(g_strdup(global_capture_opts.save_file));
2723 set_last_open_dir(s);
2726 /* "-k" was specified; start a capture. */
2727 show_main_window(TRUE);
2728 if (capture_start(&global_capture_opts)) {
2729 /* The capture started. Open stat windows; we do so after creating
2730 the main window, to avoid GTK warnings, and after successfully
2731 opening the capture file, so we know we have something to compute
2732 stats on, and after registering all dissectors, so that MATE will
2733 have registered its field array and we can have a tap filter with
2734 one of MATE's late-registered fields as part of the filter. */
2735 start_requested_stats();
2739 show_main_window(FALSE);
2740 set_menus_for_capture_in_progress(FALSE);
2741 set_capture_if_dialog_for_capture_in_progress(FALSE);
2744 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2745 if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2746 g_free(global_capture_opts.cfilter);
2747 global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2749 #else /* HAVE_LIBPCAP */
2750 show_main_window(FALSE);
2751 set_menus_for_capture_in_progress(FALSE);
2752 set_capture_if_dialog_for_capture_in_progress(FALSE);
2753 #endif /* HAVE_LIBPCAP */
2756 /* register our pid if we are being run from a U3 device */
2759 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
2761 /* we'll enter the GTK loop now and hand the control over to GTK ... */
2763 /* ... back from GTK, we're going down now! */
2765 /* deregister our pid */
2766 u3_deregister_pid();
2770 #ifdef HAVE_AIRPDCAP
2771 AirPDcapDestroyContext(&airpdcap_ctx);
2775 /* hide the (unresponsive) main window, while asking the user to close the console window */
2776 gtk_widget_hide(top_level);
2778 /* Shutdown windows sockets */
2781 /* For some unknown reason, the "atexit()" call in "create_console()"
2782 doesn't arrange that "destroy_console()" be called when we exit,
2783 so we call it here if a console was created. */
2792 /* We build this as a GUI subsystem application on Win32, so
2793 "WinMain()", not "main()", gets called.
2795 Hack shamelessly stolen from the Win32 port of the GIMP. */
2797 #define _stdcall __attribute__((stdcall))
2801 WinMain (struct HINSTANCE__ *hInstance,
2802 struct HINSTANCE__ *hPrevInstance,
2806 INITCOMMONCONTROLSEX comm_ctrl;
2808 /* Initialize our controls. Required for native Windows file dialogs. */
2809 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
2810 comm_ctrl.dwSize = sizeof(comm_ctrl);
2811 /* Includes the animate, header, hot key, list view, progress bar,
2812 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
2815 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
2816 InitCommonControlsEx(&comm_ctrl);
2818 /* RichEd20.DLL is needed for filter entries. */
2819 LoadLibrary(_T("riched20.dll"));
2821 has_console = FALSE;
2822 return main (__argc, __argv);
2825 /* The code to create and desstroy console windows should not be necessary,
2826 at least as I read the GLib source code, as it looks as if GLib is, on
2827 Win32, *supposed* to create a console window into which to display its
2830 That doesn't happen, however. I suspect there's something completely
2831 broken about that code in GLib-for-Win32, and that it may be related
2832 to the breakage that forces us to just call "printf()" on the message
2833 rather than passing the message on to "g_log_default_handler()"
2834 (which is the routine that does the aforementioned non-functional
2835 console window creation). */
2838 * If this application has no console window to which its standard output
2839 * would go, create one.
2842 create_console(void)
2844 if (stdin_capture) {
2845 /* We've been handed "-i -". Don't mess with stdio. */
2850 /* We have no console to which to print the version string, so
2851 create one and make it the standard input, output, and error. */
2852 if (!AllocConsole())
2853 return; /* couldn't create console */
2855 ws_freopen("CONIN$", "r", stdin);
2856 ws_freopen("CONOUT$", "w", stdout);
2857 ws_freopen("CONOUT$", "w", stderr);
2859 /* Well, we have a console now. */
2862 /* Now register "destroy_console()" as a routine to be called just
2863 before the application exits, so that we can destroy the console
2864 after the user has typed a key (so that the console doesn't just
2865 disappear out from under them, giving the user no chance to see
2866 the message(s) we put in there). */
2867 atexit(destroy_console);
2869 SetConsoleTitle(_T("Wireshark Debug Console"));
2874 destroy_console(void)
2877 printf("\n\nPress any key to exit\n");
2886 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
2887 const char *message, gpointer user_data _U_)
2894 /* ignore log message, if log_level isn't interesting based
2895 upon the console log preferences.
2896 If the preferences haven't been loaded loaded yet, display the
2899 The default console_log_level preference value is such that only
2900 ERROR, CRITICAL and WARNING level messages are processed;
2901 MESSAGE, INFO and DEBUG level messages are ignored. */
2902 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
2903 prefs.console_log_level != 0) {
2908 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
2909 /* the user wants a console or the application will terminate immediately */
2913 /* For some unknown reason, the above doesn't appear to actually cause
2914 anything to be sent to the standard output, so we'll just splat the
2915 message out directly, just to make sure it gets out. */
2917 switch(log_level & G_LOG_LEVEL_MASK) {
2918 case G_LOG_LEVEL_ERROR:
2921 case G_LOG_LEVEL_CRITICAL:
2924 case G_LOG_LEVEL_WARNING:
2927 case G_LOG_LEVEL_MESSAGE:
2930 case G_LOG_LEVEL_INFO:
2933 case G_LOG_LEVEL_DEBUG:
2937 fprintf(stderr, "unknown log_level %u\n", log_level);
2939 g_assert_not_reached();
2942 /* create a "timestamp" */
2944 today = localtime(&curr);
2946 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
2947 today->tm_hour, today->tm_min, today->tm_sec,
2948 log_domain != NULL ? log_domain : "",
2951 if(log_level & G_LOG_LEVEL_ERROR) {
2952 /* wait for a key press before the following error handler will terminate the program
2953 this way the user at least can read the error message */
2954 printf("\n\nPress any key to exit\n");
2958 /* XXX - on UN*X, should we just use g_log_default_handler()?
2959 We want the error messages to go to the standard output;
2960 on Mac OS X, that will cause them to show up in various
2961 per-user logs accessible through Console (details depend
2962 on whether you're running 10.0 through 10.4 or running
2963 10.5 and later), and, on other UN*X desktop environments,
2964 if they don't show up in some form of console log, that's
2965 a deficiency in that desktop environment. (Too bad
2966 Windows doesn't set the standard output and error for
2967 GUI apps to something that shows up in such a log.) */
2968 g_log_default_handler(log_domain, log_level, message, user_data);
2975 * Helper for main_widgets_rearrange()
2977 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
2978 gtk_container_remove(GTK_CONTAINER(data), widget);
2981 static GtkWidget *main_widget_layout(gint layout_content)
2983 switch(layout_content) {
2984 case(layout_pane_content_none):
2986 case(layout_pane_content_plist):
2988 case(layout_pane_content_pdetails):
2990 case(layout_pane_content_pbytes):
2993 g_assert_not_reached();
3000 * Rearrange the main window widgets
3002 void main_widgets_rearrange(void) {
3003 GtkWidget *first_pane_widget1, *first_pane_widget2;
3004 GtkWidget *second_pane_widget1, *second_pane_widget2;
3005 gboolean split_top_left;
3007 /* be a bit faster */
3008 gtk_widget_hide(main_vbox);
3010 /* be sure we don't lose a widget while rearranging */
3011 g_object_ref(G_OBJECT(menubar));
3012 g_object_ref(G_OBJECT(main_tb));
3013 g_object_ref(G_OBJECT(filter_tb));
3015 g_object_ref(G_OBJECT(airpcap_tb));
3017 g_object_ref(G_OBJECT(pkt_scrollw));
3018 g_object_ref(G_OBJECT(tv_scrollw));
3019 g_object_ref(G_OBJECT(byte_nb_ptr));
3020 g_object_ref(G_OBJECT(statusbar));
3021 g_object_ref(G_OBJECT(main_pane_v1));
3022 g_object_ref(G_OBJECT(main_pane_v2));
3023 g_object_ref(G_OBJECT(main_pane_h1));
3024 g_object_ref(G_OBJECT(main_pane_h2));
3025 g_object_ref(G_OBJECT(welcome_pane));
3027 /* empty all containers participating */
3028 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3029 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3030 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3031 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3032 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3034 statusbar_widgets_emptying(statusbar);
3036 /* add the menubar always at the top */
3037 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3040 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3042 /* filter toolbar in toolbar area */
3043 if (!prefs.filter_toolbar_show_in_statusbar) {
3044 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3048 /* airpcap toolbar */
3049 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3052 /* fill the main layout panes */
3053 switch(prefs.gui_layout_type) {
3054 case(layout_type_5):
3055 main_first_pane = main_pane_v1;
3056 main_second_pane = main_pane_v2;
3057 split_top_left = FALSE;
3059 case(layout_type_2):
3060 main_first_pane = main_pane_v1;
3061 main_second_pane = main_pane_h1;
3062 split_top_left = FALSE;
3064 case(layout_type_1):
3065 main_first_pane = main_pane_v1;
3066 main_second_pane = main_pane_h1;
3067 split_top_left = TRUE;
3069 case(layout_type_4):
3070 main_first_pane = main_pane_h1;
3071 main_second_pane = main_pane_v1;
3072 split_top_left = FALSE;
3074 case(layout_type_3):
3075 main_first_pane = main_pane_h1;
3076 main_second_pane = main_pane_v1;
3077 split_top_left = TRUE;
3079 case(layout_type_6):
3080 main_first_pane = main_pane_h1;
3081 main_second_pane = main_pane_h2;
3082 split_top_left = FALSE;
3085 main_first_pane = NULL;
3086 main_second_pane = NULL;
3087 split_top_left = FALSE;
3088 g_assert_not_reached();
3090 if (split_top_left) {
3091 first_pane_widget1 = main_second_pane;
3092 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3093 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3094 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3096 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3097 first_pane_widget2 = main_second_pane;
3098 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3099 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3101 if (first_pane_widget1 != NULL)
3102 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3103 if (first_pane_widget2 != NULL)
3104 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3105 if (second_pane_widget1 != NULL)
3106 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3107 if (second_pane_widget2 != NULL)
3108 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3110 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3113 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3116 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3118 /* filter toolbar in statusbar hbox */
3119 if (prefs.filter_toolbar_show_in_statusbar) {
3120 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3124 /* airpcap toolbar */
3125 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3128 /* statusbar widgets */
3129 statusbar_widgets_pack(statusbar);
3131 /* hide widgets on users recent settings */
3132 main_widgets_show_or_hide();
3134 gtk_widget_show(main_vbox);
3138 is_widget_visible(GtkWidget *widget, gpointer data)
3140 gboolean *is_visible = data;
3143 if (GTK_WIDGET_VISIBLE(widget))
3150 main_widgets_show_or_hide(void)
3152 gboolean main_second_pane_show;
3154 if (recent.main_toolbar_show) {
3155 gtk_widget_show(main_tb);
3157 gtk_widget_hide(main_tb);
3160 statusbar_widgets_show_or_hide(statusbar);
3162 if (recent.filter_toolbar_show) {
3163 gtk_widget_show(filter_tb);
3165 gtk_widget_hide(filter_tb);
3169 if (recent.airpcap_toolbar_show) {
3170 gtk_widget_show(airpcap_tb);
3172 gtk_widget_hide(airpcap_tb);
3176 if (recent.packet_list_show && have_capture_file) {
3177 gtk_widget_show(pkt_scrollw);
3179 gtk_widget_hide(pkt_scrollw);
3182 if (recent.tree_view_show && have_capture_file) {
3183 gtk_widget_show(tv_scrollw);
3185 gtk_widget_hide(tv_scrollw);
3188 if (recent.byte_view_show && have_capture_file) {
3189 gtk_widget_show(byte_nb_ptr);
3191 gtk_widget_hide(byte_nb_ptr);
3194 if (have_capture_file) {
3195 gtk_widget_show(main_first_pane);
3197 gtk_widget_hide(main_first_pane);
3201 * Is anything in "main_second_pane" visible?
3202 * If so, show it, otherwise hide it.
3204 main_second_pane_show = FALSE;
3205 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3206 &main_second_pane_show);
3207 if (main_second_pane_show) {
3208 gtk_widget_show(main_second_pane);
3210 gtk_widget_hide(main_second_pane);
3213 if (!have_capture_file) {
3215 gtk_widget_show(welcome_pane);
3218 gtk_widget_hide(welcome_pane);
3221 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3222 #ifndef NEW_PACKET_LIST
3223 packet_list_freeze ();
3224 packet_list_thaw ();
3229 /* called, when the window state changes (minimized, maximized, ...) */
3231 window_state_event_cb (GtkWidget *widget _U_,
3235 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3237 if( (event->type) == (GDK_WINDOW_STATE)) {
3238 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3239 /* we might have dialogs popped up while we where iconified,
3241 display_queued_messages();
3249 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3251 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3253 if (event->keyval == GDK_F8) {
3254 #ifdef NEW_PACKET_LIST
3255 new_packet_list_next();
3260 } else if (event->keyval == GDK_F7) {
3261 #ifdef NEW_PACKET_LIST
3262 new_packet_list_prev();
3267 } else if (event->state & NO_SHIFT_MOD_MASK) {
3268 return FALSE; /* Skip control, alt, and other modifiers */
3270 * A comment in gdkkeysyms.h says that it's autogenerated from
3271 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3272 * don't explicitly say so, isprint() should work as expected
3275 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3276 /* Forward the keypress on to the display filter entry */
3277 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3278 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3279 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3287 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
3289 GtkAccelGroup *accel;
3292 /* use user-defined title if preference is set */
3293 title = create_user_window_title("The Wireshark Network Analyzer");
3296 top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
3299 gtk_widget_set_name(top_level, "main window");
3300 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3302 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3303 G_CALLBACK(window_state_event_cb), NULL);
3304 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3305 G_CALLBACK(top_level_key_pressed_cb), NULL );
3307 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3308 main_vbox = gtk_vbox_new(FALSE, 1);
3309 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
3310 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3311 gtk_widget_show(main_vbox);
3314 menubar = main_menu_new(&accel);
3316 #ifdef HAVE_IGE_MAC_INTEGRATION
3317 /* MacOS X native menus are created and displayed by main_menu_new() */
3318 if(!prefs->gui_macosx_style) {
3320 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3321 gtk_widget_show(menubar);
3322 #ifdef HAVE_IGE_MAC_INTEGRATION
3327 main_tb = toolbar_new();
3328 gtk_widget_show (main_tb);
3330 /* Filter toolbar */
3331 filter_tb = filter_toolbar_new();
3334 #ifdef NEW_PACKET_LIST
3335 pkt_scrollw = new_packet_list_create();
3336 gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3337 gtk_widget_show_all(pkt_scrollw);
3339 pkt_scrollw = packet_list_new(prefs);
3340 gtk_widget_set_size_request(packet_list, -1, pl_size);
3341 gtk_widget_show(pkt_scrollw);
3345 tv_scrollw = main_tree_view_new(prefs, &tree_view);
3346 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3347 gtk_widget_show(tv_scrollw);
3349 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
3350 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3351 g_signal_connect(tree_view, "button_press_event", G_CALLBACK(popup_menu_handler),
3352 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3353 gtk_widget_show(tree_view);
3356 byte_nb_ptr = byte_view_new();
3357 gtk_widget_set_size_request(byte_nb_ptr, -1, bv_size);
3358 gtk_widget_show(byte_nb_ptr);
3360 g_signal_connect(byte_nb_ptr, "button_press_event", G_CALLBACK(popup_menu_handler),
3361 g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3363 /* Panes for the packet list, tree, and byte view */
3364 main_pane_v1 = gtk_vpaned_new();
3365 gtk_widget_show(main_pane_v1);
3366 main_pane_v2 = gtk_vpaned_new();
3367 gtk_widget_show(main_pane_v2);
3368 main_pane_h1 = gtk_hpaned_new();
3369 gtk_widget_show(main_pane_h1);
3370 main_pane_h2 = gtk_hpaned_new();
3371 gtk_widget_show(main_pane_h2);
3373 airpcap_tb = airpcap_toolbar_new();
3374 gtk_widget_show(airpcap_tb);
3377 statusbar = statusbar_new();
3378 gtk_widget_show(statusbar);
3380 /* Pane for the welcome screen */
3381 welcome_pane = welcome_new();
3382 gtk_widget_show(welcome_pane);
3386 show_main_window(gboolean doing_work)
3388 main_set_for_capture_file(doing_work);
3390 /*** we have finished all init things, show the main window ***/
3391 gtk_widget_show(top_level);
3393 /* the window can be maximized only, if it's visible, so do it after show! */
3394 main_load_window_geometry(top_level);
3396 /* process all pending GUI events before continue */
3397 while (gtk_events_pending()) gtk_main_iteration();
3399 /* Pop up any queued-up alert boxes. */
3400 display_queued_messages();
3402 /* Move the main window to the front, in case it isn't already there */
3403 gdk_window_raise(top_level->window);
3406 airpcap_toolbar_show(airpcap_tb);
3407 #endif /* HAVE_AIRPCAP */
3410 /* Fill in capture options with values from the preferences */
3412 prefs_to_capture_opts(void)
3415 /* Set promiscuous mode from the preferences setting. */
3416 /* the same applies to other preferences settings as well. */
3417 global_capture_opts.promisc_mode = prefs.capture_prom_mode;
3418 global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
3419 global_capture_opts.show_info = prefs.capture_show_info;
3420 global_capture_opts.real_time_mode = prefs.capture_real_time;
3421 auto_scroll_live = prefs.capture_auto_scroll;
3422 #endif /* HAVE_LIBPCAP */
3424 /* Set the name resolution code's flags from the preferences. */
3425 g_resolv_flags = prefs.name_resolve;
3429 /* Change configuration profile */
3430 void change_configuration_profile (const gchar *profile_name)
3432 char *gdp_path, *dp_path;
3436 /* First check if profile exists */
3437 if (!profile_exists(profile_name)) {
3441 /* Get the current geometry, before writing it to disk */
3442 main_save_window_geometry(top_level);
3444 if (profile_exists(get_profile_name())) {
3445 /* Write recent file for profile we are leaving, if it still exists */
3446 write_profile_recent();
3449 /* Set profile name and update the status bar */
3450 set_profile_name (profile_name);
3451 profile_bar_update ();
3453 /* Reset current preferences and apply the new */
3457 (void) read_configuration_files (&gdp_path, &dp_path);
3459 recent_read_profile_static(&rf_path, &rf_open_errno);
3460 if (rf_path != NULL && rf_open_errno != 0) {
3461 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3462 "Could not open common recent file\n\"%s\": %s.",
3463 rf_path, strerror(rf_open_errno));
3465 timestamp_set_type (recent.gui_time_format);
3466 color_filters_enable(recent.packet_list_colorize);
3468 prefs_to_capture_opts();
3471 /* Update window view and redraw the toolbar */
3472 update_main_window_name();
3473 toolbar_redraw_all();
3475 /* Enable all protocols and disable from the disabled list */
3477 if (gdp_path == NULL && dp_path == NULL) {
3478 set_disabled_protos_list();
3481 /* Reload color filters */
3482 color_filters_reload();
3484 /* Reload list of interfaces on welcome page */
3485 welcome_if_panel_reload();
3487 /* Recreate the packet list according to new preferences */
3488 #ifdef NEW_PACKET_LIST
3489 new_packet_list_recreate ();
3491 packet_list_recreate ();
3493 cfile.cinfo.columns_changed = FALSE; /* Reset value */
3496 /* Update menus with new recent values */
3497 menu_recent_read_finished();
3499 /* Reload pane geometry, must be done after recreating the list */
3500 main_pane_load_window_geometry();
3503 /** redissect packets and update UI */
3504 void redissect_packets(void)
3506 cf_redissect_packets(&cfile);
3507 status_expert_update();