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"
158 #include "gtk/prefs_dlg.h"
161 #include "../image/wsicon16.xpm"
162 #include "../image/wsicon32.xpm"
163 #include "../image/wsicon48.xpm"
164 #include "../image/wsicon64.xpm"
165 #include "../image/wsiconcap16.xpm"
166 #include "../image/wsiconcap32.xpm"
167 #include "../image/wsiconcap48.xpm"
172 #include "airpcap_loader.h"
173 #include "airpcap_dlg.h"
174 #include "airpcap_gui_utils.h"
178 #include <epan/crypt/airpdcap_ws.h>
181 #ifdef NEW_PACKET_LIST
182 #include "gtk/new_packet_list.h"
186 * Files under personal and global preferences directories in which
187 * GTK settings for Wireshark are stored.
189 #define RC_FILE "gtkrc"
193 /* "exported" main widgets */
194 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view_gbl, *byte_nb_ptr_gbl;
196 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
197 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
198 static GtkWidget *main_first_pane, *main_second_pane;
200 /* internally used widgets */
201 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
204 GtkWidget *airpcap_tb;
205 int airpcap_dll_ret_val = -1;
208 GString *comp_info_str, *runtime_info_str;
209 gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
211 guint tap_update_timer_id;
214 static gboolean has_console; /* TRUE if app has console */
215 static void destroy_console(void);
216 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
218 static void console_log_handler(const char *log_domain,
219 GLogLevelFlags log_level, const char *message, gpointer user_data);
222 capture_options global_capture_opts;
226 static void create_main_window(gint, gint, gint, e_prefs*);
227 static void show_main_window(gboolean);
228 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
229 static void main_save_window_geometry(GtkWidget *widget);
232 /* Match selected byte pattern */
234 match_selected_cb_do(gpointer data, int action, gchar *text)
236 GtkWidget *filter_te;
237 char *cur_filter, *new_filter;
239 if ((!text) || (0 == strlen(text))) {
240 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
245 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
248 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
250 switch (action&MATCH_SELECTED_MASK) {
252 case MATCH_SELECTED_REPLACE:
253 new_filter = g_strdup(text);
256 case MATCH_SELECTED_AND:
257 if ((!cur_filter) || (0 == strlen(cur_filter)))
258 new_filter = g_strdup(text);
260 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
263 case MATCH_SELECTED_OR:
264 if ((!cur_filter) || (0 == strlen(cur_filter)))
265 new_filter = g_strdup(text);
267 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
270 case MATCH_SELECTED_NOT:
271 new_filter = g_strconcat("!(", text, ")", NULL);
274 case MATCH_SELECTED_AND_NOT:
275 if ((!cur_filter) || (0 == strlen(cur_filter)))
276 new_filter = g_strconcat("!(", text, ")", NULL);
278 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
281 case MATCH_SELECTED_OR_NOT:
282 if ((!cur_filter) || (0 == strlen(cur_filter)))
283 new_filter = g_strconcat("!(", text, ")", NULL);
285 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
289 g_assert_not_reached();
294 /* Free up the copy we got of the old filter text. */
297 /* Don't change the current display filter if we only want to copy the filter */
298 if (action&MATCH_SELECTED_COPY_ONLY) {
299 GString *gtk_text_str = g_string_new("");
300 g_string_append(gtk_text_str, new_filter);
301 copy_to_clipboard(gtk_text_str);
302 g_string_free(gtk_text_str, TRUE);
304 /* create a new one and set the display filter entry accordingly */
305 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
307 /* Run the display filter so it goes in effect. */
308 if (action&MATCH_SELECTED_APPLY_NOW)
309 main_filter_packets(&cfile, new_filter, FALSE);
312 /* Free up the new filter text. */
317 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
321 if (cfile.finfo_selected) {
322 filter = proto_construct_match_selected_string(cfile.finfo_selected,
324 match_selected_cb_do((data ? data : w), action, filter);
329 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
333 if (cfile.finfo_selected) {
334 filter = proto_construct_match_selected_string(cfile.finfo_selected,
336 if ((!filter) || (0 == strlen(filter))) {
337 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
338 "Could not acquire information to build a filter!\n"
339 "Try expanding or choosing another item.");
344 color_display_with_filter(filter);
347 color_filters_reset_tmp();
349 color_filters_set_tmp(filt_nr,filter, FALSE);
351 cf_colorize_packets(&cfile);
357 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
359 gchar *selected_proto_url;
360 gchar *proto_abbrev = data;
365 if (cfile.finfo_selected) {
366 /* open wiki page using the protocol abbreviation */
367 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
368 browser_open_url(selected_proto_url);
369 g_free(selected_proto_url);
372 case(ESD_BTN_CANCEL):
375 g_assert_not_reached();
381 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
384 const gchar *proto_abbrev;
388 if (cfile.finfo_selected) {
389 /* convert selected field to protocol abbreviation */
390 /* XXX - could this conversion be simplified? */
391 field_id = cfile.finfo_selected->hfinfo->id;
392 /* if the selected field isn't a protocol, get it's parent */
393 if(!proto_registrar_is_protocol(field_id)) {
394 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
397 proto_abbrev = proto_registrar_get_abbrev(field_id);
399 if (!proto_is_private(field_id)) {
400 /* ask the user if the wiki page really should be opened */
401 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
402 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
404 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
406 "The Wireshark Wiki is a collaborative approach to provide information "
407 "about Wireshark in several ways (not limited to protocol specifics).\n"
409 "This Wiki is new, so the page of the selected protocol "
410 "may not exist and/or may not contain valuable information.\n"
412 "As everyone can edit the Wiki and add new content (or extend existing), "
413 "you are encouraged to add information if you can.\n"
415 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
417 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
418 "which will save you a lot of editing and will give a consistent look over the pages.",
419 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
420 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
422 /* appologize to the user that the wiki page cannot be opened */
423 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
424 "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
426 "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
428 "Since this is a private protocol, such information is not available in "
429 "a public wiki. Therefore this wiki entry is blocked.\n"
431 "Sorry for the inconvenience.\n",
432 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
437 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
439 gchar *selected_proto_url;
440 gchar *proto_abbrev = data;
444 if (cfile.finfo_selected) {
445 /* open reference page using the protocol abbreviation */
446 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
447 browser_open_url(selected_proto_url);
448 g_free(selected_proto_url);
451 case(ESD_BTN_CANCEL):
454 g_assert_not_reached();
459 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
462 const gchar *proto_abbrev;
466 if (cfile.finfo_selected) {
467 /* convert selected field to protocol abbreviation */
468 /* XXX - could this conversion be simplified? */
469 field_id = cfile.finfo_selected->hfinfo->id;
470 /* if the selected field isn't a protocol, get it's parent */
471 if(!proto_registrar_is_protocol(field_id)) {
472 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
475 proto_abbrev = proto_registrar_get_abbrev(field_id);
477 if (!proto_is_private(field_id)) {
478 /* ask the user if the wiki page really should be opened */
479 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
480 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
482 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
484 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
485 simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
487 /* appologize to the user that the wiki page cannot be opened */
488 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
489 "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
491 "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
493 "Since this is a private protocol, such information is not available on "
494 "a public website. Therefore this filter entry is blocked.\n"
496 "Sorry for the inconvenience.\n",
497 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
503 get_filter_from_packet_list_row_and_column(gpointer data)
505 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
506 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
512 #ifdef NEW_PACKET_LIST
513 fdata = (frame_data *) new_packet_list_get_row_data(row);
515 fdata = (frame_data *) packet_list_get_row_data(row);
521 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
522 cfile.pd, fdata->cap_len, &err, &err_info)) {
523 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
524 cf_read_error_message(err, err_info), cfile.filename);
527 /* proto tree, visible. We need a proto tree if there's custom columns */
528 epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
529 col_custom_prime_edt(&edt, &cfile.cinfo);
531 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata,
533 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
535 if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
536 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
537 /* leak a little but safer than ep_ here */
538 if (cfile.cinfo.col_fmt[column] == COL_CUSTOM) {
539 header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[column]);
540 if (hfi->parent == -1) {
542 buf = se_strdup(cfile.cinfo.col_expr.col_expr[column]);
543 } else if (hfi->type == FT_STRING) {
544 /* Custom string, add quotes */
545 buf = se_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
546 cfile.cinfo.col_expr.col_expr_val[column]);
550 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
551 cfile.cinfo.col_expr.col_expr_val[column]);
555 epan_dissect_cleanup(&edt);
562 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
564 match_selected_cb_do(data,
566 get_filter_from_packet_list_row_and_column(data));
569 /* This function allows users to right click in the details window and copy the text
570 * information to the operating systems clipboard.
572 * We first check to see if a string representation is setup in the tree and then
573 * read the string. If not available then we try to grab the value. If all else
574 * fails we display a message to the user to indicate the copy could not be completed.
577 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
579 GString *gtk_text_str = g_string_new("");
580 char labelstring[256];
581 char *stringpointer = labelstring;
585 case COPY_SELECTED_DESCRIPTION:
586 if (cfile.finfo_selected->rep->representation != 0) {
587 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
590 case COPY_SELECTED_FIELDNAME:
591 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
592 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
595 case COPY_SELECTED_VALUE:
596 if (cfile.edt !=0 ) {
597 g_string_append(gtk_text_str,
598 get_node_field_value(cfile.finfo_selected, cfile.edt));
605 if (gtk_text_str->len == 0) {
606 /* If no representation then... Try to read the value */
607 proto_item_fill_label(cfile.finfo_selected, stringpointer);
608 g_string_append(gtk_text_str, stringpointer);
611 if (gtk_text_str->len == 0) {
612 /* Could not get item so display error msg */
613 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
615 /* Copy string to clipboard */
616 copy_to_clipboard(gtk_text_str);
618 g_string_free(gtk_text_str, TRUE); /* Free the memory */
622 /* mark as reference time frame */
624 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
628 frame->flags.ref_time=1;
630 frame->flags.ref_time=0;
632 cf_reftime_packets(&cfile);
633 #ifdef NEW_PACKET_LIST
634 new_packet_list_queue_draw();
639 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
643 timestamp_set_type(TS_RELATIVE);
644 recent.gui_time_format = TS_RELATIVE;
645 #ifdef NEW_PACKET_LIST
646 cf_timestamp_auto_precision(&cfile);
647 new_packet_list_queue_draw();
649 cf_change_time_formats(&cfile);
655 g_assert_not_reached();
658 if (cfile.current_frame) {
659 set_frame_reftime(!cfile.current_frame->flags.ref_time,
660 cfile.current_frame, cfile.current_row);
666 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
668 static GtkWidget *reftime_dialog = NULL;
672 if (cfile.current_frame) {
673 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
674 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
675 "%sSwitch to the appropriate Time Display Format?%s\n\n"
676 "Time References don't work well with the currently selected Time Display Format.\n\n"
677 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
678 simple_dialog_primary_start(), simple_dialog_primary_end());
679 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
681 set_frame_reftime(!cfile.current_frame->flags.ref_time,
682 cfile.current_frame, cfile.current_row);
686 case REFTIME_FIND_NEXT:
687 find_previous_next_frame_with_filter("frame.ref_time", FALSE);
689 case REFTIME_FIND_PREV:
690 find_previous_next_frame_with_filter("frame.ref_time", TRUE);
696 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
698 find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
702 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
704 find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
708 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
711 gchar *help_str = NULL;
712 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
714 gboolean has_blurb = FALSE;
715 guint length = 0, byte_len;
716 GtkWidget *byte_view;
717 const guint8 *byte_data;
722 /* if nothing is selected */
723 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
726 * Which byte view is displaying the current protocol tree
729 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
730 if (byte_view == NULL)
733 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
734 if (byte_data == NULL)
737 cf_unselect_field(&cfile);
738 packet_hex_print(byte_view, byte_data,
739 cfile.current_frame, NULL, byte_len);
742 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
745 set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
747 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
748 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
749 g_assert(byte_data != NULL);
751 cfile.finfo_selected = finfo;
752 set_menus_for_selected_tree_row(&cfile);
755 if (finfo->hfinfo->blurb != NULL &&
756 finfo->hfinfo->blurb[0] != '\0') {
758 length = (guint) strlen(finfo->hfinfo->blurb);
760 length = (guint) strlen(finfo->hfinfo->name);
762 finfo_length = finfo->length + finfo->appendix_length;
764 if (finfo_length == 0) {
766 } else if (finfo_length == 1) {
767 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
769 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
771 statusbar_pop_field_msg(); /* get rid of current help msg */
773 help_str = g_strdup_printf(" %s (%s)%s",
774 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
775 finfo->hfinfo->abbrev, len_str);
776 statusbar_push_field_msg(help_str);
780 * Don't show anything if the field name is zero-length;
781 * the pseudo-field for "proto_tree_add_text()" is such
782 * a field, and we don't want "Text (text)" showing up
783 * on the status line if you've selected such a field.
785 * XXX - there are zero-length fields for which we *do*
786 * want to show the field name.
788 * XXX - perhaps the name and abbrev field should be null
789 * pointers rather than null strings for that pseudo-field,
790 * but we'd have to add checks for null pointers in some
791 * places if we did that.
793 * Or perhaps protocol tree items added with
794 * "proto_tree_add_text()" should have -1 as the field index,
795 * with no pseudo-field being used, but that might also
796 * require special checks for -1 to be added.
798 statusbar_push_field_msg("");
801 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
805 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
807 collapse_all_tree(cfile.edt->tree, tree_view_gbl);
810 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
812 expand_all_tree(cfile.edt->tree, tree_view_gbl);
815 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
817 if (cfile.finfo_selected) {
818 column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
819 cfile.finfo_selected->hfinfo->abbrev);
820 /* Recreate the packet list according to new preferences */
821 #ifdef NEW_PACKET_LIST
822 new_packet_list_recreate ();
824 packet_list_recreate ();
826 if (!prefs.gui_use_pref_save) {
829 cfile.cinfo.columns_changed = FALSE; /* Reset value */
833 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
836 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
838 /* the mouse position is at an entry, expand that one */
839 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
840 gtk_tree_path_free(path);
844 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
845 if (cfile.edt->tree) {
846 guint32 tmp = g_resolv_flags;
847 g_resolv_flags = RESOLV_ALL;
848 proto_tree_draw(cfile.edt->tree, tree_view_gbl);
849 g_resolv_flags = tmp;
854 main_set_for_capture_file(gboolean have_capture_file_in)
856 have_capture_file = have_capture_file_in;
858 main_widgets_show_or_hide();
864 /* get the current geometry, before writing it to disk */
865 main_save_window_geometry(top_level);
867 /* write user's recent file to disk
868 * It is no problem to write this file, even if we do not quit */
869 write_profile_recent();
872 /* XXX - should we check whether the capture file is an
873 unsaved temporary file for a live capture and, if so,
874 pop up a "do you want to exit without saving the capture
875 file?" dialog, and then just return, leaving said dialog
876 box to forcibly quit if the user clicks "OK"?
878 If so, note that this should be done in a subroutine that
879 returns TRUE if we do so, and FALSE otherwise, and if it
880 returns TRUE we should return TRUE without nuking anything.
882 Note that, if we do that, we might also want to check if
883 an "Update list of packets in real time" capture is in
884 progress and, if so, ask whether they want to terminate
885 the capture and discard it, and return TRUE, before nuking
886 any child capture, if they say they don't want to do so. */
889 /* Nuke any child capture in progress. */
890 capture_kill_child(&global_capture_opts);
893 /* Are we in the middle of reading a capture? */
894 if (cfile.state == FILE_READ_IN_PROGRESS) {
895 /* Yes, so we can't just close the file and quit, as
896 that may yank the rug out from under the read in
897 progress; instead, just set the state to
898 "FILE_READ_ABORTED" and return - the code doing the read
899 will check for that and, if it sees that, will clean
901 cfile.state = FILE_READ_ABORTED;
903 /* Say that the window should *not* be deleted;
904 that'll be done by the code that cleans up. */
907 /* Close any capture file we have open; on some OSes, you
908 can't unlink a temporary capture file if you have it
910 "cf_close()" will unlink it after closing it if
911 it's a temporary file.
913 We do this here, rather than after the main loop returns,
914 as, after the main loop returns, the main window may have
915 been destroyed (if this is called due to a "destroy"
916 even on the main window rather than due to the user
917 selecting a menu item), and there may be a crash
918 or other problem when "cf_close()" tries to
919 clean up stuff in the main window.
921 XXX - is there a better place to put this?
922 Or should we have a routine that *just* closes the
923 capture file, and doesn't do anything with the UI,
924 which we'd call here, and another routine that
925 calls that routine and also cleans up the UI, which
926 we'd call elsewhere? */
929 /* Exit by leaving the main loop, so that any quit functions
930 we registered get called. */
933 /* Say that the window should be deleted. */
939 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
943 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
944 gtk_window_present(GTK_WINDOW(top_level));
945 /* user didn't saved his current file, ask him */
946 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
947 "%sSave capture file before program quit?%s\n\n"
948 "If you quit the program without saving, your capture data will be discarded.",
949 simple_dialog_primary_start(), simple_dialog_primary_end());
950 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
953 /* unchanged file, just exit */
954 /* "main_do_quit()" indicates whether the main window should be deleted. */
955 return main_do_quit();
961 main_pane_load_window_geometry(void)
963 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
964 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
965 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
966 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
972 main_load_window_geometry(GtkWidget *widget)
974 window_geometry_t geom;
976 geom.set_pos = prefs.gui_geometry_save_position;
977 geom.x = recent.gui_geometry_main_x;
978 geom.y = recent.gui_geometry_main_y;
979 geom.set_size = prefs.gui_geometry_save_size;
980 if (recent.gui_geometry_main_width > 0 &&
981 recent.gui_geometry_main_height > 0) {
982 geom.width = recent.gui_geometry_main_width;
983 geom.height = recent.gui_geometry_main_height;
984 geom.set_maximized = prefs.gui_geometry_save_maximized;
986 /* We assume this means the width and height weren't set in
987 the "recent" file (or that there is no "recent" file),
988 and weren't set to a default value, so we don't set the
989 size. (The "recent" file code rejects non-positive width
990 and height values.) */
991 geom.set_size = FALSE;
993 geom.maximized = recent.gui_geometry_main_maximized;
995 window_set_geometry(widget, &geom);
997 main_pane_load_window_geometry();
998 statusbar_load_window_geometry();
1003 main_save_window_geometry(GtkWidget *widget)
1005 window_geometry_t geom;
1007 window_get_geometry(widget, &geom);
1009 if (prefs.gui_geometry_save_position) {
1010 recent.gui_geometry_main_x = geom.x;
1011 recent.gui_geometry_main_y = geom.y;
1014 if (prefs.gui_geometry_save_size) {
1015 recent.gui_geometry_main_width = geom.width;
1016 recent.gui_geometry_main_height = geom.height;
1019 if(prefs.gui_geometry_save_maximized) {
1020 recent.gui_geometry_main_maximized = geom.maximized;
1023 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1024 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1025 statusbar_save_window_geometry();
1028 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1032 /* save file first */
1033 file_save_as_cmd(after_save_exit, NULL);
1035 case(ESD_BTN_QUIT_DONT_SAVE):
1038 case(ESD_BTN_CANCEL):
1041 g_assert_not_reached();
1046 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1050 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1051 /* user didn't saved his current file, ask him */
1052 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1053 "%sSave capture file before program quit?%s\n\n"
1054 "If you quit the program without saving, your capture data will be discarded.",
1055 simple_dialog_primary_start(), simple_dialog_primary_end());
1056 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1058 /* unchanged file, just exit */
1064 print_usage(gboolean print_ver) {
1074 fprintf(output, "Wireshark " VERSION "%s\n"
1075 "Interactively dump and analyze network traffic.\n"
1076 "See http://www.wireshark.org for more information.\n"
1079 wireshark_svnversion, get_copyright_info());
1083 fprintf(output, "\n");
1084 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1085 fprintf(output, "\n");
1088 fprintf(output, "Capture interface:\n");
1089 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1090 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1091 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1092 fprintf(output, " -p don't capture in promiscuous mode\n");
1093 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1094 fprintf(output, " -Q quit Wireshark after capturing\n");
1095 fprintf(output, " -S update packet display when new packets are captured\n");
1096 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1098 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1100 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1101 fprintf(output, " -D print list of interfaces and exit\n");
1102 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1103 fprintf(output, "\n");
1104 fprintf(output, "Capture stop conditions:\n");
1105 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1106 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1107 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1108 fprintf(output, " files:NUM - stop after NUM files\n");
1109 /*fprintf(output, "\n");*/
1110 fprintf(output, "Capture output:\n");
1111 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1112 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1113 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1114 #endif /* HAVE_LIBPCAP */
1116 /*fprintf(output, "\n");*/
1117 fprintf(output, "Input file:\n");
1118 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1120 fprintf(output, "\n");
1121 fprintf(output, "Processing:\n");
1122 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1123 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1124 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1126 fprintf(output, "\n");
1127 fprintf(output, "User interface:\n");
1128 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1129 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1130 fprintf(output, " -J <jump filter> jump to the first packet matching the (display) filter\n");
1131 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
1132 fprintf(output, " -m <font> set the font name used for most text\n");
1133 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1134 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1135 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1137 fprintf(output, "\n");
1138 fprintf(output, "Output:\n");
1139 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1141 fprintf(output, "\n");
1142 fprintf(output, "Miscellaneous:\n");
1143 fprintf(output, " -h display this help and exit\n");
1144 fprintf(output, " -v display version info and exit\n");
1145 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1146 fprintf(output, " persdata:path - personal data files\n");
1147 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1148 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1150 fprintf(output, " --display=DISPLAY X display to use\n");
1165 printf(PACKAGE " " VERSION "%s\n"
1172 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1173 runtime_info_str->str);
1181 * Report an error in command-line arguments.
1182 * Creates a console on Windows.
1183 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1184 * terminal isn't the standard error?
1187 cmdarg_err(const char *fmt, ...)
1195 fprintf(stderr, "wireshark: ");
1196 vfprintf(stderr, fmt, ap);
1197 fprintf(stderr, "\n");
1202 * Report additional information for an error in command-line arguments.
1203 * Creates a console on Windows.
1204 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1205 * terminal isn't the standard error?
1208 cmdarg_err_cont(const char *fmt, ...)
1216 vfprintf(stderr, fmt, ap);
1217 fprintf(stderr, "\n");
1221 #if defined(_WIN32) || ! defined USE_THREADS
1223 Once every 3 seconds we get a callback here which we use to update
1224 the tap extensions. Since Gtk1 is single threaded we dont have to
1225 worry about any locking or critical regions.
1228 tap_update_cb(gpointer data _U_)
1230 draw_tap_listeners(FALSE);
1234 /* Restart the tap update display timer with new configured interval */
1235 void reset_tap_update_timer(void)
1237 g_source_remove(tap_update_timer_id);
1238 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1243 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1244 use threads all update_thread_mutex can be dropped and protect/unprotect
1245 would just be empty functions.
1247 This allows gtk2-rpcstat.c and friends to be copied unmodified to
1248 gtk1-wireshark and it will just work.
1250 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1252 update_thread(gpointer data _U_)
1256 g_get_current_time(&tv1);
1257 g_static_mutex_lock(&update_thread_mutex);
1258 gdk_threads_enter();
1259 draw_tap_listeners(FALSE);
1260 gdk_threads_leave();
1261 g_static_mutex_unlock(&update_thread_mutex);
1263 g_get_current_time(&tv2);
1265 /* Assuming it took less than configured time to update tap listeners... */
1266 if( (tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) >
1267 (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1268 /* Wait for remainder of configured time */
1269 g_usleep((tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) -
1270 (tv2.tv_sec * 1000000 + tv2.tv_usec));
1277 protect_thread_critical_region(void)
1279 #if !defined(_WIN32) && defined USE_THREADS
1280 g_static_mutex_lock(&update_thread_mutex);
1284 unprotect_thread_critical_region(void)
1286 #if !defined(_WIN32) && defined USE_THREADS
1287 g_static_mutex_unlock(&update_thread_mutex);
1292 * Periodically process outstanding hostname lookups. If we have new items,
1293 * redraw the packet list and tree view.
1297 resolv_update_cb(gpointer data _U_)
1299 /* Anything new show up? */
1300 if (host_name_lookup_process(NULL)) {
1301 gdk_window_invalidate_rect(pkt_scrollw->window, NULL, TRUE);
1302 gdk_window_invalidate_rect(tv_scrollw->window, NULL, TRUE);
1305 /* Always check. Even if we don't do async lookups we could still get
1306 passive updates, e.g. from DNS packets. */
1311 /* Set the file name in the name for the main window and in the name for the main window's icon. */
1313 set_display_filename(capture_file *cf)
1317 if (!cf->is_tempfile && cf->filename) {
1318 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1319 add_menu_recent_capture_file(cf->filename);
1323 win_name = g_strdup_printf("%s - Wireshark", cf_get_display_name(cf));
1324 set_main_window_name(win_name);
1328 GtkWidget *close_dlg = NULL;
1331 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1333 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1338 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1340 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1345 main_cf_cb_file_closing(capture_file *cf)
1348 /* if we have more than 10000 packets, show a splash screen while closing */
1349 /* XXX - don't know a better way to decide whether to show or not,
1350 * as most of the time is spend in a single eth_clist_clear function,
1351 * so we can't use a progress bar here! */
1352 if(cf->count > 10000) {
1353 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1354 "%sClosing file!%s\n\nPlease wait ...",
1355 simple_dialog_primary_start(),
1356 simple_dialog_primary_end());
1357 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1360 /* Destroy all windows, which refer to the
1361 capture file we're closing. */
1362 destroy_packet_wins();
1363 file_save_as_destroy();
1365 /* Restore the standard title bar message. */
1366 set_main_window_name("The Wireshark Network Analyzer");
1368 /* Disable all menu items that make sense only if you have a capture. */
1369 set_menus_for_capture_file(NULL);
1370 set_menus_for_captured_packets(FALSE);
1371 set_menus_for_selected_packet(cf);
1372 set_menus_for_capture_in_progress(FALSE);
1373 set_capture_if_dialog_for_capture_in_progress(FALSE);
1374 set_menus_for_selected_tree_row(cf);
1376 /* Set up main window for no capture file. */
1377 main_set_for_capture_file(FALSE);
1379 main_window_update();
1383 main_cf_cb_file_closed(capture_file *cf _U_)
1385 if(close_dlg != NULL) {
1386 splash_destroy(close_dlg);
1393 main_cf_cb_file_read_started(capture_file *cf _U_)
1395 tap_dfilter_dlg_update();
1397 /* Set up main window for a capture file. */
1398 main_set_for_capture_file(TRUE);
1402 main_cf_cb_file_read_finished(capture_file *cf)
1404 set_display_filename(cf);
1406 /* Enable menu items that make sense if you have a capture file you've
1407 finished reading. */
1408 set_menus_for_capture_file(cf);
1410 /* Enable menu items that make sense if you have some captured packets. */
1411 set_menus_for_captured_packets(TRUE);
1415 static GList *icon_list_create(
1416 const char **icon16_xpm,
1417 const char **icon32_xpm,
1418 const char **icon48_xpm,
1419 const char **icon64_xpm)
1421 GList *icon_list = NULL;
1422 GdkPixbuf * pixbuf16;
1423 GdkPixbuf * pixbuf32;
1424 GdkPixbuf * pixbuf48;
1425 GdkPixbuf * pixbuf64;
1428 if(icon16_xpm != NULL) {
1429 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1431 icon_list = g_list_append(icon_list, pixbuf16);
1434 if(icon32_xpm != NULL) {
1435 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1437 icon_list = g_list_append(icon_list, pixbuf32);
1440 if(icon48_xpm != NULL) {
1441 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1443 icon_list = g_list_append(icon_list, pixbuf48);
1446 if(icon64_xpm != NULL) {
1447 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1449 icon_list = g_list_append(icon_list, pixbuf64);
1456 main_capture_set_main_window_title(capture_options *capture_opts)
1458 GString *title = g_string_new("");
1460 g_string_append(title, "Capturing ");
1461 if(capture_opts->iface) {
1462 g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1464 g_string_append(title, "- Wireshark");
1466 set_main_window_name(title->str);
1467 g_string_free(title, TRUE);
1471 main_capture_cb_capture_prepared(capture_options *capture_opts)
1473 static GList *icon_list = NULL;
1475 main_capture_set_main_window_title(capture_opts);
1477 if(icon_list == NULL) {
1478 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1480 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1482 /* Disable menu items that make no sense if you're currently running
1484 set_menus_for_capture_in_progress(TRUE);
1485 set_capture_if_dialog_for_capture_in_progress(TRUE);
1487 /* Don't set up main window for a capture file. */
1488 main_set_for_capture_file(FALSE);
1492 main_capture_cb_capture_update_started(capture_options *capture_opts)
1494 /* We've done this in "prepared" above, but it will be cleared while
1495 switching to the next multiple file. */
1496 main_capture_set_main_window_title(capture_opts);
1498 set_menus_for_capture_in_progress(TRUE);
1499 set_capture_if_dialog_for_capture_in_progress(TRUE);
1501 /* Enable menu items that make sense if you have some captured
1502 packets (yes, I know, we don't have any *yet*). */
1503 set_menus_for_captured_packets(TRUE);
1505 /* Set up main window for a capture file. */
1506 main_set_for_capture_file(TRUE);
1510 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1512 capture_file *cf = capture_opts->cf;
1513 static GList *icon_list = NULL;
1515 set_display_filename(cf);
1517 /* Enable menu items that make sense if you're not currently running
1519 set_menus_for_capture_in_progress(FALSE);
1520 set_capture_if_dialog_for_capture_in_progress(FALSE);
1522 /* Enable menu items that make sense if you have a capture file
1523 you've finished reading. */
1524 set_menus_for_capture_file(cf);
1526 /* Set up main window for a capture file. */
1527 main_set_for_capture_file(TRUE);
1529 if(icon_list == NULL) {
1530 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1532 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1534 if(global_capture_opts.quit_after_cap) {
1535 /* command line asked us to quit after the capture */
1536 /* don't pop up a dialog to ask for unsaved files etc. */
1542 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1544 /* Don't set up main window for a capture file. */
1545 main_set_for_capture_file(FALSE);
1549 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1552 capture_file *cf = capture_opts->cf;
1554 static GList *icon_list = NULL;
1556 /*set_display_filename(cf);*/
1558 /* Enable menu items that make sense if you're not currently running
1560 set_menus_for_capture_in_progress(FALSE);
1561 set_capture_if_dialog_for_capture_in_progress(FALSE);
1563 /* Restore the standard title bar message */
1564 /* (just in case we have trouble opening the capture file). */
1565 set_main_window_name("The Wireshark Network Analyzer");
1567 if(icon_list == NULL) {
1568 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1570 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1572 /* We don't have loaded the capture file, this will be done later.
1573 * For now we still have simply a blank screen. */
1575 if(global_capture_opts.quit_after_cap) {
1576 /* command line asked us to quit after the capture */
1577 /* don't pop up a dialog to ask for unsaved files etc. */
1582 #endif /* HAVE_LIBPCAP */
1585 main_cf_cb_packet_selected(gpointer data)
1587 capture_file *cf = data;
1589 /* Display the GUI protocol tree and packet bytes.
1590 XXX - why do we dump core if we call "proto_tree_draw()"
1591 before calling "add_byte_views()"? */
1592 add_main_byte_views(cf->edt);
1593 main_proto_tree_draw(cf->edt->tree);
1595 /* The user is searching for a string in the data or a hex value,
1596 * highlight the field that is found in the tree and hex displays. */
1597 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1598 highlight_field(cf->edt->tvb, cfile.search_pos,
1599 (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1600 cfile.search_pos = 0; /* Reset the position */
1603 /* A packet is selected. */
1604 set_menus_for_selected_packet(cf);
1608 main_cf_cb_packet_unselected(capture_file *cf)
1610 /* Clear out the display of that packet. */
1611 clear_tree_and_hex_views();
1613 /* No packet is selected. */
1614 set_menus_for_selected_packet(cf);
1618 main_cf_cb_field_unselected(capture_file *cf)
1620 set_menus_for_selected_tree_row(cf);
1624 main_cf_cb_file_save_reload_finished(gpointer data _U_)
1626 set_display_filename(&cfile);
1627 set_menus_for_capture_file(&cfile);
1631 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1634 case(cf_cb_file_closing):
1635 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1636 main_cf_cb_file_closing(data);
1638 case(cf_cb_file_closed):
1639 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1640 main_cf_cb_file_closed(data);
1642 case(cf_cb_file_read_started):
1643 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1644 main_cf_cb_file_read_started(data);
1646 case(cf_cb_file_read_finished):
1647 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1648 main_cf_cb_file_read_finished(data);
1650 case(cf_cb_packet_selected):
1651 main_cf_cb_packet_selected(data);
1653 case(cf_cb_packet_unselected):
1654 main_cf_cb_packet_unselected(data);
1656 case(cf_cb_field_unselected):
1657 main_cf_cb_field_unselected(data);
1659 case(cf_cb_file_save_started):
1660 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1662 case(cf_cb_file_save_finished):
1663 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1665 case(cf_cb_file_save_reload_finished):
1666 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1667 main_cf_cb_file_save_reload_finished(data);
1669 case(cf_cb_file_save_failed):
1670 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1673 g_warning("main_cf_callback: event %u unknown", event);
1674 g_assert_not_reached();
1680 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1683 case(capture_cb_capture_prepared):
1684 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1685 main_capture_cb_capture_prepared(capture_opts);
1687 case(capture_cb_capture_update_started):
1688 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1689 main_capture_cb_capture_update_started(capture_opts);
1691 case(capture_cb_capture_update_continue):
1692 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1694 case(capture_cb_capture_update_finished):
1695 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1696 main_capture_cb_capture_update_finished(capture_opts);
1698 case(capture_cb_capture_fixed_started):
1699 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1700 main_capture_cb_capture_fixed_started(capture_opts);
1702 case(capture_cb_capture_fixed_continue):
1703 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1705 case(capture_cb_capture_fixed_finished):
1706 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1707 main_capture_cb_capture_fixed_finished(capture_opts);
1709 case(capture_cb_capture_stopping):
1710 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1711 /* Beware: this state won't be called, if the capture child
1712 * closes the capturing on it's own! */
1715 g_warning("main_capture_callback: event %u unknown", event);
1716 g_assert_not_reached();
1722 get_gui_compiled_info(GString *str)
1724 get_epan_compiled_version_info(str);
1726 g_string_append(str, ", ");
1727 #ifdef HAVE_LIBPORTAUDIO
1728 #ifdef PORTAUDIO_API_1
1729 g_string_append(str, "with PortAudio <= V18");
1730 #else /* PORTAUDIO_API_1 */
1731 g_string_append(str, "with ");
1732 g_string_append(str, Pa_GetVersionText());
1733 #endif /* PORTAUDIO_API_1 */
1734 #else /* HAVE_LIBPORTAUDIO */
1735 g_string_append(str, "without PortAudio");
1736 #endif /* HAVE_LIBPORTAUDIO */
1738 g_string_append(str, ", ");
1740 get_compiled_airpcap_version(str);
1742 g_string_append(str, "without AirPcap");
1744 #ifdef NEW_PACKET_LIST
1745 g_string_append(str, ", with new_packet_list");
1750 get_gui_runtime_info(GString *str)
1753 g_string_append(str, ", ");
1754 get_runtime_airpcap_version(str);
1758 g_string_append(str, ", ");
1759 u3_runtime_info(str);
1765 read_configuration_files(char **gdp_path, char **dp_path)
1767 int gpf_open_errno, gpf_read_errno;
1768 int cf_open_errno, df_open_errno;
1769 int gdp_open_errno, gdp_read_errno;
1770 int dp_open_errno, dp_read_errno;
1771 char *gpf_path, *pf_path;
1772 char *cf_path, *df_path;
1773 int pf_open_errno, pf_read_errno;
1776 /* Read the preference files. */
1777 prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1778 &pf_open_errno, &pf_read_errno, &pf_path);
1780 if (gpf_path != NULL) {
1781 if (gpf_open_errno != 0) {
1782 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1783 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1784 strerror(gpf_open_errno));
1786 if (gpf_read_errno != 0) {
1787 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1788 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1789 strerror(gpf_read_errno));
1792 if (pf_path != NULL) {
1793 if (pf_open_errno != 0) {
1794 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1795 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1796 strerror(pf_open_errno));
1798 if (pf_read_errno != 0) {
1799 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1800 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1801 strerror(pf_read_errno));
1808 /* if the user wants a console to be always there, well, we should open one for him */
1809 if (prefs_p->gui_console_open == console_open_always) {
1814 /* Read the capture filter file. */
1815 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1816 if (cf_path != NULL) {
1817 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1818 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1819 strerror(cf_open_errno));
1823 /* Read the display filter file. */
1824 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1825 if (df_path != NULL) {
1826 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1827 "Could not open your display filter file\n\"%s\": %s.", df_path,
1828 strerror(df_open_errno));
1832 /* Read the disabled protocols file. */
1833 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1834 dp_path, &dp_open_errno, &dp_read_errno);
1835 if (*gdp_path != NULL) {
1836 if (gdp_open_errno != 0) {
1837 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1838 "Could not open global disabled protocols file\n\"%s\": %s.",
1839 *gdp_path, strerror(gdp_open_errno));
1841 if (gdp_read_errno != 0) {
1842 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1843 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1844 *gdp_path, strerror(gdp_read_errno));
1849 if (*dp_path != NULL) {
1850 if (dp_open_errno != 0) {
1851 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1852 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1853 strerror(dp_open_errno));
1855 if (dp_read_errno != 0) {
1856 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1857 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1858 strerror(dp_read_errno));
1867 /* And now our feature presentation... [ fade to music ] */
1869 main(int argc, char *argv[])
1871 char *init_progfile_dir_error;
1874 gboolean arg_error = FALSE;
1876 extern int info_update_freq; /* Found in about_dlg.c. */
1877 const gchar *filter;
1885 char *gdp_path, *dp_path;
1888 gboolean start_capture = FALSE;
1889 gboolean list_link_layer_types = FALSE;
1891 gboolean capture_option_specified = FALSE;
1893 gint pl_size = 280, tv_size = 95, bv_size = 75;
1894 gchar *rc_file, *cf_name = NULL, *rfilter = NULL, *jfilter = NULL;
1895 dfilter_t *rfcode = NULL;
1896 gboolean rfilter_parse_failed = FALSE;
1899 GtkWidget *splash_win = NULL;
1900 gpointer priv_warning_dialog;
1901 GLogLevelFlags log_flags;
1902 guint go_to_packet = 0;
1903 gboolean jump_backwards = FALSE, saved_bw = FALSE;
1904 dfilter_t *jump_to_filter = NULL;
1907 gchar *cur_user, *cur_group;
1915 #define OPTSTRING_INIT "a:b:c:C:Df:g:Hhi:jJ:kK:lLm:nN:o:P:pQr:R:Ss:t:vw:X:y:z:"
1917 #if defined HAVE_LIBPCAP && defined _WIN32
1918 #define OPTSTRING_WIN32 "B:"
1920 #define OPTSTRING_WIN32 ""
1923 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
1924 OPTSTRING_INIT OPTSTRING_WIN32;
1927 * Get credential information for later use, and drop privileges
1928 * before doing anything else.
1929 * Let the user know if anything happened.
1931 get_credential_info();
1932 relinquish_special_privs_perm();
1935 * Attempt to get the pathname of the executable file.
1937 init_progfile_dir_error = init_progfile_dir(argv[0], main);
1939 /* initialize the funnel mini-api */
1940 initialize_funnel_ops();
1942 #ifdef HAVE_AIRPDCAP
1943 AirPDcapInitContext(&airpdcap_ctx);
1947 /* Load wpcap if possible. Do this before collecting the run-time version information */
1950 /* ... and also load the packet.dll from wpcap */
1951 wpcap_packet_load();
1954 /* Load the airpcap.dll. This must also be done before collecting
1955 * run-time version information. */
1956 airpcap_dll_ret_val = load_airpcap();
1958 switch (airpcap_dll_ret_val) {
1959 case AIRPCAP_DLL_OK:
1960 /* load the airpcap interfaces */
1961 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
1963 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
1964 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
1965 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
1968 airpcap_if_active = NULL;
1972 /* select the first ad default (THIS SHOULD BE CHANGED) */
1973 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
1978 * XXX - Maybe we need to warn the user if one of the following happens???
1980 case AIRPCAP_DLL_OLD:
1981 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
1984 case AIRPCAP_DLL_ERROR:
1985 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
1988 case AIRPCAP_DLL_NOT_FOUND:
1989 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
1993 #endif /* HAVE_AIRPCAP */
1995 /* Start windows sockets */
1996 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
1999 profile_store_persconffiles (TRUE);
2001 /* Assemble the compile-time version information string */
2002 comp_info_str = g_string_new("Compiled ");
2004 g_string_append(comp_info_str, "with ");
2005 g_string_append_printf(comp_info_str,
2006 #ifdef GTK_MAJOR_VERSION
2007 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
2010 "GTK+ (version unknown)");
2012 g_string_append(comp_info_str, ", ");
2014 get_compiled_version_info(comp_info_str, get_gui_compiled_info);
2016 /* Assemble the run-time version information string */
2017 runtime_info_str = g_string_new("Running ");
2018 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2020 /* Read the profile independent recent file. We have to do this here so we can */
2021 /* set the profile before it can be set from the command line parameterts */
2022 recent_read_static(&rf_path, &rf_open_errno);
2023 if (rf_path != NULL && rf_open_errno != 0) {
2024 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2025 "Could not open common recent file\n\"%s\": %s.",
2026 rf_path, strerror(rf_open_errno));
2029 /* "pre-scan" the command line parameters, if we have "console only"
2030 parameters. We do this so we don't start GTK+ if we're only showing
2031 command-line help or version information.
2033 XXX - this pre-scan is done before we start GTK+, so we haven't
2034 run gtk_init() on the arguments. That means that GTK+ arguments
2035 have not been removed from the argument list; those arguments
2036 begin with "--", and will be treated as an error by getopt().
2038 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2041 optind_initial = optind;
2042 while ((opt = getopt(argc, argv, optstring)) != -1) {
2044 case 'C': /* Configuration Profile */
2045 if (profile_exists (optarg)) {
2046 set_profile_name (optarg);
2048 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2052 case 'h': /* Print help and exit */
2058 if (strcmp(optarg, "-") == 0)
2059 stdin_capture = TRUE;
2062 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2063 status = filesystem_opt(opt, optarg);
2065 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2069 case 'v': /* Show version and exit */
2075 * Extension command line options have to be processed before
2076 * we call epan_init() as they are supposed to be used by dissectors
2077 * or taps very early in the registration process.
2081 case '?': /* Ignore errors - the "real" scan will catch them. */
2086 /* Init the "Open file" dialog directory */
2087 /* (do this after the path settings are processed) */
2088 set_last_open_dir(get_persdatafile_dir());
2090 /* Set getopt index back to initial value, so it will start with the
2091 first command line parameter again. Also reset opterr to 1, so that
2092 error messages are printed by getopt().
2094 XXX - this seems to work on most platforms, but time will tell.
2095 The Single UNIX Specification says "The getopt() function need
2096 not be reentrant", so this isn't guaranteed to work. The Mac
2097 OS X 10.4[.x] getopt() man page says
2099 In order to use getopt() to evaluate multiple sets of arguments, or to
2100 evaluate a single set of arguments multiple times, the variable optreset
2101 must be set to 1 before the second and each additional set of calls to
2102 getopt(), and the variable optind must be reinitialized.
2106 The optreset variable was added to make it possible to call the getopt()
2107 function multiple times. This is an extension to the IEEE Std 1003.2
2108 (``POSIX.2'') specification.
2110 which I think comes from one of the other BSDs.
2112 XXX - if we want to control all the command-line option errors, so
2113 that we can display them where we choose (e.g., in a window), we'd
2114 want to leave opterr as 0, and produce our own messages using optopt.
2115 We'd have to check the value of optopt to see if it's a valid option
2116 letter, in which case *presumably* the error is "this option requires
2117 an argument but none was specified", or not a valid option letter,
2118 in which case *presumably* the error is "this option isn't valid".
2119 Some versions of getopt() let you supply a option string beginning
2120 with ':', which means that getopt() will return ':' rather than '?'
2121 for "this option requires an argument but none was specified", but
2123 optind = optind_initial;
2126 /* Set the current locale according to the program environment.
2127 * We haven't localized anything, but some GTK widgets are localized
2128 * (the file selection dialogue, for example).
2129 * This also sets the C-language locale to the native environment. */
2132 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2133 gtk_init (&argc, &argv);
2135 cf_callback_add(main_cf_callback, NULL);
2137 capture_callback_add(main_capture_callback, NULL);
2139 cf_callback_add(statusbar_cf_callback, NULL);
2141 capture_callback_add(statusbar_capture_callback, NULL);
2144 /* Arrange that if we have no console window, and a GLib message logging
2145 routine is called to log a message, we pop up a console window.
2147 We do that by inserting our own handler for all messages logged
2148 to the default domain; that handler pops up a console if necessary,
2149 and then calls the default handler. */
2151 /* We might want to have component specific log levels later ... */
2155 G_LOG_LEVEL_CRITICAL|
2156 G_LOG_LEVEL_WARNING|
2157 G_LOG_LEVEL_MESSAGE|
2160 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2162 g_log_set_handler(NULL,
2164 console_log_handler, NULL /* user_data */);
2165 g_log_set_handler(LOG_DOMAIN_MAIN,
2167 console_log_handler, NULL /* user_data */);
2170 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2172 console_log_handler, NULL /* user_data */);
2173 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2175 console_log_handler, NULL /* user_data */);
2177 /* Set the initial values in the capture options. This might be overwritten
2178 by preference settings and then again by the command line parameters. */
2179 capture_opts_init(&global_capture_opts, &cfile);
2181 global_capture_opts.snaplen = MIN_PACKET_SIZE;
2182 global_capture_opts.has_ring_num_files = TRUE;
2185 /* Initialize whatever we need to allocate colors for GTK+ */
2188 /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2189 filter = get_conn_cfilter();
2190 if ( *filter != '\0' ) {
2191 info_update_freq = 1000; /* Milliseconds */
2194 /* We won't come till here, if we had a "console only" command line parameter. */
2195 splash_win = splash_new("Loading Wireshark ...");
2196 if (init_progfile_dir_error != NULL) {
2197 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2198 "Can't get pathname of Wireshark: %s.\n"
2199 "It won't be possible to capture traffic.\n"
2200 "Report this to the Wireshark developers.",
2201 init_progfile_dir_error);
2202 g_free(init_progfile_dir_error);
2205 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2207 /* Register all dissectors; we must do this before checking for the
2208 "-G" flag, as the "-G" flag dumps information registered by the
2209 dissectors, and we must do it before we read the preferences, in
2210 case any dissectors register preferences. */
2211 epan_init(register_all_protocols,register_all_protocol_handoffs,
2212 splash_update, (gpointer) splash_win,
2213 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2214 write_failure_alert_box);
2216 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2218 /* Register all tap listeners; we do this before we parse the arguments,
2219 as the "-z" argument can specify a registered tap. */
2221 /* we register the plugin taps before the other taps because
2222 stats_tree taps plugins will be registered as tap listeners
2223 by stats_tree_stat.c and need to registered before that */
2226 register_all_plugin_tap_listeners();
2229 register_all_tap_listeners();
2231 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2233 /* Now register the preferences for any non-dissector modules.
2234 We must do that before we read the preferences as well. */
2235 prefs_register_modules();
2237 prefs_p = read_configuration_files (&gdp_path, &dp_path);
2239 /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2240 #if !defined(_WIN32) && defined(G_THREADS_ENABLED) && defined USE_THREADS
2243 g_thread_init(NULL);
2245 ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2246 g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2248 #else /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2249 /* this is to keep tap extensions updating once every 3 seconds */
2250 tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2251 #endif /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2253 g_timeout_add(info_update_freq, resolv_update_cb, NULL);
2255 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2258 /* Read the profile dependent (static part) of the recent file. */
2259 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2260 /* recent lists which is done in the dynamic part. */
2261 /* We have to do this already here, so command line parameters can overwrite these values. */
2262 recent_read_profile_static(&rf_path, &rf_open_errno);
2263 if (rf_path != NULL && rf_open_errno != 0) {
2264 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2265 "Could not open recent file\n\"%s\": %s.",
2266 rf_path, strerror(rf_open_errno));
2269 cap_file_init(&cfile);
2271 /* Fill in capture options with values from the preferences */
2272 prefs_to_capture_opts();
2274 /* Now get our args */
2275 while ((opt = getopt(argc, argv, optstring)) != -1) {
2277 /*** capture option specific ***/
2278 case 'a': /* autostop criteria */
2279 case 'b': /* Ringbuffer option */
2280 case 'c': /* Capture xxx packets */
2281 case 'f': /* capture filter */
2282 case 'k': /* Start capture immediately */
2283 case 'H': /* Hide capture info dialog box */
2284 case 'i': /* Use interface xxx */
2285 case 'p': /* Don't capture in promiscuous mode */
2286 case 'Q': /* Quit after capture (just capture to file) */
2287 case 's': /* Set the snapshot (capture) length */
2288 case 'S': /* "Sync" mode: used for following file ala tail -f */
2289 case 'w': /* Write to capture file xxx */
2290 case 'y': /* Set the pcap data link type */
2292 case 'B': /* Buffer size */
2295 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2301 capture_option_specified = TRUE;
2306 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2307 case 'K': /* Kerberos keytab file */
2308 read_keytab_file(optarg);
2312 /*** all non capture option specific ***/
2314 /* Configuration profile settings were already processed just ignore them this time*/
2316 case 'D': /* Print a list of capture devices and exit */
2318 capture_opts_list_interfaces(FALSE);
2321 capture_option_specified = TRUE;
2325 case 'j': /* Search backwards for a matching packet from filter in option J */
2326 jump_backwards = TRUE;
2328 case 'g': /* Go to packet with the given packet number */
2329 go_to_packet = get_positive_int(optarg, "go to packet");
2331 case 'J': /* Jump to the first packet which matches the filter criteria */
2334 case 'l': /* Automatic scrolling in live capture mode */
2336 auto_scroll_live = TRUE;
2338 capture_option_specified = TRUE;
2342 case 'L': /* Print list of link-layer types and exit */
2344 list_link_layer_types = TRUE;
2346 capture_option_specified = TRUE;
2350 case 'm': /* Fixed-width font for the display */
2351 g_free(prefs_p->gui_font_name);
2352 prefs_p->gui_font_name = g_strdup(optarg);
2354 case 'n': /* No name resolution */
2355 g_resolv_flags = RESOLV_NONE;
2357 case 'N': /* Select what types of addresses/port #s to resolve */
2358 if (g_resolv_flags == RESOLV_ALL)
2359 g_resolv_flags = RESOLV_NONE;
2360 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2361 if (badopt != '\0') {
2362 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2367 case 'o': /* Override preference from command line */
2368 switch (prefs_set_pref(optarg)) {
2371 case PREFS_SET_SYNTAX_ERR:
2372 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2375 case PREFS_SET_NO_SUCH_PREF:
2376 /* not a preference, might be a recent setting */
2377 switch (recent_set_arg(optarg)) {
2380 case PREFS_SET_SYNTAX_ERR:
2381 /* shouldn't happen, checked already above */
2382 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2385 case PREFS_SET_NO_SUCH_PREF:
2386 case PREFS_SET_OBSOLETE:
2387 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2392 g_assert_not_reached();
2395 case PREFS_SET_OBSOLETE:
2396 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2401 g_assert_not_reached();
2405 /* Path settings were already processed just ignore them this time*/
2407 case 'r': /* Read capture file xxx */
2408 /* We may set "last_open_dir" to "cf_name", and if we change
2409 "last_open_dir" later, we free the old value, so we have to
2410 set "cf_name" to something that's been allocated. */
2411 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2412 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2413 cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2415 cf_name = g_strdup(optarg);
2418 case 'R': /* Read file filter */
2421 case 't': /* Time stamp type */
2422 if (strcmp(optarg, "r") == 0)
2423 timestamp_set_type(TS_RELATIVE);
2424 else if (strcmp(optarg, "a") == 0)
2425 timestamp_set_type(TS_ABSOLUTE);
2426 else if (strcmp(optarg, "ad") == 0)
2427 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2428 else if (strcmp(optarg, "d") == 0)
2429 timestamp_set_type(TS_DELTA);
2430 else if (strcmp(optarg, "dd") == 0)
2431 timestamp_set_type(TS_DELTA_DIS);
2432 else if (strcmp(optarg, "e") == 0)
2433 timestamp_set_type(TS_EPOCH);
2435 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2436 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2437 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2442 /* ext ops were already processed just ignore them this time*/
2445 /* We won't call the init function for the stat this soon
2446 as it would disallow MATE's fields (which are registered
2447 by the preferences set callback) from being used as
2448 part of a tap filter. Instead, we just add the argument
2449 to a list of stat arguments. */
2450 if (!process_stat_cmd_arg(optarg)) {
2451 cmdarg_err("Invalid -z argument.");
2452 cmdarg_err_cont(" -z argument must be one of :");
2453 list_stat_cmd_args();
2458 case '?': /* Bad flag - print usage message */
2466 if (cf_name != NULL) {
2468 * Input file name specified with "-r" *and* specified as a regular
2469 * command-line argument.
2471 cmdarg_err("File name specified both with -r and regular argument");
2475 * Input file name not specified with "-r", and a command-line argument
2476 * was specified; treat it as the input file name.
2478 * Yes, this is different from tshark, where non-flag command-line
2479 * arguments are a filter, but this works better on GUI desktops
2480 * where a command can be specified to be run to open a particular
2481 * file - yes, you could have "-r" as the last part of the command,
2482 * but that's a bit ugly.
2484 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2485 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2486 cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2488 cf_name = g_strdup(argv[0]);
2499 * Extra command line arguments were specified; complain.
2501 cmdarg_err("Invalid argument: %s", argv[0]);
2506 #ifndef HAVE_LIBPCAP
2507 if (capture_option_specified) {
2508 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2516 if (start_capture && list_link_layer_types) {
2517 /* Specifying *both* is bogus. */
2518 cmdarg_err("You can't specify both -L and a live capture.");
2522 if (list_link_layer_types) {
2523 /* We're supposed to list the link-layer types for an interface;
2524 did the user also specify a capture file to be read? */
2526 /* Yes - that's bogus. */
2527 cmdarg_err("You can't specify -L and a capture file to be read.");
2530 /* No - did they specify a ring buffer option? */
2531 if (global_capture_opts.multi_files_on) {
2532 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2536 /* We're supposed to do a live capture; did the user also specify
2537 a capture file to be read? */
2538 if (start_capture && cf_name) {
2539 /* Yes - that's bogus. */
2540 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2544 /* No - was the ring buffer option specified and, if so, does it make
2546 if (global_capture_opts.multi_files_on) {
2547 /* Ring buffer works only under certain conditions:
2548 a) ring buffer does not work with temporary files;
2549 b) real_time_mode and multi_files_on are mutually exclusive -
2550 real_time_mode takes precedence;
2551 c) it makes no sense to enable the ring buffer if the maximum
2552 file size is set to "infinite". */
2553 if (global_capture_opts.save_file == NULL) {
2554 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2555 global_capture_opts.multi_files_on = FALSE;
2557 /* if (global_capture_opts.real_time_mode) {
2558 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2559 global_capture_opts.multi_files_on = FALSE;
2561 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2562 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2563 /* XXX - this must be redesigned as the conditions changed */
2564 /* global_capture_opts.multi_files_on = FALSE;*/
2569 if (start_capture || list_link_layer_types) {
2570 /* Did the user specify an interface to use? */
2571 if (!capture_opts_trim_iface(&global_capture_opts,
2572 (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2577 if (list_link_layer_types) {
2578 status = capture_opts_list_link_layer_types(&global_capture_opts, FALSE);
2582 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2583 capture_opts_trim_ring_num_files(&global_capture_opts);
2584 #endif /* HAVE_LIBPCAP */
2586 /* Notify all registered modules that have had any of their preferences
2587 changed either from one of the preferences file or from the command
2588 line that their preferences have changed. */
2591 /* disabled protocols as per configuration file */
2592 if (gdp_path == NULL && dp_path == NULL) {
2593 set_disabled_protos_list();
2596 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2598 /* read in rc file from global and personal configuration paths. */
2599 rc_file = get_datafile_path(RC_FILE);
2600 gtk_rc_parse(rc_file);
2602 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2603 gtk_rc_parse(rc_file);
2610 /* close the splash screen, as we are going to open the main window now */
2611 splash_destroy(splash_win);
2613 /************************************************************************/
2614 /* Everything is prepared now, preferences and command line was read in */
2616 /* Pop up the main window. */
2617 create_main_window(pl_size, tv_size, bv_size, prefs_p);
2619 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2620 recent_read_dynamic(&rf_path, &rf_open_errno);
2621 if (rf_path != NULL && rf_open_errno != 0) {
2622 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2623 "Could not open recent file\n\"%s\": %s.",
2624 rf_path, strerror(rf_open_errno));
2627 color_filters_enable(recent.packet_list_colorize);
2629 /* rearrange all the widgets as we now have all recent settings ready for this */
2630 main_widgets_rearrange();
2632 /* Fill in column titles. This must be done after the top level window
2635 XXX - is that still true, with fixed-width columns? */
2636 #ifndef NEW_PACKET_LIST
2637 packet_list_set_column_titles();
2640 menu_recent_read_finished();
2642 menu_auto_scroll_live_changed(auto_scroll_live);
2645 switch (user_font_apply()) {
2648 case FA_FONT_NOT_RESIZEABLE:
2649 /* "user_font_apply()" popped up an alert box. */
2650 /* turn off zooming - font can't be resized */
2651 case FA_FONT_NOT_AVAILABLE:
2652 /* XXX - did we successfully load the un-zoomed version earlier?
2653 If so, this *probably* means the font is available, but not at
2654 this particular zoom level, but perhaps some other failure
2655 occurred; I'm not sure you can determine which is the case,
2657 /* turn off zooming - zoom level is unavailable */
2659 /* in any other case than FA_SUCCESS, turn off zooming */
2660 recent.gui_zoom_level = 0;
2661 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2664 dnd_init(top_level);
2666 color_filters_init();
2669 /* the window can be sized only, if it's not already shown, so do it now! */
2670 main_load_window_geometry(top_level);
2672 /* Tell the user not to run as root. */
2673 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
2674 cur_user = get_cur_username();
2675 cur_group = get_cur_groupname();
2676 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2677 "Running as user \"%s\" and group \"%s\".\n"
2678 "This could be dangerous.", cur_user, cur_group);
2681 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2682 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
2686 /* Warn the user if npf.sys isn't loaded. */
2687 if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
2688 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2689 "The NPF driver isn't running. You may have trouble\n"
2690 "capturing or listing interfaces.");
2691 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2692 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
2696 /* If we were given the name of a capture file, read it in now;
2697 we defer it until now, so that, if we can't open it, and pop
2698 up an alert box, the alert box is more likely to come up on
2699 top of the main window - but before the preference-file-error
2700 alert box, so, if we get one of those, it's more likely to come
2703 show_main_window(TRUE);
2704 if (rfilter != NULL) {
2705 if (!dfilter_compile(rfilter, &rfcode)) {
2706 bad_dfilter_alert_box(rfilter);
2707 rfilter_parse_failed = TRUE;
2710 if (!rfilter_parse_failed) {
2711 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2712 /* "cf_open()" succeeded, so it closed the previous
2713 capture file, and thus destroyed any previous read filter
2714 attached to "cf". */
2716 cfile.rfcode = rfcode;
2717 /* Open stat windows; we do so after creating the main window,
2718 to avoid GTK warnings, and after successfully opening the
2719 capture file, so we know we have something to compute stats
2720 on, and after registering all dissectors, so that MATE will
2721 have registered its field array and we can have a tap filter
2722 with one of MATE's late-registered fields as part of the
2724 start_requested_stats();
2726 /* Read the capture file. */
2727 switch (cf_read(&cfile, FALSE)) {
2731 /* Just because we got an error, that doesn't mean we were unable
2732 to read any of the file; we handle what we could get from the
2734 /* if the user told us to jump to a specific packet, do it now */
2735 if(go_to_packet != 0) {
2736 /* Jump to the specified frame number, kept for backward
2738 cf_goto_frame(&cfile, go_to_packet);
2739 } else if (jfilter != NULL) {
2740 /* try to compile given filter */
2741 if (!dfilter_compile(jfilter, &jump_to_filter)) {
2742 bad_dfilter_alert_box(jfilter);
2745 /* Filter ok, jump to the first packet matching the filter
2746 conditions. Default search direction is forward, but if
2747 option d was given, search backwards */
2748 saved_bw = cfile.sbackward;
2749 cfile.sbackward = jump_backwards;
2750 cf_find_packet_dfilter(&cfile, jump_to_filter);
2751 cfile.sbackward = saved_bw;
2756 case CF_READ_ABORTED:
2761 /* Save the name of the containing directory specified in the
2762 path name, if any; we can write over cf_name, which is a
2763 good thing, given that "get_dirname()" does write over its
2765 s = get_dirname(cf_name);
2766 set_last_open_dir(s);
2771 dfilter_free(rfcode);
2772 cfile.rfcode = NULL;
2773 show_main_window(FALSE);
2774 set_menus_for_capture_in_progress(FALSE);
2775 set_capture_if_dialog_for_capture_in_progress(FALSE);
2780 if (start_capture) {
2781 if (global_capture_opts.save_file != NULL) {
2782 /* Save the directory name for future file dialogs. */
2783 /* (get_dirname overwrites filename) */
2784 s = get_dirname(g_strdup(global_capture_opts.save_file));
2785 set_last_open_dir(s);
2788 /* "-k" was specified; start a capture. */
2789 show_main_window(TRUE);
2790 if (capture_start(&global_capture_opts)) {
2791 /* The capture started. Open stat windows; we do so after creating
2792 the main window, to avoid GTK warnings, and after successfully
2793 opening the capture file, so we know we have something to compute
2794 stats on, and after registering all dissectors, so that MATE will
2795 have registered its field array and we can have a tap filter with
2796 one of MATE's late-registered fields as part of the filter. */
2797 start_requested_stats();
2801 show_main_window(FALSE);
2802 set_menus_for_capture_in_progress(FALSE);
2803 set_capture_if_dialog_for_capture_in_progress(FALSE);
2806 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2807 if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2808 g_free(global_capture_opts.cfilter);
2809 global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2811 #else /* HAVE_LIBPCAP */
2812 show_main_window(FALSE);
2813 set_menus_for_capture_in_progress(FALSE);
2814 set_capture_if_dialog_for_capture_in_progress(FALSE);
2815 #endif /* HAVE_LIBPCAP */
2818 /* register our pid if we are being run from a U3 device */
2821 profile_store_persconffiles (FALSE);
2823 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
2825 /* we'll enter the GTK loop now and hand the control over to GTK ... */
2827 /* ... back from GTK, we're going down now! */
2829 /* deregister our pid */
2830 u3_deregister_pid();
2834 #ifdef HAVE_AIRPDCAP
2835 AirPDcapDestroyContext(&airpdcap_ctx);
2839 /* hide the (unresponsive) main window, while asking the user to close the console window */
2840 gtk_widget_hide(top_level);
2842 /* Shutdown windows sockets */
2845 /* For some unknown reason, the "atexit()" call in "create_console()"
2846 doesn't arrange that "destroy_console()" be called when we exit,
2847 so we call it here if a console was created. */
2856 /* We build this as a GUI subsystem application on Win32, so
2857 "WinMain()", not "main()", gets called.
2859 Hack shamelessly stolen from the Win32 port of the GIMP. */
2861 #define _stdcall __attribute__((stdcall))
2865 WinMain (struct HINSTANCE__ *hInstance,
2866 struct HINSTANCE__ *hPrevInstance,
2870 INITCOMMONCONTROLSEX comm_ctrl;
2872 /* Initialize our controls. Required for native Windows file dialogs. */
2873 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
2874 comm_ctrl.dwSize = sizeof(comm_ctrl);
2875 /* Includes the animate, header, hot key, list view, progress bar,
2876 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
2879 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
2880 InitCommonControlsEx(&comm_ctrl);
2882 /* RichEd20.DLL is needed for filter entries. */
2883 LoadLibrary(_T("riched20.dll"));
2885 has_console = FALSE;
2886 return main (__argc, __argv);
2889 /* The code to create and desstroy console windows should not be necessary,
2890 at least as I read the GLib source code, as it looks as if GLib is, on
2891 Win32, *supposed* to create a console window into which to display its
2894 That doesn't happen, however. I suspect there's something completely
2895 broken about that code in GLib-for-Win32, and that it may be related
2896 to the breakage that forces us to just call "printf()" on the message
2897 rather than passing the message on to "g_log_default_handler()"
2898 (which is the routine that does the aforementioned non-functional
2899 console window creation). */
2902 * If this application has no console window to which its standard output
2903 * would go, create one.
2906 create_console(void)
2908 if (stdin_capture) {
2909 /* We've been handed "-i -". Don't mess with stdio. */
2914 /* We have no console to which to print the version string, so
2915 create one and make it the standard input, output, and error. */
2916 if (!AllocConsole())
2917 return; /* couldn't create console */
2919 ws_freopen("CONIN$", "r", stdin);
2920 ws_freopen("CONOUT$", "w", stdout);
2921 ws_freopen("CONOUT$", "w", stderr);
2923 /* Well, we have a console now. */
2926 /* Now register "destroy_console()" as a routine to be called just
2927 before the application exits, so that we can destroy the console
2928 after the user has typed a key (so that the console doesn't just
2929 disappear out from under them, giving the user no chance to see
2930 the message(s) we put in there). */
2931 atexit(destroy_console);
2933 SetConsoleTitle(_T("Wireshark Debug Console"));
2938 destroy_console(void)
2941 printf("\n\nPress any key to exit\n");
2950 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
2951 const char *message, gpointer user_data _U_)
2958 /* ignore log message, if log_level isn't interesting based
2959 upon the console log preferences.
2960 If the preferences haven't been loaded loaded yet, display the
2963 The default console_log_level preference value is such that only
2964 ERROR, CRITICAL and WARNING level messages are processed;
2965 MESSAGE, INFO and DEBUG level messages are ignored. */
2966 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
2967 prefs.console_log_level != 0) {
2972 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
2973 /* the user wants a console or the application will terminate immediately */
2977 /* For some unknown reason, the above doesn't appear to actually cause
2978 anything to be sent to the standard output, so we'll just splat the
2979 message out directly, just to make sure it gets out. */
2981 switch(log_level & G_LOG_LEVEL_MASK) {
2982 case G_LOG_LEVEL_ERROR:
2985 case G_LOG_LEVEL_CRITICAL:
2988 case G_LOG_LEVEL_WARNING:
2991 case G_LOG_LEVEL_MESSAGE:
2994 case G_LOG_LEVEL_INFO:
2997 case G_LOG_LEVEL_DEBUG:
3001 fprintf(stderr, "unknown log_level %u\n", log_level);
3003 g_assert_not_reached();
3006 /* create a "timestamp" */
3008 today = localtime(&curr);
3010 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3011 today->tm_hour, today->tm_min, today->tm_sec,
3012 log_domain != NULL ? log_domain : "",
3015 if(log_level & G_LOG_LEVEL_ERROR) {
3016 /* wait for a key press before the following error handler will terminate the program
3017 this way the user at least can read the error message */
3018 printf("\n\nPress any key to exit\n");
3022 /* XXX - on UN*X, should we just use g_log_default_handler()?
3023 We want the error messages to go to the standard output;
3024 on Mac OS X, that will cause them to show up in various
3025 per-user logs accessible through Console (details depend
3026 on whether you're running 10.0 through 10.4 or running
3027 10.5 and later), and, on other UN*X desktop environments,
3028 if they don't show up in some form of console log, that's
3029 a deficiency in that desktop environment. (Too bad
3030 Windows doesn't set the standard output and error for
3031 GUI apps to something that shows up in such a log.) */
3032 g_log_default_handler(log_domain, log_level, message, user_data);
3039 * Helper for main_widgets_rearrange()
3041 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3042 gtk_container_remove(GTK_CONTAINER(data), widget);
3045 static GtkWidget *main_widget_layout(gint layout_content)
3047 switch(layout_content) {
3048 case(layout_pane_content_none):
3050 case(layout_pane_content_plist):
3052 case(layout_pane_content_pdetails):
3054 case(layout_pane_content_pbytes):
3055 return byte_nb_ptr_gbl;
3057 g_assert_not_reached();
3064 * Rearrange the main window widgets
3066 void main_widgets_rearrange(void) {
3067 GtkWidget *first_pane_widget1, *first_pane_widget2;
3068 GtkWidget *second_pane_widget1, *second_pane_widget2;
3069 gboolean split_top_left;
3071 /* be a bit faster */
3072 gtk_widget_hide(main_vbox);
3074 /* be sure we don't lose a widget while rearranging */
3075 g_object_ref(G_OBJECT(menubar));
3076 g_object_ref(G_OBJECT(main_tb));
3077 g_object_ref(G_OBJECT(filter_tb));
3079 g_object_ref(G_OBJECT(airpcap_tb));
3081 g_object_ref(G_OBJECT(pkt_scrollw));
3082 g_object_ref(G_OBJECT(tv_scrollw));
3083 g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3084 g_object_ref(G_OBJECT(statusbar));
3085 g_object_ref(G_OBJECT(main_pane_v1));
3086 g_object_ref(G_OBJECT(main_pane_v2));
3087 g_object_ref(G_OBJECT(main_pane_h1));
3088 g_object_ref(G_OBJECT(main_pane_h2));
3089 g_object_ref(G_OBJECT(welcome_pane));
3091 /* empty all containers participating */
3092 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3093 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3094 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3095 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3096 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3098 statusbar_widgets_emptying(statusbar);
3100 /* add the menubar always at the top */
3101 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3104 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3106 /* filter toolbar in toolbar area */
3107 if (!prefs.filter_toolbar_show_in_statusbar) {
3108 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3112 /* airpcap toolbar */
3113 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3116 /* fill the main layout panes */
3117 switch(prefs.gui_layout_type) {
3118 case(layout_type_5):
3119 main_first_pane = main_pane_v1;
3120 main_second_pane = main_pane_v2;
3121 split_top_left = FALSE;
3123 case(layout_type_2):
3124 main_first_pane = main_pane_v1;
3125 main_second_pane = main_pane_h1;
3126 split_top_left = FALSE;
3128 case(layout_type_1):
3129 main_first_pane = main_pane_v1;
3130 main_second_pane = main_pane_h1;
3131 split_top_left = TRUE;
3133 case(layout_type_4):
3134 main_first_pane = main_pane_h1;
3135 main_second_pane = main_pane_v1;
3136 split_top_left = FALSE;
3138 case(layout_type_3):
3139 main_first_pane = main_pane_h1;
3140 main_second_pane = main_pane_v1;
3141 split_top_left = TRUE;
3143 case(layout_type_6):
3144 main_first_pane = main_pane_h1;
3145 main_second_pane = main_pane_h2;
3146 split_top_left = FALSE;
3149 main_first_pane = NULL;
3150 main_second_pane = NULL;
3151 split_top_left = FALSE;
3152 g_assert_not_reached();
3154 if (split_top_left) {
3155 first_pane_widget1 = main_second_pane;
3156 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3157 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3158 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3160 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3161 first_pane_widget2 = main_second_pane;
3162 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3163 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3165 if (first_pane_widget1 != NULL)
3166 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3167 if (first_pane_widget2 != NULL)
3168 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3169 if (second_pane_widget1 != NULL)
3170 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3171 if (second_pane_widget2 != NULL)
3172 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3174 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3177 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3180 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3182 /* filter toolbar in statusbar hbox */
3183 if (prefs.filter_toolbar_show_in_statusbar) {
3184 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3188 /* airpcap toolbar */
3189 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3192 /* statusbar widgets */
3193 statusbar_widgets_pack(statusbar);
3195 /* hide widgets on users recent settings */
3196 main_widgets_show_or_hide();
3198 gtk_widget_show(main_vbox);
3202 is_widget_visible(GtkWidget *widget, gpointer data)
3204 gboolean *is_visible = data;
3207 if (GTK_WIDGET_VISIBLE(widget))
3214 main_widgets_show_or_hide(void)
3216 gboolean main_second_pane_show;
3218 if (recent.main_toolbar_show) {
3219 gtk_widget_show(main_tb);
3221 gtk_widget_hide(main_tb);
3224 statusbar_widgets_show_or_hide(statusbar);
3226 if (recent.filter_toolbar_show) {
3227 gtk_widget_show(filter_tb);
3229 gtk_widget_hide(filter_tb);
3233 if (recent.airpcap_toolbar_show) {
3234 gtk_widget_show(airpcap_tb);
3236 gtk_widget_hide(airpcap_tb);
3240 if (recent.packet_list_show && have_capture_file) {
3241 gtk_widget_show(pkt_scrollw);
3243 gtk_widget_hide(pkt_scrollw);
3246 if (recent.tree_view_show && have_capture_file) {
3247 gtk_widget_show(tv_scrollw);
3249 gtk_widget_hide(tv_scrollw);
3252 if (recent.byte_view_show && have_capture_file) {
3253 gtk_widget_show(byte_nb_ptr_gbl);
3255 gtk_widget_hide(byte_nb_ptr_gbl);
3258 if (have_capture_file) {
3259 gtk_widget_show(main_first_pane);
3261 gtk_widget_hide(main_first_pane);
3265 * Is anything in "main_second_pane" visible?
3266 * If so, show it, otherwise hide it.
3268 main_second_pane_show = FALSE;
3269 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3270 &main_second_pane_show);
3271 if (main_second_pane_show) {
3272 gtk_widget_show(main_second_pane);
3274 gtk_widget_hide(main_second_pane);
3277 if (!have_capture_file) {
3279 gtk_widget_show(welcome_pane);
3282 gtk_widget_hide(welcome_pane);
3285 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3286 #ifndef NEW_PACKET_LIST
3287 packet_list_freeze ();
3288 packet_list_thaw ();
3293 /* called, when the window state changes (minimized, maximized, ...) */
3295 window_state_event_cb (GtkWidget *widget _U_,
3299 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3301 if( (event->type) == (GDK_WINDOW_STATE)) {
3302 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3303 /* we might have dialogs popped up while we where iconified,
3305 display_queued_messages();
3313 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3315 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3317 if (event->keyval == GDK_F8) {
3318 #ifdef NEW_PACKET_LIST
3319 new_packet_list_next();
3324 } else if (event->keyval == GDK_F7) {
3325 #ifdef NEW_PACKET_LIST
3326 new_packet_list_prev();
3331 } else if (event->state & NO_SHIFT_MOD_MASK) {
3332 return FALSE; /* Skip control, alt, and other modifiers */
3334 * A comment in gdkkeysyms.h says that it's autogenerated from
3335 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3336 * don't explicitly say so, isprint() should work as expected
3339 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3340 /* Forward the keypress on to the display filter entry */
3341 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3342 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3343 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3351 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3353 GtkAccelGroup *accel;
3356 /* use user-defined title if preference is set */
3357 title = create_user_window_title("The Wireshark Network Analyzer");
3360 top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
3363 gtk_widget_set_name(top_level, "main window");
3364 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3366 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3367 G_CALLBACK(window_state_event_cb), NULL);
3368 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3369 G_CALLBACK(top_level_key_pressed_cb), NULL );
3371 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3372 main_vbox = gtk_vbox_new(FALSE, 1);
3373 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
3374 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3375 gtk_widget_show(main_vbox);
3378 menubar = main_menu_new(&accel);
3380 #ifdef HAVE_IGE_MAC_INTEGRATION
3381 /* MacOS X native menus are created and displayed by main_menu_new() */
3382 if(!prefs_p->gui_macosx_style) {
3384 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3385 gtk_widget_show(menubar);
3386 #ifdef HAVE_IGE_MAC_INTEGRATION
3391 main_tb = toolbar_new();
3392 gtk_widget_show (main_tb);
3394 /* Filter toolbar */
3395 filter_tb = filter_toolbar_new();
3398 #ifdef NEW_PACKET_LIST
3399 pkt_scrollw = new_packet_list_create();
3400 gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3401 gtk_widget_show_all(pkt_scrollw);
3403 pkt_scrollw = packet_list_new(prefs_p);
3404 gtk_widget_set_size_request(packet_list, -1, pl_size);
3405 gtk_widget_show(pkt_scrollw);
3409 tv_scrollw = main_tree_view_new(prefs_p, &tree_view_gbl);
3410 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3411 gtk_widget_show(tv_scrollw);
3413 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3414 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3415 g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3416 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3417 gtk_widget_show(tree_view_gbl);
3420 byte_nb_ptr_gbl = byte_view_new();
3421 gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3422 gtk_widget_show(byte_nb_ptr_gbl);
3424 g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3425 g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3427 /* Panes for the packet list, tree, and byte view */
3428 main_pane_v1 = gtk_vpaned_new();
3429 gtk_widget_show(main_pane_v1);
3430 main_pane_v2 = gtk_vpaned_new();
3431 gtk_widget_show(main_pane_v2);
3432 main_pane_h1 = gtk_hpaned_new();
3433 gtk_widget_show(main_pane_h1);
3434 main_pane_h2 = gtk_hpaned_new();
3435 gtk_widget_show(main_pane_h2);
3437 airpcap_tb = airpcap_toolbar_new();
3438 gtk_widget_show(airpcap_tb);
3441 statusbar = statusbar_new();
3442 gtk_widget_show(statusbar);
3444 /* Pane for the welcome screen */
3445 welcome_pane = welcome_new();
3446 gtk_widget_show(welcome_pane);
3450 show_main_window(gboolean doing_work)
3452 main_set_for_capture_file(doing_work);
3454 /*** we have finished all init things, show the main window ***/
3455 gtk_widget_show(top_level);
3457 /* the window can be maximized only, if it's visible, so do it after show! */
3458 main_load_window_geometry(top_level);
3460 /* process all pending GUI events before continue */
3461 while (gtk_events_pending()) gtk_main_iteration();
3463 /* Pop up any queued-up alert boxes. */
3464 display_queued_messages();
3466 /* Move the main window to the front, in case it isn't already there */
3467 gdk_window_raise(top_level->window);
3470 airpcap_toolbar_show(airpcap_tb);
3471 #endif /* HAVE_AIRPCAP */
3474 /* Fill in capture options with values from the preferences */
3476 prefs_to_capture_opts(void)
3479 /* Set promiscuous mode from the preferences setting. */
3480 /* the same applies to other preferences settings as well. */
3481 global_capture_opts.promisc_mode = prefs.capture_prom_mode;
3482 global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
3483 global_capture_opts.show_info = prefs.capture_show_info;
3484 global_capture_opts.real_time_mode = prefs.capture_real_time;
3485 auto_scroll_live = prefs.capture_auto_scroll;
3486 #endif /* HAVE_LIBPCAP */
3488 /* Set the name resolution code's flags from the preferences. */
3489 g_resolv_flags = prefs.name_resolve;
3493 /* Change configuration profile */
3494 void change_configuration_profile (const gchar *profile_name)
3496 char *gdp_path, *dp_path;
3500 /* First check if profile exists */
3501 if (!profile_exists(profile_name)) {
3505 /* Get the current geometry, before writing it to disk */
3506 main_save_window_geometry(top_level);
3508 if (profile_exists(get_profile_name())) {
3509 /* Write recent file for profile we are leaving, if it still exists */
3510 write_profile_recent();
3513 /* Set profile name and update the status bar */
3514 set_profile_name (profile_name);
3515 profile_bar_update ();
3517 /* Reset current preferences and apply the new */
3521 (void) read_configuration_files (&gdp_path, &dp_path);
3523 recent_read_profile_static(&rf_path, &rf_open_errno);
3524 if (rf_path != NULL && rf_open_errno != 0) {
3525 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3526 "Could not open common recent file\n\"%s\": %s.",
3527 rf_path, strerror(rf_open_errno));
3529 timestamp_set_type (recent.gui_time_format);
3530 color_filters_enable(recent.packet_list_colorize);
3532 prefs_to_capture_opts();
3535 /* Update window view and redraw the toolbar */
3536 update_main_window_name();
3537 toolbar_redraw_all();
3539 /* Enable all protocols and disable from the disabled list */
3541 if (gdp_path == NULL && dp_path == NULL) {
3542 set_disabled_protos_list();
3545 /* Reload color filters */
3546 color_filters_reload();
3548 /* Reload list of interfaces on welcome page */
3549 welcome_if_panel_reload();
3551 /* Recreate the packet list according to new preferences */
3552 #ifdef NEW_PACKET_LIST
3553 new_packet_list_recreate ();
3555 packet_list_recreate ();
3557 cfile.cinfo.columns_changed = FALSE; /* Reset value */
3560 /* Update menus with new recent values */
3561 menu_recent_read_finished();
3563 /* Reload pane geometry, must be done after recreating the list */
3564 main_pane_load_window_geometry();
3567 /** redissect packets and update UI */
3568 void redissect_packets(void)
3570 cf_redissect_packets(&cfile);
3571 status_expert_update();