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 is_address_column (gint column)
505 if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
506 (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
507 (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
508 (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
509 strlen(cfile.cinfo.col_expr.col_expr_val[column]))
518 get_ip_address_list_from_packet_list_row(gpointer data)
520 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
521 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
524 GList *addr_list = NULL;
528 #ifdef NEW_PACKET_LIST
529 fdata = (frame_data *) new_packet_list_get_row_data(row);
531 fdata = (frame_data *) packet_list_get_row_data(row);
537 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
538 cfile.pd, fdata->cap_len, &err, &err_info))
540 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
541 cf_read_error_message(err, err_info), cfile.filename);
545 epan_dissect_init(&edt, FALSE, FALSE);
546 col_custom_prime_edt(&edt, &cfile.cinfo);
548 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
549 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
551 /* First check selected column */
552 if (is_address_column (column)) {
553 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
556 for (col = 0; col < cfile.cinfo.num_cols; col++) {
557 /* Then check all columns except the selected */
558 if ((col != column) && (is_address_column (col))) {
559 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
563 epan_dissect_cleanup(&edt);
570 get_filter_from_packet_list_row_and_column(gpointer data)
572 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
573 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
579 #ifdef NEW_PACKET_LIST
580 fdata = (frame_data *) new_packet_list_get_row_data(row);
582 fdata = (frame_data *) packet_list_get_row_data(row);
588 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
589 cfile.pd, fdata->cap_len, &err, &err_info)) {
590 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
591 cf_read_error_message(err, err_info), cfile.filename);
594 /* proto tree, visible. We need a proto tree if there's custom columns */
595 epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
596 col_custom_prime_edt(&edt, &cfile.cinfo);
598 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata,
600 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
602 if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
603 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
604 /* leak a little but safer than ep_ here */
605 if (cfile.cinfo.col_fmt[column] == COL_CUSTOM) {
606 header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[column]);
607 if (hfi->parent == -1) {
609 buf = se_strdup(cfile.cinfo.col_expr.col_expr[column]);
610 } else if (hfi->type == FT_STRING) {
611 /* Custom string, add quotes */
612 buf = se_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
613 cfile.cinfo.col_expr.col_expr_val[column]);
617 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
618 cfile.cinfo.col_expr.col_expr_val[column]);
622 epan_dissect_cleanup(&edt);
629 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
631 match_selected_cb_do(data,
633 get_filter_from_packet_list_row_and_column(data));
636 /* This function allows users to right click in the details window and copy the text
637 * information to the operating systems clipboard.
639 * We first check to see if a string representation is setup in the tree and then
640 * read the string. If not available then we try to grab the value. If all else
641 * fails we display a message to the user to indicate the copy could not be completed.
644 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
646 GString *gtk_text_str = g_string_new("");
647 char labelstring[256];
648 char *stringpointer = labelstring;
652 case COPY_SELECTED_DESCRIPTION:
653 if (cfile.finfo_selected->rep->representation != 0) {
654 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
657 case COPY_SELECTED_FIELDNAME:
658 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
659 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
662 case COPY_SELECTED_VALUE:
663 if (cfile.edt !=0 ) {
664 g_string_append(gtk_text_str,
665 get_node_field_value(cfile.finfo_selected, cfile.edt));
672 if (gtk_text_str->len == 0) {
673 /* If no representation then... Try to read the value */
674 proto_item_fill_label(cfile.finfo_selected, stringpointer);
675 g_string_append(gtk_text_str, stringpointer);
678 if (gtk_text_str->len == 0) {
679 /* Could not get item so display error msg */
680 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
682 /* Copy string to clipboard */
683 copy_to_clipboard(gtk_text_str);
685 g_string_free(gtk_text_str, TRUE); /* Free the memory */
689 /* mark as reference time frame */
691 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
695 frame->flags.ref_time=1;
697 frame->flags.ref_time=0;
699 cf_reftime_packets(&cfile);
700 #ifdef NEW_PACKET_LIST
701 new_packet_list_queue_draw();
706 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
710 timestamp_set_type(TS_RELATIVE);
711 recent.gui_time_format = TS_RELATIVE;
712 #ifdef NEW_PACKET_LIST
713 cf_timestamp_auto_precision(&cfile);
714 new_packet_list_queue_draw();
716 cf_change_time_formats(&cfile);
722 g_assert_not_reached();
725 if (cfile.current_frame) {
726 set_frame_reftime(!cfile.current_frame->flags.ref_time,
727 cfile.current_frame, cfile.current_row);
733 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
735 static GtkWidget *reftime_dialog = NULL;
739 if (cfile.current_frame) {
740 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
741 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
742 "%sSwitch to the appropriate Time Display Format?%s\n\n"
743 "Time References don't work well with the currently selected Time Display Format.\n\n"
744 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
745 simple_dialog_primary_start(), simple_dialog_primary_end());
746 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
748 set_frame_reftime(!cfile.current_frame->flags.ref_time,
749 cfile.current_frame, cfile.current_row);
753 case REFTIME_FIND_NEXT:
754 find_previous_next_frame_with_filter("frame.ref_time", FALSE);
756 case REFTIME_FIND_PREV:
757 find_previous_next_frame_with_filter("frame.ref_time", TRUE);
763 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
765 find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
769 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
771 find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
775 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
778 gchar *help_str = NULL;
779 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
781 gboolean has_blurb = FALSE;
782 guint length = 0, byte_len;
783 GtkWidget *byte_view;
784 const guint8 *byte_data;
789 /* if nothing is selected */
790 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
793 * Which byte view is displaying the current protocol tree
796 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
797 if (byte_view == NULL)
800 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
801 if (byte_data == NULL)
804 cf_unselect_field(&cfile);
805 packet_hex_print(byte_view, byte_data,
806 cfile.current_frame, NULL, byte_len);
809 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
812 set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
814 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
815 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
816 g_assert(byte_data != NULL);
818 cfile.finfo_selected = finfo;
819 set_menus_for_selected_tree_row(&cfile);
822 if (finfo->hfinfo->blurb != NULL &&
823 finfo->hfinfo->blurb[0] != '\0') {
825 length = (guint) strlen(finfo->hfinfo->blurb);
827 length = (guint) strlen(finfo->hfinfo->name);
829 finfo_length = finfo->length + finfo->appendix_length;
831 if (finfo_length == 0) {
833 } else if (finfo_length == 1) {
834 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
836 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
838 statusbar_pop_field_msg(); /* get rid of current help msg */
840 help_str = g_strdup_printf(" %s (%s)%s",
841 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
842 finfo->hfinfo->abbrev, len_str);
843 statusbar_push_field_msg(help_str);
847 * Don't show anything if the field name is zero-length;
848 * the pseudo-field for "proto_tree_add_text()" is such
849 * a field, and we don't want "Text (text)" showing up
850 * on the status line if you've selected such a field.
852 * XXX - there are zero-length fields for which we *do*
853 * want to show the field name.
855 * XXX - perhaps the name and abbrev field should be null
856 * pointers rather than null strings for that pseudo-field,
857 * but we'd have to add checks for null pointers in some
858 * places if we did that.
860 * Or perhaps protocol tree items added with
861 * "proto_tree_add_text()" should have -1 as the field index,
862 * with no pseudo-field being used, but that might also
863 * require special checks for -1 to be added.
865 statusbar_push_field_msg("");
868 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
872 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
874 collapse_all_tree(cfile.edt->tree, tree_view_gbl);
877 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
879 expand_all_tree(cfile.edt->tree, tree_view_gbl);
882 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
884 if (cfile.finfo_selected) {
885 column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
886 cfile.finfo_selected->hfinfo->abbrev);
887 /* Recreate the packet list according to new preferences */
888 #ifdef NEW_PACKET_LIST
889 new_packet_list_recreate ();
891 packet_list_recreate ();
893 if (!prefs.gui_use_pref_save) {
896 cfile.cinfo.columns_changed = FALSE; /* Reset value */
900 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
903 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
905 /* the mouse position is at an entry, expand that one */
906 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
907 gtk_tree_path_free(path);
911 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
912 if (cfile.edt->tree) {
913 guint32 tmp = g_resolv_flags;
914 g_resolv_flags = RESOLV_ALL;
915 proto_tree_draw(cfile.edt->tree, tree_view_gbl);
916 g_resolv_flags = tmp;
921 main_set_for_capture_file(gboolean have_capture_file_in)
923 have_capture_file = have_capture_file_in;
925 main_widgets_show_or_hide();
931 /* get the current geometry, before writing it to disk */
932 main_save_window_geometry(top_level);
934 /* write user's recent file to disk
935 * It is no problem to write this file, even if we do not quit */
936 write_profile_recent();
939 /* XXX - should we check whether the capture file is an
940 unsaved temporary file for a live capture and, if so,
941 pop up a "do you want to exit without saving the capture
942 file?" dialog, and then just return, leaving said dialog
943 box to forcibly quit if the user clicks "OK"?
945 If so, note that this should be done in a subroutine that
946 returns TRUE if we do so, and FALSE otherwise, and if it
947 returns TRUE we should return TRUE without nuking anything.
949 Note that, if we do that, we might also want to check if
950 an "Update list of packets in real time" capture is in
951 progress and, if so, ask whether they want to terminate
952 the capture and discard it, and return TRUE, before nuking
953 any child capture, if they say they don't want to do so. */
956 /* Nuke any child capture in progress. */
957 capture_kill_child(&global_capture_opts);
960 /* Are we in the middle of reading a capture? */
961 if (cfile.state == FILE_READ_IN_PROGRESS) {
962 /* Yes, so we can't just close the file and quit, as
963 that may yank the rug out from under the read in
964 progress; instead, just set the state to
965 "FILE_READ_ABORTED" and return - the code doing the read
966 will check for that and, if it sees that, will clean
968 cfile.state = FILE_READ_ABORTED;
970 /* Say that the window should *not* be deleted;
971 that'll be done by the code that cleans up. */
974 /* Close any capture file we have open; on some OSes, you
975 can't unlink a temporary capture file if you have it
977 "cf_close()" will unlink it after closing it if
978 it's a temporary file.
980 We do this here, rather than after the main loop returns,
981 as, after the main loop returns, the main window may have
982 been destroyed (if this is called due to a "destroy"
983 even on the main window rather than due to the user
984 selecting a menu item), and there may be a crash
985 or other problem when "cf_close()" tries to
986 clean up stuff in the main window.
988 XXX - is there a better place to put this?
989 Or should we have a routine that *just* closes the
990 capture file, and doesn't do anything with the UI,
991 which we'd call here, and another routine that
992 calls that routine and also cleans up the UI, which
993 we'd call elsewhere? */
996 /* Exit by leaving the main loop, so that any quit functions
997 we registered get called. */
1000 /* Say that the window should be deleted. */
1006 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1010 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1011 gtk_window_present(GTK_WINDOW(top_level));
1012 /* user didn't saved his current file, ask him */
1013 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1014 "%sSave capture file before program quit?%s\n\n"
1015 "If you quit the program without saving, your capture data will be discarded.",
1016 simple_dialog_primary_start(), simple_dialog_primary_end());
1017 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1020 /* unchanged file, just exit */
1021 /* "main_do_quit()" indicates whether the main window should be deleted. */
1022 return main_do_quit();
1028 main_pane_load_window_geometry(void)
1030 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1031 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1032 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
1033 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1039 main_load_window_geometry(GtkWidget *widget)
1041 window_geometry_t geom;
1043 geom.set_pos = prefs.gui_geometry_save_position;
1044 geom.x = recent.gui_geometry_main_x;
1045 geom.y = recent.gui_geometry_main_y;
1046 geom.set_size = prefs.gui_geometry_save_size;
1047 if (recent.gui_geometry_main_width > 0 &&
1048 recent.gui_geometry_main_height > 0) {
1049 geom.width = recent.gui_geometry_main_width;
1050 geom.height = recent.gui_geometry_main_height;
1051 geom.set_maximized = prefs.gui_geometry_save_maximized;
1053 /* We assume this means the width and height weren't set in
1054 the "recent" file (or that there is no "recent" file),
1055 and weren't set to a default value, so we don't set the
1056 size. (The "recent" file code rejects non-positive width
1057 and height values.) */
1058 geom.set_size = FALSE;
1060 geom.maximized = recent.gui_geometry_main_maximized;
1062 window_set_geometry(widget, &geom);
1064 main_pane_load_window_geometry();
1065 statusbar_load_window_geometry();
1070 main_save_window_geometry(GtkWidget *widget)
1072 window_geometry_t geom;
1074 window_get_geometry(widget, &geom);
1076 if (prefs.gui_geometry_save_position) {
1077 recent.gui_geometry_main_x = geom.x;
1078 recent.gui_geometry_main_y = geom.y;
1081 if (prefs.gui_geometry_save_size) {
1082 recent.gui_geometry_main_width = geom.width;
1083 recent.gui_geometry_main_height = geom.height;
1086 if(prefs.gui_geometry_save_maximized) {
1087 recent.gui_geometry_main_maximized = geom.maximized;
1090 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1091 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1092 statusbar_save_window_geometry();
1095 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1099 /* save file first */
1100 file_save_as_cmd(after_save_exit, NULL);
1102 case(ESD_BTN_QUIT_DONT_SAVE):
1105 case(ESD_BTN_CANCEL):
1108 g_assert_not_reached();
1113 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1117 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1118 /* user didn't saved his current file, ask him */
1119 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1120 "%sSave capture file before program quit?%s\n\n"
1121 "If you quit the program without saving, your capture data will be discarded.",
1122 simple_dialog_primary_start(), simple_dialog_primary_end());
1123 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1125 /* unchanged file, just exit */
1131 print_usage(gboolean print_ver) {
1141 fprintf(output, "Wireshark " VERSION "%s\n"
1142 "Interactively dump and analyze network traffic.\n"
1143 "See http://www.wireshark.org for more information.\n"
1146 wireshark_svnversion, get_copyright_info());
1150 fprintf(output, "\n");
1151 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1152 fprintf(output, "\n");
1155 fprintf(output, "Capture interface:\n");
1156 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1157 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1158 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1159 fprintf(output, " -p don't capture in promiscuous mode\n");
1160 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1161 fprintf(output, " -Q quit Wireshark after capturing\n");
1162 fprintf(output, " -S update packet display when new packets are captured\n");
1163 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1165 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1167 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1168 fprintf(output, " -D print list of interfaces and exit\n");
1169 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1170 fprintf(output, "\n");
1171 fprintf(output, "Capture stop conditions:\n");
1172 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1173 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1174 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1175 fprintf(output, " files:NUM - stop after NUM files\n");
1176 /*fprintf(output, "\n");*/
1177 fprintf(output, "Capture output:\n");
1178 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1179 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1180 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1181 #endif /* HAVE_LIBPCAP */
1183 /*fprintf(output, "\n");*/
1184 fprintf(output, "Input file:\n");
1185 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1187 fprintf(output, "\n");
1188 fprintf(output, "Processing:\n");
1189 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1190 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1191 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1193 fprintf(output, "\n");
1194 fprintf(output, "User interface:\n");
1195 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1196 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1197 fprintf(output, " -J <jump filter> jump to the first packet matching the (display) filter\n");
1198 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
1199 fprintf(output, " -m <font> set the font name used for most text\n");
1200 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1201 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1202 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1204 fprintf(output, "\n");
1205 fprintf(output, "Output:\n");
1206 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1208 fprintf(output, "\n");
1209 fprintf(output, "Miscellaneous:\n");
1210 fprintf(output, " -h display this help and exit\n");
1211 fprintf(output, " -v display version info and exit\n");
1212 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1213 fprintf(output, " persdata:path - personal data files\n");
1214 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1215 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1217 fprintf(output, " --display=DISPLAY X display to use\n");
1232 printf(PACKAGE " " VERSION "%s\n"
1239 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1240 runtime_info_str->str);
1248 * Report an error in command-line arguments.
1249 * Creates a console on Windows.
1250 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1251 * terminal isn't the standard error?
1254 cmdarg_err(const char *fmt, ...)
1262 fprintf(stderr, "wireshark: ");
1263 vfprintf(stderr, fmt, ap);
1264 fprintf(stderr, "\n");
1269 * Report additional information for an error in command-line arguments.
1270 * Creates a console on Windows.
1271 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1272 * terminal isn't the standard error?
1275 cmdarg_err_cont(const char *fmt, ...)
1283 vfprintf(stderr, fmt, ap);
1284 fprintf(stderr, "\n");
1288 #if defined(_WIN32) || ! defined USE_THREADS
1290 Once every 3 seconds we get a callback here which we use to update
1291 the tap extensions. Since Gtk1 is single threaded we dont have to
1292 worry about any locking or critical regions.
1295 tap_update_cb(gpointer data _U_)
1297 draw_tap_listeners(FALSE);
1301 /* Restart the tap update display timer with new configured interval */
1302 void reset_tap_update_timer(void)
1304 g_source_remove(tap_update_timer_id);
1305 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1310 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1311 use threads all update_thread_mutex can be dropped and protect/unprotect
1312 would just be empty functions.
1314 This allows gtk2-rpcstat.c and friends to be copied unmodified to
1315 gtk1-wireshark and it will just work.
1317 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1319 update_thread(gpointer data _U_)
1323 g_get_current_time(&tv1);
1324 g_static_mutex_lock(&update_thread_mutex);
1325 gdk_threads_enter();
1326 draw_tap_listeners(FALSE);
1327 gdk_threads_leave();
1328 g_static_mutex_unlock(&update_thread_mutex);
1330 g_get_current_time(&tv2);
1332 /* Assuming it took less than configured time to update tap listeners... */
1333 if( (tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) >
1334 (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1335 /* Wait for remainder of configured time */
1336 g_usleep((tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) -
1337 (tv2.tv_sec * 1000000 + tv2.tv_usec));
1344 protect_thread_critical_region(void)
1346 #if !defined(_WIN32) && defined USE_THREADS
1347 g_static_mutex_lock(&update_thread_mutex);
1351 unprotect_thread_critical_region(void)
1353 #if !defined(_WIN32) && defined USE_THREADS
1354 g_static_mutex_unlock(&update_thread_mutex);
1359 * Periodically process outstanding hostname lookups. If we have new items,
1360 * redraw the packet list and tree view.
1364 resolv_update_cb(gpointer data _U_)
1366 /* Anything new show up? */
1367 if (host_name_lookup_process(NULL)) {
1368 gdk_window_invalidate_rect(pkt_scrollw->window, NULL, TRUE);
1369 gdk_window_invalidate_rect(tv_scrollw->window, NULL, TRUE);
1372 /* Always check. Even if we don't do async lookups we could still get
1373 passive updates, e.g. from DNS packets. */
1378 /* Set the file name in the name for the main window and in the name for the main window's icon. */
1380 set_display_filename(capture_file *cf)
1384 if (!cf->is_tempfile && cf->filename) {
1385 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1386 add_menu_recent_capture_file(cf->filename);
1390 win_name = g_strdup_printf("%s - Wireshark", cf_get_display_name(cf));
1391 set_main_window_name(win_name);
1395 GtkWidget *close_dlg = NULL;
1398 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1400 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1405 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1407 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1412 main_cf_cb_file_closing(capture_file *cf)
1415 /* if we have more than 10000 packets, show a splash screen while closing */
1416 /* XXX - don't know a better way to decide whether to show or not,
1417 * as most of the time is spend in a single eth_clist_clear function,
1418 * so we can't use a progress bar here! */
1419 if(cf->count > 10000) {
1420 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1421 "%sClosing file!%s\n\nPlease wait ...",
1422 simple_dialog_primary_start(),
1423 simple_dialog_primary_end());
1424 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1427 /* Destroy all windows, which refer to the
1428 capture file we're closing. */
1429 destroy_packet_wins();
1430 file_save_as_destroy();
1432 /* Restore the standard title bar message. */
1433 set_main_window_name("The Wireshark Network Analyzer");
1435 /* Disable all menu items that make sense only if you have a capture. */
1436 set_menus_for_capture_file(NULL);
1437 set_menus_for_captured_packets(FALSE);
1438 set_menus_for_selected_packet(cf);
1439 set_menus_for_capture_in_progress(FALSE);
1440 set_capture_if_dialog_for_capture_in_progress(FALSE);
1441 set_menus_for_selected_tree_row(cf);
1443 /* Set up main window for no capture file. */
1444 main_set_for_capture_file(FALSE);
1446 main_window_update();
1450 main_cf_cb_file_closed(capture_file *cf _U_)
1452 if(close_dlg != NULL) {
1453 splash_destroy(close_dlg);
1460 main_cf_cb_file_read_started(capture_file *cf _U_)
1462 tap_dfilter_dlg_update();
1464 /* Set up main window for a capture file. */
1465 main_set_for_capture_file(TRUE);
1469 main_cf_cb_file_read_finished(capture_file *cf)
1471 set_display_filename(cf);
1473 /* Enable menu items that make sense if you have a capture file you've
1474 finished reading. */
1475 set_menus_for_capture_file(cf);
1477 /* Enable menu items that make sense if you have some captured packets. */
1478 set_menus_for_captured_packets(TRUE);
1482 static GList *icon_list_create(
1483 const char **icon16_xpm,
1484 const char **icon32_xpm,
1485 const char **icon48_xpm,
1486 const char **icon64_xpm)
1488 GList *icon_list = NULL;
1489 GdkPixbuf * pixbuf16;
1490 GdkPixbuf * pixbuf32;
1491 GdkPixbuf * pixbuf48;
1492 GdkPixbuf * pixbuf64;
1495 if(icon16_xpm != NULL) {
1496 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1498 icon_list = g_list_append(icon_list, pixbuf16);
1501 if(icon32_xpm != NULL) {
1502 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1504 icon_list = g_list_append(icon_list, pixbuf32);
1507 if(icon48_xpm != NULL) {
1508 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1510 icon_list = g_list_append(icon_list, pixbuf48);
1513 if(icon64_xpm != NULL) {
1514 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1516 icon_list = g_list_append(icon_list, pixbuf64);
1523 main_capture_set_main_window_title(capture_options *capture_opts)
1525 GString *title = g_string_new("");
1527 g_string_append(title, "Capturing ");
1528 if(capture_opts->iface) {
1529 g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1531 g_string_append(title, "- Wireshark");
1533 set_main_window_name(title->str);
1534 g_string_free(title, TRUE);
1538 main_capture_cb_capture_prepared(capture_options *capture_opts)
1540 static GList *icon_list = NULL;
1542 main_capture_set_main_window_title(capture_opts);
1544 if(icon_list == NULL) {
1545 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1547 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1549 /* Disable menu items that make no sense if you're currently running
1551 set_menus_for_capture_in_progress(TRUE);
1552 set_capture_if_dialog_for_capture_in_progress(TRUE);
1554 /* Don't set up main window for a capture file. */
1555 main_set_for_capture_file(FALSE);
1559 main_capture_cb_capture_update_started(capture_options *capture_opts)
1561 /* We've done this in "prepared" above, but it will be cleared while
1562 switching to the next multiple file. */
1563 main_capture_set_main_window_title(capture_opts);
1565 set_menus_for_capture_in_progress(TRUE);
1566 set_capture_if_dialog_for_capture_in_progress(TRUE);
1568 /* Enable menu items that make sense if you have some captured
1569 packets (yes, I know, we don't have any *yet*). */
1570 set_menus_for_captured_packets(TRUE);
1572 /* Set up main window for a capture file. */
1573 main_set_for_capture_file(TRUE);
1577 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1579 capture_file *cf = capture_opts->cf;
1580 static GList *icon_list = NULL;
1582 set_display_filename(cf);
1584 /* Enable menu items that make sense if you're not currently running
1586 set_menus_for_capture_in_progress(FALSE);
1587 set_capture_if_dialog_for_capture_in_progress(FALSE);
1589 /* Enable menu items that make sense if you have a capture file
1590 you've finished reading. */
1591 set_menus_for_capture_file(cf);
1593 /* Set up main window for a capture file. */
1594 main_set_for_capture_file(TRUE);
1596 if(icon_list == NULL) {
1597 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1599 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1601 if(global_capture_opts.quit_after_cap) {
1602 /* command line asked us to quit after the capture */
1603 /* don't pop up a dialog to ask for unsaved files etc. */
1609 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1611 /* Don't set up main window for a capture file. */
1612 main_set_for_capture_file(FALSE);
1616 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1619 capture_file *cf = capture_opts->cf;
1621 static GList *icon_list = NULL;
1623 /*set_display_filename(cf);*/
1625 /* Enable menu items that make sense if you're not currently running
1627 set_menus_for_capture_in_progress(FALSE);
1628 set_capture_if_dialog_for_capture_in_progress(FALSE);
1630 /* Restore the standard title bar message */
1631 /* (just in case we have trouble opening the capture file). */
1632 set_main_window_name("The Wireshark Network Analyzer");
1634 if(icon_list == NULL) {
1635 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1637 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1639 /* We don't have loaded the capture file, this will be done later.
1640 * For now we still have simply a blank screen. */
1642 if(global_capture_opts.quit_after_cap) {
1643 /* command line asked us to quit after the capture */
1644 /* don't pop up a dialog to ask for unsaved files etc. */
1649 #endif /* HAVE_LIBPCAP */
1652 main_cf_cb_packet_selected(gpointer data)
1654 capture_file *cf = data;
1656 /* Display the GUI protocol tree and packet bytes.
1657 XXX - why do we dump core if we call "proto_tree_draw()"
1658 before calling "add_byte_views()"? */
1659 add_main_byte_views(cf->edt);
1660 main_proto_tree_draw(cf->edt->tree);
1662 /* The user is searching for a string in the data or a hex value,
1663 * highlight the field that is found in the tree and hex displays. */
1664 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1665 highlight_field(cf->edt->tvb, cfile.search_pos,
1666 (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1667 cfile.search_pos = 0; /* Reset the position */
1670 /* A packet is selected. */
1671 set_menus_for_selected_packet(cf);
1675 main_cf_cb_packet_unselected(capture_file *cf)
1677 /* Clear out the display of that packet. */
1678 clear_tree_and_hex_views();
1680 /* No packet is selected. */
1681 set_menus_for_selected_packet(cf);
1685 main_cf_cb_field_unselected(capture_file *cf)
1687 set_menus_for_selected_tree_row(cf);
1691 main_cf_cb_file_save_reload_finished(gpointer data _U_)
1693 set_display_filename(&cfile);
1694 set_menus_for_capture_file(&cfile);
1698 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1701 case(cf_cb_file_closing):
1702 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1703 main_cf_cb_file_closing(data);
1705 case(cf_cb_file_closed):
1706 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1707 main_cf_cb_file_closed(data);
1709 case(cf_cb_file_read_started):
1710 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1711 main_cf_cb_file_read_started(data);
1713 case(cf_cb_file_read_finished):
1714 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1715 main_cf_cb_file_read_finished(data);
1717 case(cf_cb_packet_selected):
1718 main_cf_cb_packet_selected(data);
1720 case(cf_cb_packet_unselected):
1721 main_cf_cb_packet_unselected(data);
1723 case(cf_cb_field_unselected):
1724 main_cf_cb_field_unselected(data);
1726 case(cf_cb_file_save_started):
1727 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1729 case(cf_cb_file_save_finished):
1730 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1732 case(cf_cb_file_save_reload_finished):
1733 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1734 main_cf_cb_file_save_reload_finished(data);
1736 case(cf_cb_file_save_failed):
1737 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1740 g_warning("main_cf_callback: event %u unknown", event);
1741 g_assert_not_reached();
1747 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1750 case(capture_cb_capture_prepared):
1751 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1752 main_capture_cb_capture_prepared(capture_opts);
1754 case(capture_cb_capture_update_started):
1755 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1756 main_capture_cb_capture_update_started(capture_opts);
1758 case(capture_cb_capture_update_continue):
1759 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1761 case(capture_cb_capture_update_finished):
1762 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1763 main_capture_cb_capture_update_finished(capture_opts);
1765 case(capture_cb_capture_fixed_started):
1766 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1767 main_capture_cb_capture_fixed_started(capture_opts);
1769 case(capture_cb_capture_fixed_continue):
1770 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1772 case(capture_cb_capture_fixed_finished):
1773 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1774 main_capture_cb_capture_fixed_finished(capture_opts);
1776 case(capture_cb_capture_stopping):
1777 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1778 /* Beware: this state won't be called, if the capture child
1779 * closes the capturing on it's own! */
1782 g_warning("main_capture_callback: event %u unknown", event);
1783 g_assert_not_reached();
1789 get_gui_compiled_info(GString *str)
1791 get_epan_compiled_version_info(str);
1793 g_string_append(str, ", ");
1794 #ifdef HAVE_LIBPORTAUDIO
1795 #ifdef PORTAUDIO_API_1
1796 g_string_append(str, "with PortAudio <= V18");
1797 #else /* PORTAUDIO_API_1 */
1798 g_string_append(str, "with ");
1799 g_string_append(str, Pa_GetVersionText());
1800 #endif /* PORTAUDIO_API_1 */
1801 #else /* HAVE_LIBPORTAUDIO */
1802 g_string_append(str, "without PortAudio");
1803 #endif /* HAVE_LIBPORTAUDIO */
1805 g_string_append(str, ", ");
1807 get_compiled_airpcap_version(str);
1809 g_string_append(str, "without AirPcap");
1811 #ifdef NEW_PACKET_LIST
1812 g_string_append(str, ", with new_packet_list");
1817 get_gui_runtime_info(GString *str)
1820 g_string_append(str, ", ");
1821 get_runtime_airpcap_version(str);
1825 g_string_append(str, ", ");
1826 u3_runtime_info(str);
1832 read_configuration_files(char **gdp_path, char **dp_path)
1834 int gpf_open_errno, gpf_read_errno;
1835 int cf_open_errno, df_open_errno;
1836 int gdp_open_errno, gdp_read_errno;
1837 int dp_open_errno, dp_read_errno;
1838 char *gpf_path, *pf_path;
1839 char *cf_path, *df_path;
1840 int pf_open_errno, pf_read_errno;
1843 /* Read the preference files. */
1844 prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1845 &pf_open_errno, &pf_read_errno, &pf_path);
1847 if (gpf_path != NULL) {
1848 if (gpf_open_errno != 0) {
1849 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1850 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1851 strerror(gpf_open_errno));
1853 if (gpf_read_errno != 0) {
1854 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1855 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1856 strerror(gpf_read_errno));
1859 if (pf_path != NULL) {
1860 if (pf_open_errno != 0) {
1861 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1862 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1863 strerror(pf_open_errno));
1865 if (pf_read_errno != 0) {
1866 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1867 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1868 strerror(pf_read_errno));
1875 /* if the user wants a console to be always there, well, we should open one for him */
1876 if (prefs_p->gui_console_open == console_open_always) {
1881 /* Read the capture filter file. */
1882 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1883 if (cf_path != NULL) {
1884 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1885 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1886 strerror(cf_open_errno));
1890 /* Read the display filter file. */
1891 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1892 if (df_path != NULL) {
1893 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1894 "Could not open your display filter file\n\"%s\": %s.", df_path,
1895 strerror(df_open_errno));
1899 /* Read the disabled protocols file. */
1900 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1901 dp_path, &dp_open_errno, &dp_read_errno);
1902 if (*gdp_path != NULL) {
1903 if (gdp_open_errno != 0) {
1904 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1905 "Could not open global disabled protocols file\n\"%s\": %s.",
1906 *gdp_path, strerror(gdp_open_errno));
1908 if (gdp_read_errno != 0) {
1909 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1910 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1911 *gdp_path, strerror(gdp_read_errno));
1916 if (*dp_path != NULL) {
1917 if (dp_open_errno != 0) {
1918 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1919 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1920 strerror(dp_open_errno));
1922 if (dp_read_errno != 0) {
1923 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1924 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1925 strerror(dp_read_errno));
1934 /* Check if there's something important to tell the user during startup.
1935 * We want to do this *after* showing the main window so that any windows
1936 * we pop up will be above the main window.
1940 check_and_warn_user_startup(gchar *cf_name)
1942 check_and_warn_user_startup(gchar *cf_name _U_)
1945 gchar *cur_user, *cur_group;
1946 gpointer priv_warning_dialog;
1948 /* Tell the user not to run as root. */
1949 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
1950 cur_user = get_cur_username();
1951 cur_group = get_cur_groupname();
1952 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1953 "Running as user \"%s\" and group \"%s\".\n"
1954 "This could be dangerous.", cur_user, cur_group);
1957 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1958 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
1962 /* Warn the user if npf.sys isn't loaded. */
1963 if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
1964 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1965 "The NPF driver isn't running. You may have trouble\n"
1966 "capturing or listing interfaces.");
1967 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1968 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
1975 /* And now our feature presentation... [ fade to music ] */
1977 main(int argc, char *argv[])
1979 char *init_progfile_dir_error;
1982 gboolean arg_error = FALSE;
1984 extern int info_update_freq; /* Found in about_dlg.c. */
1985 const gchar *filter;
1993 char *gdp_path, *dp_path;
1996 gboolean start_capture = FALSE;
1997 gboolean list_link_layer_types = FALSE;
1999 gboolean capture_option_specified = FALSE;
2001 gint pl_size = 280, tv_size = 95, bv_size = 75;
2002 gchar *rc_file, *cf_name = NULL, *rfilter = NULL, *jfilter = NULL;
2003 dfilter_t *rfcode = NULL;
2004 gboolean rfilter_parse_failed = FALSE;
2007 GtkWidget *splash_win = NULL;
2008 GLogLevelFlags log_flags;
2009 guint go_to_packet = 0;
2010 gboolean jump_backwards = FALSE, saved_bw = FALSE;
2011 dfilter_t *jump_to_filter = NULL;
2021 #define OPTSTRING_INIT "a:b:c:C:Df:g:Hhi:jJ:kK:lLm:nN:o:P:pQr:R:Ss:t:vw:X:y:z:"
2023 #if defined HAVE_LIBPCAP && defined _WIN32
2024 #define OPTSTRING_WIN32 "B:"
2026 #define OPTSTRING_WIN32 ""
2029 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
2030 OPTSTRING_INIT OPTSTRING_WIN32;
2033 * Get credential information for later use, and drop privileges
2034 * before doing anything else.
2035 * Let the user know if anything happened.
2037 get_credential_info();
2038 relinquish_special_privs_perm();
2041 * Attempt to get the pathname of the executable file.
2043 init_progfile_dir_error = init_progfile_dir(argv[0], main);
2045 /* initialize the funnel mini-api */
2046 initialize_funnel_ops();
2048 #ifdef HAVE_AIRPDCAP
2049 AirPDcapInitContext(&airpdcap_ctx);
2053 /* Load wpcap if possible. Do this before collecting the run-time version information */
2056 /* ... and also load the packet.dll from wpcap */
2057 wpcap_packet_load();
2060 /* Load the airpcap.dll. This must also be done before collecting
2061 * run-time version information. */
2062 airpcap_dll_ret_val = load_airpcap();
2064 switch (airpcap_dll_ret_val) {
2065 case AIRPCAP_DLL_OK:
2066 /* load the airpcap interfaces */
2067 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2069 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2070 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2071 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2074 airpcap_if_active = NULL;
2078 /* select the first ad default (THIS SHOULD BE CHANGED) */
2079 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2084 * XXX - Maybe we need to warn the user if one of the following happens???
2086 case AIRPCAP_DLL_OLD:
2087 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2090 case AIRPCAP_DLL_ERROR:
2091 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2094 case AIRPCAP_DLL_NOT_FOUND:
2095 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2099 #endif /* HAVE_AIRPCAP */
2101 /* Start windows sockets */
2102 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2105 profile_store_persconffiles (TRUE);
2107 /* Assemble the compile-time version information string */
2108 comp_info_str = g_string_new("Compiled ");
2110 g_string_append(comp_info_str, "with ");
2111 g_string_append_printf(comp_info_str,
2112 #ifdef GTK_MAJOR_VERSION
2113 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
2116 "GTK+ (version unknown)");
2118 g_string_append(comp_info_str, ", ");
2120 get_compiled_version_info(comp_info_str, get_gui_compiled_info);
2122 /* Assemble the run-time version information string */
2123 runtime_info_str = g_string_new("Running ");
2124 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2126 /* Read the profile independent recent file. We have to do this here so we can */
2127 /* set the profile before it can be set from the command line parameterts */
2128 recent_read_static(&rf_path, &rf_open_errno);
2129 if (rf_path != NULL && rf_open_errno != 0) {
2130 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2131 "Could not open common recent file\n\"%s\": %s.",
2132 rf_path, strerror(rf_open_errno));
2135 /* "pre-scan" the command line parameters, if we have "console only"
2136 parameters. We do this so we don't start GTK+ if we're only showing
2137 command-line help or version information.
2139 XXX - this pre-scan is done before we start GTK+, so we haven't
2140 run gtk_init() on the arguments. That means that GTK+ arguments
2141 have not been removed from the argument list; those arguments
2142 begin with "--", and will be treated as an error by getopt().
2144 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2147 optind_initial = optind;
2148 while ((opt = getopt(argc, argv, optstring)) != -1) {
2150 case 'C': /* Configuration Profile */
2151 if (profile_exists (optarg)) {
2152 set_profile_name (optarg);
2154 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2158 case 'h': /* Print help and exit */
2164 if (strcmp(optarg, "-") == 0)
2165 stdin_capture = TRUE;
2168 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2169 status = filesystem_opt(opt, optarg);
2171 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2175 case 'v': /* Show version and exit */
2181 * Extension command line options have to be processed before
2182 * we call epan_init() as they are supposed to be used by dissectors
2183 * or taps very early in the registration process.
2187 case '?': /* Ignore errors - the "real" scan will catch them. */
2192 /* Init the "Open file" dialog directory */
2193 /* (do this after the path settings are processed) */
2194 set_last_open_dir(get_persdatafile_dir());
2196 /* Set getopt index back to initial value, so it will start with the
2197 first command line parameter again. Also reset opterr to 1, so that
2198 error messages are printed by getopt().
2200 XXX - this seems to work on most platforms, but time will tell.
2201 The Single UNIX Specification says "The getopt() function need
2202 not be reentrant", so this isn't guaranteed to work. The Mac
2203 OS X 10.4[.x] getopt() man page says
2205 In order to use getopt() to evaluate multiple sets of arguments, or to
2206 evaluate a single set of arguments multiple times, the variable optreset
2207 must be set to 1 before the second and each additional set of calls to
2208 getopt(), and the variable optind must be reinitialized.
2212 The optreset variable was added to make it possible to call the getopt()
2213 function multiple times. This is an extension to the IEEE Std 1003.2
2214 (``POSIX.2'') specification.
2216 which I think comes from one of the other BSDs.
2218 XXX - if we want to control all the command-line option errors, so
2219 that we can display them where we choose (e.g., in a window), we'd
2220 want to leave opterr as 0, and produce our own messages using optopt.
2221 We'd have to check the value of optopt to see if it's a valid option
2222 letter, in which case *presumably* the error is "this option requires
2223 an argument but none was specified", or not a valid option letter,
2224 in which case *presumably* the error is "this option isn't valid".
2225 Some versions of getopt() let you supply a option string beginning
2226 with ':', which means that getopt() will return ':' rather than '?'
2227 for "this option requires an argument but none was specified", but
2229 optind = optind_initial;
2232 /* Set the current locale according to the program environment.
2233 * We haven't localized anything, but some GTK widgets are localized
2234 * (the file selection dialogue, for example).
2235 * This also sets the C-language locale to the native environment. */
2238 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2239 gtk_init (&argc, &argv);
2241 cf_callback_add(main_cf_callback, NULL);
2243 capture_callback_add(main_capture_callback, NULL);
2245 cf_callback_add(statusbar_cf_callback, NULL);
2247 capture_callback_add(statusbar_capture_callback, NULL);
2250 /* Arrange that if we have no console window, and a GLib message logging
2251 routine is called to log a message, we pop up a console window.
2253 We do that by inserting our own handler for all messages logged
2254 to the default domain; that handler pops up a console if necessary,
2255 and then calls the default handler. */
2257 /* We might want to have component specific log levels later ... */
2261 G_LOG_LEVEL_CRITICAL|
2262 G_LOG_LEVEL_WARNING|
2263 G_LOG_LEVEL_MESSAGE|
2266 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2268 g_log_set_handler(NULL,
2270 console_log_handler, NULL /* user_data */);
2271 g_log_set_handler(LOG_DOMAIN_MAIN,
2273 console_log_handler, NULL /* user_data */);
2276 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2278 console_log_handler, NULL /* user_data */);
2279 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2281 console_log_handler, NULL /* user_data */);
2283 /* Set the initial values in the capture options. This might be overwritten
2284 by preference settings and then again by the command line parameters. */
2285 capture_opts_init(&global_capture_opts, &cfile);
2287 global_capture_opts.snaplen = MIN_PACKET_SIZE;
2288 global_capture_opts.has_ring_num_files = TRUE;
2291 /* Initialize whatever we need to allocate colors for GTK+ */
2294 /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2295 filter = get_conn_cfilter();
2296 if ( *filter != '\0' ) {
2297 info_update_freq = 1000; /* Milliseconds */
2300 /* We won't come till here, if we had a "console only" command line parameter. */
2301 splash_win = splash_new("Loading Wireshark ...");
2302 if (init_progfile_dir_error != NULL) {
2303 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2304 "Can't get pathname of Wireshark: %s.\n"
2305 "It won't be possible to capture traffic.\n"
2306 "Report this to the Wireshark developers.",
2307 init_progfile_dir_error);
2308 g_free(init_progfile_dir_error);
2311 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2313 /* Register all dissectors; we must do this before checking for the
2314 "-G" flag, as the "-G" flag dumps information registered by the
2315 dissectors, and we must do it before we read the preferences, in
2316 case any dissectors register preferences. */
2317 epan_init(register_all_protocols,register_all_protocol_handoffs,
2318 splash_update, (gpointer) splash_win,
2319 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2320 write_failure_alert_box);
2322 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2324 /* Register all tap listeners; we do this before we parse the arguments,
2325 as the "-z" argument can specify a registered tap. */
2327 /* we register the plugin taps before the other taps because
2328 stats_tree taps plugins will be registered as tap listeners
2329 by stats_tree_stat.c and need to registered before that */
2332 register_all_plugin_tap_listeners();
2335 register_all_tap_listeners();
2337 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2339 /* Now register the preferences for any non-dissector modules.
2340 We must do that before we read the preferences as well. */
2341 prefs_register_modules();
2343 prefs_p = read_configuration_files (&gdp_path, &dp_path);
2345 /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2346 #if !defined(_WIN32) && defined(G_THREADS_ENABLED) && defined USE_THREADS
2349 g_thread_init(NULL);
2351 ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2352 g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2354 #else /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2355 /* this is to keep tap extensions updating once every 3 seconds */
2356 tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2357 #endif /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2359 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2362 /* Read the profile dependent (static part) of the recent file. */
2363 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2364 /* recent lists which is done in the dynamic part. */
2365 /* We have to do this already here, so command line parameters can overwrite these values. */
2366 recent_read_profile_static(&rf_path, &rf_open_errno);
2367 if (rf_path != NULL && rf_open_errno != 0) {
2368 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2369 "Could not open recent file\n\"%s\": %s.",
2370 rf_path, strerror(rf_open_errno));
2373 cap_file_init(&cfile);
2375 /* Fill in capture options with values from the preferences */
2376 prefs_to_capture_opts();
2378 /* Now get our args */
2379 while ((opt = getopt(argc, argv, optstring)) != -1) {
2381 /*** capture option specific ***/
2382 case 'a': /* autostop criteria */
2383 case 'b': /* Ringbuffer option */
2384 case 'c': /* Capture xxx packets */
2385 case 'f': /* capture filter */
2386 case 'k': /* Start capture immediately */
2387 case 'H': /* Hide capture info dialog box */
2388 case 'i': /* Use interface xxx */
2389 case 'p': /* Don't capture in promiscuous mode */
2390 case 'Q': /* Quit after capture (just capture to file) */
2391 case 's': /* Set the snapshot (capture) length */
2392 case 'S': /* "Sync" mode: used for following file ala tail -f */
2393 case 'w': /* Write to capture file xxx */
2394 case 'y': /* Set the pcap data link type */
2396 case 'B': /* Buffer size */
2399 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2405 capture_option_specified = TRUE;
2410 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2411 case 'K': /* Kerberos keytab file */
2412 read_keytab_file(optarg);
2416 /*** all non capture option specific ***/
2418 /* Configuration profile settings were already processed just ignore them this time*/
2420 case 'D': /* Print a list of capture devices and exit */
2422 capture_opts_list_interfaces(FALSE);
2425 capture_option_specified = TRUE;
2429 case 'j': /* Search backwards for a matching packet from filter in option J */
2430 jump_backwards = TRUE;
2432 case 'g': /* Go to packet with the given packet number */
2433 go_to_packet = get_positive_int(optarg, "go to packet");
2435 case 'J': /* Jump to the first packet which matches the filter criteria */
2438 case 'l': /* Automatic scrolling in live capture mode */
2440 auto_scroll_live = TRUE;
2442 capture_option_specified = TRUE;
2446 case 'L': /* Print list of link-layer types and exit */
2448 list_link_layer_types = TRUE;
2450 capture_option_specified = TRUE;
2454 case 'm': /* Fixed-width font for the display */
2455 g_free(prefs_p->gui_font_name);
2456 prefs_p->gui_font_name = g_strdup(optarg);
2458 case 'n': /* No name resolution */
2459 g_resolv_flags = RESOLV_NONE;
2461 case 'N': /* Select what types of addresses/port #s to resolve */
2462 if (g_resolv_flags == RESOLV_ALL)
2463 g_resolv_flags = RESOLV_NONE;
2464 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2465 if (badopt != '\0') {
2466 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2471 case 'o': /* Override preference from command line */
2472 switch (prefs_set_pref(optarg)) {
2475 case PREFS_SET_SYNTAX_ERR:
2476 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2479 case PREFS_SET_NO_SUCH_PREF:
2480 /* not a preference, might be a recent setting */
2481 switch (recent_set_arg(optarg)) {
2484 case PREFS_SET_SYNTAX_ERR:
2485 /* shouldn't happen, checked already above */
2486 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2489 case PREFS_SET_NO_SUCH_PREF:
2490 case PREFS_SET_OBSOLETE:
2491 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2496 g_assert_not_reached();
2499 case PREFS_SET_OBSOLETE:
2500 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2505 g_assert_not_reached();
2509 /* Path settings were already processed just ignore them this time*/
2511 case 'r': /* Read capture file xxx */
2512 /* We may set "last_open_dir" to "cf_name", and if we change
2513 "last_open_dir" later, we free the old value, so we have to
2514 set "cf_name" to something that's been allocated. */
2515 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2516 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2517 cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2519 cf_name = g_strdup(optarg);
2522 case 'R': /* Read file filter */
2525 case 't': /* Time stamp type */
2526 if (strcmp(optarg, "r") == 0)
2527 timestamp_set_type(TS_RELATIVE);
2528 else if (strcmp(optarg, "a") == 0)
2529 timestamp_set_type(TS_ABSOLUTE);
2530 else if (strcmp(optarg, "ad") == 0)
2531 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2532 else if (strcmp(optarg, "d") == 0)
2533 timestamp_set_type(TS_DELTA);
2534 else if (strcmp(optarg, "dd") == 0)
2535 timestamp_set_type(TS_DELTA_DIS);
2536 else if (strcmp(optarg, "e") == 0)
2537 timestamp_set_type(TS_EPOCH);
2539 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2540 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2541 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2546 /* ext ops were already processed just ignore them this time*/
2549 /* We won't call the init function for the stat this soon
2550 as it would disallow MATE's fields (which are registered
2551 by the preferences set callback) from being used as
2552 part of a tap filter. Instead, we just add the argument
2553 to a list of stat arguments. */
2554 if (!process_stat_cmd_arg(optarg)) {
2555 cmdarg_err("Invalid -z argument.");
2556 cmdarg_err_cont(" -z argument must be one of :");
2557 list_stat_cmd_args();
2562 case '?': /* Bad flag - print usage message */
2570 if (cf_name != NULL) {
2572 * Input file name specified with "-r" *and* specified as a regular
2573 * command-line argument.
2575 cmdarg_err("File name specified both with -r and regular argument");
2579 * Input file name not specified with "-r", and a command-line argument
2580 * was specified; treat it as the input file name.
2582 * Yes, this is different from tshark, where non-flag command-line
2583 * arguments are a filter, but this works better on GUI desktops
2584 * where a command can be specified to be run to open a particular
2585 * file - yes, you could have "-r" as the last part of the command,
2586 * but that's a bit ugly.
2588 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2589 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2590 cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2592 cf_name = g_strdup(argv[0]);
2603 * Extra command line arguments were specified; complain.
2605 cmdarg_err("Invalid argument: %s", argv[0]);
2610 #ifndef HAVE_LIBPCAP
2611 if (capture_option_specified) {
2612 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2620 if (start_capture && list_link_layer_types) {
2621 /* Specifying *both* is bogus. */
2622 cmdarg_err("You can't specify both -L and a live capture.");
2626 if (list_link_layer_types) {
2627 /* We're supposed to list the link-layer types for an interface;
2628 did the user also specify a capture file to be read? */
2630 /* Yes - that's bogus. */
2631 cmdarg_err("You can't specify -L and a capture file to be read.");
2634 /* No - did they specify a ring buffer option? */
2635 if (global_capture_opts.multi_files_on) {
2636 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2640 /* We're supposed to do a live capture; did the user also specify
2641 a capture file to be read? */
2642 if (start_capture && cf_name) {
2643 /* Yes - that's bogus. */
2644 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2648 /* No - was the ring buffer option specified and, if so, does it make
2650 if (global_capture_opts.multi_files_on) {
2651 /* Ring buffer works only under certain conditions:
2652 a) ring buffer does not work with temporary files;
2653 b) real_time_mode and multi_files_on are mutually exclusive -
2654 real_time_mode takes precedence;
2655 c) it makes no sense to enable the ring buffer if the maximum
2656 file size is set to "infinite". */
2657 if (global_capture_opts.save_file == NULL) {
2658 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2659 global_capture_opts.multi_files_on = FALSE;
2661 /* if (global_capture_opts.real_time_mode) {
2662 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2663 global_capture_opts.multi_files_on = FALSE;
2665 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2666 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2667 /* XXX - this must be redesigned as the conditions changed */
2668 /* global_capture_opts.multi_files_on = FALSE;*/
2673 if (start_capture || list_link_layer_types) {
2674 /* Did the user specify an interface to use? */
2675 if (!capture_opts_trim_iface(&global_capture_opts,
2676 (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2681 if (list_link_layer_types) {
2682 status = capture_opts_list_link_layer_types(&global_capture_opts, FALSE);
2686 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2687 capture_opts_trim_ring_num_files(&global_capture_opts);
2688 #endif /* HAVE_LIBPCAP */
2690 /* Notify all registered modules that have had any of their preferences
2691 changed either from one of the preferences file or from the command
2692 line that their preferences have changed. */
2695 /* disabled protocols as per configuration file */
2696 if (gdp_path == NULL && dp_path == NULL) {
2697 set_disabled_protos_list();
2700 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2702 /* read in rc file from global and personal configuration paths. */
2703 rc_file = get_datafile_path(RC_FILE);
2704 gtk_rc_parse(rc_file);
2706 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2707 gtk_rc_parse(rc_file);
2714 /* close the splash screen, as we are going to open the main window now */
2715 splash_destroy(splash_win);
2717 /************************************************************************/
2718 /* Everything is prepared now, preferences and command line was read in */
2720 /* Pop up the main window. */
2721 create_main_window(pl_size, tv_size, bv_size, prefs_p);
2723 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2724 recent_read_dynamic(&rf_path, &rf_open_errno);
2725 if (rf_path != NULL && rf_open_errno != 0) {
2726 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2727 "Could not open recent file\n\"%s\": %s.",
2728 rf_path, strerror(rf_open_errno));
2731 color_filters_enable(recent.packet_list_colorize);
2733 /* rearrange all the widgets as we now have all recent settings ready for this */
2734 main_widgets_rearrange();
2736 /* Fill in column titles. This must be done after the top level window
2739 XXX - is that still true, with fixed-width columns? */
2740 #ifndef NEW_PACKET_LIST
2741 packet_list_set_column_titles();
2744 menu_recent_read_finished();
2746 menu_auto_scroll_live_changed(auto_scroll_live);
2749 switch (user_font_apply()) {
2752 case FA_FONT_NOT_RESIZEABLE:
2753 /* "user_font_apply()" popped up an alert box. */
2754 /* turn off zooming - font can't be resized */
2755 case FA_FONT_NOT_AVAILABLE:
2756 /* XXX - did we successfully load the un-zoomed version earlier?
2757 If so, this *probably* means the font is available, but not at
2758 this particular zoom level, but perhaps some other failure
2759 occurred; I'm not sure you can determine which is the case,
2761 /* turn off zooming - zoom level is unavailable */
2763 /* in any other case than FA_SUCCESS, turn off zooming */
2764 recent.gui_zoom_level = 0;
2765 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2768 dnd_init(top_level);
2770 color_filters_init();
2773 /* the window can be sized only, if it's not already shown, so do it now! */
2774 main_load_window_geometry(top_level);
2776 g_timeout_add(info_update_freq, resolv_update_cb, NULL);
2779 /* If we were given the name of a capture file, read it in now;
2780 we defer it until now, so that, if we can't open it, and pop
2781 up an alert box, the alert box is more likely to come up on
2782 top of the main window - but before the preference-file-error
2783 alert box, so, if we get one of those, it's more likely to come
2786 show_main_window(TRUE);
2787 check_and_warn_user_startup(cf_name);
2788 if (rfilter != NULL) {
2789 if (!dfilter_compile(rfilter, &rfcode)) {
2790 bad_dfilter_alert_box(rfilter);
2791 rfilter_parse_failed = TRUE;
2794 if (!rfilter_parse_failed) {
2795 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2796 /* "cf_open()" succeeded, so it closed the previous
2797 capture file, and thus destroyed any previous read filter
2798 attached to "cf". */
2800 cfile.rfcode = rfcode;
2801 /* Open stat windows; we do so after creating the main window,
2802 to avoid GTK warnings, and after successfully opening the
2803 capture file, so we know we have something to compute stats
2804 on, and after registering all dissectors, so that MATE will
2805 have registered its field array and we can have a tap filter
2806 with one of MATE's late-registered fields as part of the
2808 start_requested_stats();
2810 /* Read the capture file. */
2811 switch (cf_read(&cfile, FALSE)) {
2815 /* Just because we got an error, that doesn't mean we were unable
2816 to read any of the file; we handle what we could get from the
2818 /* if the user told us to jump to a specific packet, do it now */
2819 if(go_to_packet != 0) {
2820 /* Jump to the specified frame number, kept for backward
2822 cf_goto_frame(&cfile, go_to_packet);
2823 } else if (jfilter != NULL) {
2824 /* try to compile given filter */
2825 if (!dfilter_compile(jfilter, &jump_to_filter)) {
2826 bad_dfilter_alert_box(jfilter);
2829 /* Filter ok, jump to the first packet matching the filter
2830 conditions. Default search direction is forward, but if
2831 option d was given, search backwards */
2832 saved_bw = cfile.sbackward;
2833 cfile.sbackward = jump_backwards;
2834 cf_find_packet_dfilter(&cfile, jump_to_filter);
2835 cfile.sbackward = saved_bw;
2840 case CF_READ_ABORTED:
2845 /* Save the name of the containing directory specified in the
2846 path name, if any; we can write over cf_name, which is a
2847 good thing, given that "get_dirname()" does write over its
2849 s = get_dirname(cf_name);
2850 set_last_open_dir(s);
2855 dfilter_free(rfcode);
2856 cfile.rfcode = NULL;
2857 show_main_window(FALSE);
2858 /* Don't call check_and_warn_user_startup(): we did it above */
2859 set_menus_for_capture_in_progress(FALSE);
2860 set_capture_if_dialog_for_capture_in_progress(FALSE);
2865 if (start_capture) {
2866 if (global_capture_opts.save_file != NULL) {
2867 /* Save the directory name for future file dialogs. */
2868 /* (get_dirname overwrites filename) */
2869 s = get_dirname(g_strdup(global_capture_opts.save_file));
2870 set_last_open_dir(s);
2873 /* "-k" was specified; start a capture. */
2874 show_main_window(TRUE);
2875 check_and_warn_user_startup(cf_name);
2876 if (capture_start(&global_capture_opts)) {
2877 /* The capture started. Open stat windows; we do so after creating
2878 the main window, to avoid GTK warnings, and after successfully
2879 opening the capture file, so we know we have something to compute
2880 stats on, and after registering all dissectors, so that MATE will
2881 have registered its field array and we can have a tap filter with
2882 one of MATE's late-registered fields as part of the filter. */
2883 start_requested_stats();
2887 show_main_window(FALSE);
2888 check_and_warn_user_startup(cf_name);
2889 set_menus_for_capture_in_progress(FALSE);
2890 set_capture_if_dialog_for_capture_in_progress(FALSE);
2893 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2894 if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2895 g_free(global_capture_opts.cfilter);
2896 global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2898 #else /* HAVE_LIBPCAP */
2899 show_main_window(FALSE);
2900 check_and_warn_user_startup(cf_name);
2901 set_menus_for_capture_in_progress(FALSE);
2902 set_capture_if_dialog_for_capture_in_progress(FALSE);
2903 #endif /* HAVE_LIBPCAP */
2906 /* register our pid if we are being run from a U3 device */
2909 profile_store_persconffiles (FALSE);
2911 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
2913 /* we'll enter the GTK loop now and hand the control over to GTK ... */
2915 /* ... back from GTK, we're going down now! */
2917 /* deregister our pid */
2918 u3_deregister_pid();
2922 #ifdef HAVE_AIRPDCAP
2923 AirPDcapDestroyContext(&airpdcap_ctx);
2927 /* hide the (unresponsive) main window, while asking the user to close the console window */
2928 gtk_widget_hide(top_level);
2930 /* Shutdown windows sockets */
2933 /* For some unknown reason, the "atexit()" call in "create_console()"
2934 doesn't arrange that "destroy_console()" be called when we exit,
2935 so we call it here if a console was created. */
2944 /* We build this as a GUI subsystem application on Win32, so
2945 "WinMain()", not "main()", gets called.
2947 Hack shamelessly stolen from the Win32 port of the GIMP. */
2949 #define _stdcall __attribute__((stdcall))
2953 WinMain (struct HINSTANCE__ *hInstance,
2954 struct HINSTANCE__ *hPrevInstance,
2958 INITCOMMONCONTROLSEX comm_ctrl;
2960 /* Initialize our controls. Required for native Windows file dialogs. */
2961 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
2962 comm_ctrl.dwSize = sizeof(comm_ctrl);
2963 /* Includes the animate, header, hot key, list view, progress bar,
2964 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
2967 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
2968 InitCommonControlsEx(&comm_ctrl);
2970 /* RichEd20.DLL is needed for filter entries. */
2971 LoadLibrary(_T("riched20.dll"));
2973 has_console = FALSE;
2974 return main (__argc, __argv);
2977 /* The code to create and desstroy console windows should not be necessary,
2978 at least as I read the GLib source code, as it looks as if GLib is, on
2979 Win32, *supposed* to create a console window into which to display its
2982 That doesn't happen, however. I suspect there's something completely
2983 broken about that code in GLib-for-Win32, and that it may be related
2984 to the breakage that forces us to just call "printf()" on the message
2985 rather than passing the message on to "g_log_default_handler()"
2986 (which is the routine that does the aforementioned non-functional
2987 console window creation). */
2990 * If this application has no console window to which its standard output
2991 * would go, create one.
2994 create_console(void)
2996 if (stdin_capture) {
2997 /* We've been handed "-i -". Don't mess with stdio. */
3002 /* We have no console to which to print the version string, so
3003 create one and make it the standard input, output, and error. */
3004 if (!AllocConsole())
3005 return; /* couldn't create console */
3007 ws_freopen("CONIN$", "r", stdin);
3008 ws_freopen("CONOUT$", "w", stdout);
3009 ws_freopen("CONOUT$", "w", stderr);
3011 /* Well, we have a console now. */
3014 /* Now register "destroy_console()" as a routine to be called just
3015 before the application exits, so that we can destroy the console
3016 after the user has typed a key (so that the console doesn't just
3017 disappear out from under them, giving the user no chance to see
3018 the message(s) we put in there). */
3019 atexit(destroy_console);
3021 SetConsoleTitle(_T("Wireshark Debug Console"));
3026 destroy_console(void)
3029 printf("\n\nPress any key to exit\n");
3038 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3039 const char *message, gpointer user_data _U_)
3046 /* ignore log message, if log_level isn't interesting based
3047 upon the console log preferences.
3048 If the preferences haven't been loaded loaded yet, display the
3051 The default console_log_level preference value is such that only
3052 ERROR, CRITICAL and WARNING level messages are processed;
3053 MESSAGE, INFO and DEBUG level messages are ignored. */
3054 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3055 prefs.console_log_level != 0) {
3060 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3061 /* the user wants a console or the application will terminate immediately */
3065 /* For some unknown reason, the above doesn't appear to actually cause
3066 anything to be sent to the standard output, so we'll just splat the
3067 message out directly, just to make sure it gets out. */
3069 switch(log_level & G_LOG_LEVEL_MASK) {
3070 case G_LOG_LEVEL_ERROR:
3073 case G_LOG_LEVEL_CRITICAL:
3076 case G_LOG_LEVEL_WARNING:
3079 case G_LOG_LEVEL_MESSAGE:
3082 case G_LOG_LEVEL_INFO:
3085 case G_LOG_LEVEL_DEBUG:
3089 fprintf(stderr, "unknown log_level %u\n", log_level);
3091 g_assert_not_reached();
3094 /* create a "timestamp" */
3096 today = localtime(&curr);
3098 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3099 today->tm_hour, today->tm_min, today->tm_sec,
3100 log_domain != NULL ? log_domain : "",
3103 if(log_level & G_LOG_LEVEL_ERROR) {
3104 /* wait for a key press before the following error handler will terminate the program
3105 this way the user at least can read the error message */
3106 printf("\n\nPress any key to exit\n");
3110 /* XXX - on UN*X, should we just use g_log_default_handler()?
3111 We want the error messages to go to the standard output;
3112 on Mac OS X, that will cause them to show up in various
3113 per-user logs accessible through Console (details depend
3114 on whether you're running 10.0 through 10.4 or running
3115 10.5 and later), and, on other UN*X desktop environments,
3116 if they don't show up in some form of console log, that's
3117 a deficiency in that desktop environment. (Too bad
3118 Windows doesn't set the standard output and error for
3119 GUI apps to something that shows up in such a log.) */
3120 g_log_default_handler(log_domain, log_level, message, user_data);
3127 * Helper for main_widgets_rearrange()
3129 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3130 gtk_container_remove(GTK_CONTAINER(data), widget);
3133 static GtkWidget *main_widget_layout(gint layout_content)
3135 switch(layout_content) {
3136 case(layout_pane_content_none):
3138 case(layout_pane_content_plist):
3140 case(layout_pane_content_pdetails):
3142 case(layout_pane_content_pbytes):
3143 return byte_nb_ptr_gbl;
3145 g_assert_not_reached();
3152 * Rearrange the main window widgets
3154 void main_widgets_rearrange(void) {
3155 GtkWidget *first_pane_widget1, *first_pane_widget2;
3156 GtkWidget *second_pane_widget1, *second_pane_widget2;
3157 gboolean split_top_left;
3159 /* be a bit faster */
3160 gtk_widget_hide(main_vbox);
3162 /* be sure we don't lose a widget while rearranging */
3163 g_object_ref(G_OBJECT(menubar));
3164 g_object_ref(G_OBJECT(main_tb));
3165 g_object_ref(G_OBJECT(filter_tb));
3167 g_object_ref(G_OBJECT(airpcap_tb));
3169 g_object_ref(G_OBJECT(pkt_scrollw));
3170 g_object_ref(G_OBJECT(tv_scrollw));
3171 g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3172 g_object_ref(G_OBJECT(statusbar));
3173 g_object_ref(G_OBJECT(main_pane_v1));
3174 g_object_ref(G_OBJECT(main_pane_v2));
3175 g_object_ref(G_OBJECT(main_pane_h1));
3176 g_object_ref(G_OBJECT(main_pane_h2));
3177 g_object_ref(G_OBJECT(welcome_pane));
3179 /* empty all containers participating */
3180 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3181 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3182 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3183 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3184 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3186 statusbar_widgets_emptying(statusbar);
3188 /* add the menubar always at the top */
3189 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3192 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3194 /* filter toolbar in toolbar area */
3195 if (!prefs.filter_toolbar_show_in_statusbar) {
3196 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3200 /* airpcap toolbar */
3201 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3204 /* fill the main layout panes */
3205 switch(prefs.gui_layout_type) {
3206 case(layout_type_5):
3207 main_first_pane = main_pane_v1;
3208 main_second_pane = main_pane_v2;
3209 split_top_left = FALSE;
3211 case(layout_type_2):
3212 main_first_pane = main_pane_v1;
3213 main_second_pane = main_pane_h1;
3214 split_top_left = FALSE;
3216 case(layout_type_1):
3217 main_first_pane = main_pane_v1;
3218 main_second_pane = main_pane_h1;
3219 split_top_left = TRUE;
3221 case(layout_type_4):
3222 main_first_pane = main_pane_h1;
3223 main_second_pane = main_pane_v1;
3224 split_top_left = FALSE;
3226 case(layout_type_3):
3227 main_first_pane = main_pane_h1;
3228 main_second_pane = main_pane_v1;
3229 split_top_left = TRUE;
3231 case(layout_type_6):
3232 main_first_pane = main_pane_h1;
3233 main_second_pane = main_pane_h2;
3234 split_top_left = FALSE;
3237 main_first_pane = NULL;
3238 main_second_pane = NULL;
3239 split_top_left = FALSE;
3240 g_assert_not_reached();
3242 if (split_top_left) {
3243 first_pane_widget1 = main_second_pane;
3244 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3245 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3246 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3248 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3249 first_pane_widget2 = main_second_pane;
3250 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3251 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3253 if (first_pane_widget1 != NULL)
3254 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3255 if (first_pane_widget2 != NULL)
3256 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3257 if (second_pane_widget1 != NULL)
3258 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3259 if (second_pane_widget2 != NULL)
3260 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3262 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3265 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3268 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3270 /* filter toolbar in statusbar hbox */
3271 if (prefs.filter_toolbar_show_in_statusbar) {
3272 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3276 /* airpcap toolbar */
3277 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3280 /* statusbar widgets */
3281 statusbar_widgets_pack(statusbar);
3283 /* hide widgets on users recent settings */
3284 main_widgets_show_or_hide();
3286 gtk_widget_show(main_vbox);
3290 is_widget_visible(GtkWidget *widget, gpointer data)
3292 gboolean *is_visible = data;
3295 if (GTK_WIDGET_VISIBLE(widget))
3302 main_widgets_show_or_hide(void)
3304 gboolean main_second_pane_show;
3306 if (recent.main_toolbar_show) {
3307 gtk_widget_show(main_tb);
3309 gtk_widget_hide(main_tb);
3312 statusbar_widgets_show_or_hide(statusbar);
3314 if (recent.filter_toolbar_show) {
3315 gtk_widget_show(filter_tb);
3317 gtk_widget_hide(filter_tb);
3321 if (recent.airpcap_toolbar_show) {
3322 gtk_widget_show(airpcap_tb);
3324 gtk_widget_hide(airpcap_tb);
3328 if (recent.packet_list_show && have_capture_file) {
3329 gtk_widget_show(pkt_scrollw);
3331 gtk_widget_hide(pkt_scrollw);
3334 if (recent.tree_view_show && have_capture_file) {
3335 gtk_widget_show(tv_scrollw);
3337 gtk_widget_hide(tv_scrollw);
3340 if (recent.byte_view_show && have_capture_file) {
3341 gtk_widget_show(byte_nb_ptr_gbl);
3343 gtk_widget_hide(byte_nb_ptr_gbl);
3346 if (have_capture_file) {
3347 gtk_widget_show(main_first_pane);
3349 gtk_widget_hide(main_first_pane);
3353 * Is anything in "main_second_pane" visible?
3354 * If so, show it, otherwise hide it.
3356 main_second_pane_show = FALSE;
3357 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3358 &main_second_pane_show);
3359 if (main_second_pane_show) {
3360 gtk_widget_show(main_second_pane);
3362 gtk_widget_hide(main_second_pane);
3365 if (!have_capture_file) {
3367 gtk_widget_show(welcome_pane);
3370 gtk_widget_hide(welcome_pane);
3373 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3374 #ifndef NEW_PACKET_LIST
3375 packet_list_freeze ();
3376 packet_list_thaw ();
3381 /* called, when the window state changes (minimized, maximized, ...) */
3383 window_state_event_cb (GtkWidget *widget _U_,
3387 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3389 if( (event->type) == (GDK_WINDOW_STATE)) {
3390 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3391 /* we might have dialogs popped up while we where iconified,
3393 display_queued_messages();
3401 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3403 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3405 if (event->keyval == GDK_F8) {
3406 #ifdef NEW_PACKET_LIST
3407 new_packet_list_next();
3412 } else if (event->keyval == GDK_F7) {
3413 #ifdef NEW_PACKET_LIST
3414 new_packet_list_prev();
3419 } else if (event->state & NO_SHIFT_MOD_MASK) {
3420 return FALSE; /* Skip control, alt, and other modifiers */
3422 * A comment in gdkkeysyms.h says that it's autogenerated from
3423 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3424 * don't explicitly say so, isprint() should work as expected
3427 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3428 /* Forward the keypress on to the display filter entry */
3429 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3430 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3431 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3439 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3441 GtkAccelGroup *accel;
3444 /* use user-defined title if preference is set */
3445 title = create_user_window_title("The Wireshark Network Analyzer");
3448 top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
3451 gtk_widget_set_name(top_level, "main window");
3452 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3454 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3455 G_CALLBACK(window_state_event_cb), NULL);
3456 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3457 G_CALLBACK(top_level_key_pressed_cb), NULL );
3459 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3460 main_vbox = gtk_vbox_new(FALSE, 1);
3461 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
3462 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3463 gtk_widget_show(main_vbox);
3466 menubar = main_menu_new(&accel);
3468 #ifdef HAVE_IGE_MAC_INTEGRATION
3469 /* MacOS X native menus are created and displayed by main_menu_new() */
3470 if(!prefs_p->gui_macosx_style) {
3472 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3473 gtk_widget_show(menubar);
3474 #ifdef HAVE_IGE_MAC_INTEGRATION
3479 main_tb = toolbar_new();
3480 gtk_widget_show (main_tb);
3482 /* Filter toolbar */
3483 filter_tb = filter_toolbar_new();
3486 #ifdef NEW_PACKET_LIST
3487 pkt_scrollw = new_packet_list_create();
3488 gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3489 gtk_widget_show_all(pkt_scrollw);
3491 pkt_scrollw = packet_list_new(prefs_p);
3492 gtk_widget_set_size_request(packet_list, -1, pl_size);
3493 gtk_widget_show(pkt_scrollw);
3497 tv_scrollw = main_tree_view_new(prefs_p, &tree_view_gbl);
3498 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3499 gtk_widget_show(tv_scrollw);
3501 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3502 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3503 g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3504 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3505 gtk_widget_show(tree_view_gbl);
3508 byte_nb_ptr_gbl = byte_view_new();
3509 gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3510 gtk_widget_show(byte_nb_ptr_gbl);
3512 g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3513 g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3515 /* Panes for the packet list, tree, and byte view */
3516 main_pane_v1 = gtk_vpaned_new();
3517 gtk_widget_show(main_pane_v1);
3518 main_pane_v2 = gtk_vpaned_new();
3519 gtk_widget_show(main_pane_v2);
3520 main_pane_h1 = gtk_hpaned_new();
3521 gtk_widget_show(main_pane_h1);
3522 main_pane_h2 = gtk_hpaned_new();
3523 gtk_widget_show(main_pane_h2);
3525 airpcap_tb = airpcap_toolbar_new();
3526 gtk_widget_show(airpcap_tb);
3529 statusbar = statusbar_new();
3530 gtk_widget_show(statusbar);
3532 /* Pane for the welcome screen */
3533 welcome_pane = welcome_new();
3534 gtk_widget_show(welcome_pane);
3538 show_main_window(gboolean doing_work)
3540 main_set_for_capture_file(doing_work);
3542 /*** we have finished all init things, show the main window ***/
3543 gtk_widget_show(top_level);
3545 /* the window can be maximized only, if it's visible, so do it after show! */
3546 main_load_window_geometry(top_level);
3548 /* process all pending GUI events before continue */
3549 while (gtk_events_pending()) gtk_main_iteration();
3551 /* Pop up any queued-up alert boxes. */
3552 display_queued_messages();
3554 /* Move the main window to the front, in case it isn't already there */
3555 gdk_window_raise(top_level->window);
3558 airpcap_toolbar_show(airpcap_tb);
3559 #endif /* HAVE_AIRPCAP */
3562 /* Fill in capture options with values from the preferences */
3564 prefs_to_capture_opts(void)
3567 /* Set promiscuous mode from the preferences setting. */
3568 /* the same applies to other preferences settings as well. */
3569 global_capture_opts.promisc_mode = prefs.capture_prom_mode;
3570 global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
3571 global_capture_opts.show_info = prefs.capture_show_info;
3572 global_capture_opts.real_time_mode = prefs.capture_real_time;
3573 auto_scroll_live = prefs.capture_auto_scroll;
3574 #endif /* HAVE_LIBPCAP */
3576 /* Set the name resolution code's flags from the preferences. */
3577 g_resolv_flags = prefs.name_resolve;
3581 /* Change configuration profile */
3582 void change_configuration_profile (const gchar *profile_name)
3584 char *gdp_path, *dp_path;
3588 /* First check if profile exists */
3589 if (!profile_exists(profile_name)) {
3593 /* Get the current geometry, before writing it to disk */
3594 main_save_window_geometry(top_level);
3596 if (profile_exists(get_profile_name())) {
3597 /* Write recent file for profile we are leaving, if it still exists */
3598 write_profile_recent();
3601 /* Set profile name and update the status bar */
3602 set_profile_name (profile_name);
3603 profile_bar_update ();
3605 /* Reset current preferences and apply the new */
3609 (void) read_configuration_files (&gdp_path, &dp_path);
3611 recent_read_profile_static(&rf_path, &rf_open_errno);
3612 if (rf_path != NULL && rf_open_errno != 0) {
3613 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3614 "Could not open common recent file\n\"%s\": %s.",
3615 rf_path, strerror(rf_open_errno));
3617 timestamp_set_type (recent.gui_time_format);
3618 color_filters_enable(recent.packet_list_colorize);
3620 prefs_to_capture_opts();
3623 /* Update window view and redraw the toolbar */
3624 update_main_window_name();
3625 toolbar_redraw_all();
3627 /* Enable all protocols and disable from the disabled list */
3629 if (gdp_path == NULL && dp_path == NULL) {
3630 set_disabled_protos_list();
3633 /* Reload color filters */
3634 color_filters_reload();
3636 /* Reload list of interfaces on welcome page */
3637 welcome_if_panel_reload();
3639 /* Recreate the packet list according to new preferences */
3640 #ifdef NEW_PACKET_LIST
3641 new_packet_list_recreate ();
3643 packet_list_recreate ();
3645 cfile.cinfo.columns_changed = FALSE; /* Reset value */
3648 /* Update menus with new recent values */
3649 menu_recent_read_finished();
3651 /* Reload pane geometry, must be done after recreating the list */
3652 main_pane_load_window_geometry();
3655 /** redissect packets and update UI */
3656 void redissect_packets(void)
3658 cf_redissect_packets(&cfile);
3659 status_expert_update();